Fabric.js - 实现添加鼠标右键点击事件响应(右键菜单:新增/删除)

Fabric.js 的 Canvas 有个 mouse:down 事件,通过它我们可以监听到鼠标按下的行为。不过该事件只对鼠标左键其作用,如果是右键按下则不会触发该事件。 而 Canvas 上又无法直接监听 contextmenu 事件,所以想要实现右键点击响应就需要换种方式实现。

1. 实现原理

Fabric.js 的 Canvas 初始化完毕后,会自动在其上方覆盖一个 class 名为 upper-canvas 的 canvas。
我们可以在上层这个 canvas 上添加 contextmenu 事件监听。当右键按下时会触发该事件,然后将点击的坐标转换成底下实际的 canvas 里的坐标(坐标需要转换是因为下面 canvas 可能会被移动,缩放)。

2. 实现步骤

2.1. 默认情况下,鼠标左键点击对象即可选择中该对象。这里增加个右键选中功能,即通过右键同样可以选中对象。

2.2. 这里我们使用一个专门的第三方菜单组件(contextMenu)来实现,在上面的右键点击响应中将菜单弹出即可。关于 contextMenu 更详细的用法,可以参考此文章:jQuery - 右键菜单插件contextMenu使用详解

3. 效果图

(1)当鼠标在对像上按下右键时,会出现个菜单,新增 / 删除
(2)点击菜单里的“新增”项,即可将对象添加。
(3)点击菜单里的“删除”项,即可将对象删除。

在这里插入图片描述

4. 参考代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        canvas {
            border: 1px dashed black;
        }
    </style>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.contextMenu.min.css">
    <script src="https://cdn.bootcss.com/fabric.js/4.0.0-beta.5/fabric.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.contextMenu.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.ui.position.js"></script>
    <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 },
                "add": { name: "新增", icon: "add", 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);
            }else if(key = "add"){
                var rect3 = new fabric.Rect({ top: 50, left: 350, width: 70, height: 70, fill: 'red' });
                canvas.add(rect3);
                canvas.renderAll();
            }
        }
    </script>
</head>

<body>
    <canvas id="canvas" width="450" height="200"></canvas>
    <div id="contextmenu-output"></div>
</body>

</html>
发布了114 篇原创文章 · 获赞 99 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/qq_36410795/article/details/104519573