Fabric.js - 添加鼠标右键点击事件响应(附:右键菜单)
Fabric.js 的 Canvas 有个 mouse:down 事件,通过它我们可以监听到鼠标按下的行为。不过该事件只对鼠标左键其作用,如果是右键按下则不会触发该事件。
而 Canvas 上又无法直接监听 contextmenu 事件,所以想要实现右键点击响应就需要换种方式实现。
1,实现原理
- Fabric.js 的 Canvas 初始化完毕后,会自动在其上方覆盖一个 class 名为 upper-canvas 的 canvas。
- 我们可以在上层这个 canvas 上添加 contextmenu 事件监听。当右键按下时会触发该事件,然后将点击的坐标转换成底下实际的 canvas 里的坐标(坐标需要转换是因为下面 canvas 可能会被移动,缩放)。
2,效果图
- 默认情况下,鼠标左键点击对象即可选择中该对象。
- 这里增加个右键选中功能,即通过右键同样可以选中对象。
3,样例代码
<!DOCTYPE html> <html> <head> <style> canvas { border: 1px dashed black; } </style> <script src="fabric.js"></script> <script src="jquery-3.1.1.js"></script> <script> var canvas; window.onload = function() { canvas = new fabric.Canvas('canvas'); var rect1 = new fabric.Rect({top: 50, left: 50, width: 70, height: 70, fill: 'red'}); canvas.add(rect1); var rect2 = new fabric.Rect({top: 50, left: 150, width: 70, height: 70, fill: 'red'}); canvas.add(rect2); var rect3 = new fabric.Rect({top: 50, left: 250, width: 70, height: 70, fill: 'red'}); canvas.add(rect3); //在canvas上层对象上添加右键事件监听 $(".upper-canvas").contextmenu(onContextmenu); } //右键点击事件响应 var onContextmenu = function(event) { var pointer = canvas.getPointer(event.originalEvent); var objects = canvas.getObjects(); for (var i = objects.length - 1; i >= 0; i--) { var object = objects[i]; //判断该对象是否在鼠标点击处 if (canvas.containsPoint(event, object)) { //选中该对象 canvas.setActiveObject(object); } } //阻止系统右键菜单 event.preventDefault(); return false; } </script> </head> <body> <canvas id="canvas" width="450" height="200"></canvas> </body> </html>
附:添加一个自定义的右键菜单
1,实现原理
- 这里我们使用一个专门的第三方菜单组件(contextMenu)来实现,在上面的右键点击响应中将菜单弹出即可。
- 关于 contextMenu 更详细的用法,可以参考我之前的文章:jQuery - 右键菜单插件contextMenu使用详解1(安装配置、基本用法)
2,效果图
(1)当鼠标在对像上按下右键时,会出现个菜单。
(2)点击菜单里的“删除”项,即可将对象删除。
3,样例代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> canvas { border: 1px dashed black; } </style> <script src="fabric.js"></script> <script src="jquery-3.1.1.js"></script> <script src="contextMenu/jquery.ui.position.min.js" type="text/javascript"></script> <script src="contextMenu/jquery.contextMenu.js" type="text/javascript"></script> <link href="contextMenu/jquery.contextMenu.css" rel="stylesheet" type="text/css" /> <script> var canvas; //菜单项 var contextMenuItems; window.onload = function() { canvas = new fabric.Canvas('canvas'); var rect1 = new fabric.Rect({top: 50, left: 50, width: 70, height: 70, fill: 'red'}); canvas.add(rect1); var rect2 = new fabric.Rect({top: 50, left: 150, width: 70, height: 70, fill: 'red'}); canvas.add(rect2); var rect3 = new fabric.Rect({top: 50, left: 250, width: 70, height: 70, fill: 'red'}); canvas.add(rect3); //在canvas上层对象上添加右键事件监听 $(".upper-canvas").contextmenu(onContextmenu); //初始化右键菜单 $.contextMenu({ selector: '#contextmenu-output', trigger: 'none', build: function($trigger, e) { //构建菜单项build方法在每次右键点击会执行 return { callback: contextMenuClick, items: contextMenuItems }; }, }); } //右键点击事件响应 function onContextmenu(event) { var pointer = canvas.getPointer(event.originalEvent); var objects = canvas.getObjects(); for (var i = objects.length - 1; i >= 0; i--) { var object = objects[i]; //判断该对象是否在鼠标点击处 if (canvas.containsPoint(event, object)) { //选中该对象 canvas.setActiveObject(object); //显示菜单 showContextMenu(event, object); continue; } } //阻止系统右键菜单 event.preventDefault(); return false; } //右键菜单项点击 function showContextMenu(event, object) { //定义右键菜单项 contextMenuItems = { "delete": {name: "删除", icon: "delete", data: object}, }; //右键菜单显示位置 var position = { x: event.clientX, y: event.clientY } $('#contextmenu-output').contextMenu(position); } //右键菜单项点击 function contextMenuClick(key, options) { if(key == "delete") { //得到对应的object并删除 var object = contextMenuItems[key].data; canvas.remove(object); } } </script> </head> <body> <canvas id="canvas" width="450" height="200"></canvas> <div id="contextmenu-output"></div> </body> </html>