当前位置:网站首页>Fabric.js 右键菜单
Fabric.js 右键菜单
2022-07-02 05:08:00 【德育处主任】
本文简介
Fabric.js 默认没提供 鼠标右键事件,只有 鼠标按键点击 、鼠标按键抬起 、鼠标移动 等事件。 但在工作中有可能需要用到 “右键” 事件,比如 “右键菜单” 。所以就有了本文。
<br>
本文主要关注 Fabric.js 的主要 api 有:
fireRightClick:允许右键点击stopContextMenu:禁用默认右键菜单mouse:down:鼠标点击事件
<br>

<br>
如果不知道 Fabric.js 的同学,可以看 《Fabric.js 从入门到___》
<br>
本案例是使用原生方式开发,不基于 Vue 、React 等框架,所以不用太担心运行环境等问题。
<br>
案例代码放了在文末~
<br> <br>
环境和版本
Chrome浏览器版本:96.0.4664.45
Fabric.js版本:4.6.0
<br><br>
思路
先说说需求:
- 右键单击元素,弹出菜单;
- 弹出菜单分4种情况(菜单在鼠标右侧,菜单在鼠标左侧,菜单在鼠标上方,菜单在鼠标下方);
- 左键单击画布其他地方,隐藏菜单;
<br>
实现思路:
- 创建画布;
- 创建 “菜单” 的DOM元素;
- 去官网查找 “右键相关事件”;
- 右键单击在元素上,根据鼠标离画布边缘的距离,计算菜单要显示的位置;
- 左键单击在画布上,隐藏菜单;
<br> <br>
实现
查文档
在上面的思路中,其实难点只有 “右键相关事件” 。

在 对象相关的文档 里,关于鼠标的事件好像没有右键,稍微沾边点的就是鼠标点击(这里我选了 mousedown)。
<br>
于是我去 画布的文档 里找了下,发现这两个属性:
fireRightClick:画布是否可以触发右键事件stopContextMenu:禁止默认右键菜单
哈哈哈哈,发达了~

<br>
经我仔细观察,发现 mouse:down 事件里有个 button 属性:
- 左键:
button的值为 1 - 右键:
button的值为 3 - 中键(也就是点击滚轮),
button的值为 2,前提需要设置fireMiddleClick: true
<br>
动手开发
布局
<style> /* 容器,相对定位 */ .box { position: relative; } /* 画布,给个边框 */ #canvas { border: 1px solid #ccc; } /* 菜单 */ .menu-x { visibility: hidden; /* 隐藏菜单 */ z-index: -100; position: absolute; top: 0; left: 0; box-sizing: border-box; border-radius: 4px; box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); background-color: #fff; } /* 菜单每个选项 */ .menu-li { box-sizing: border-box; padding: 4px 8px; border-bottom: 1px solid #ccc; cursor: pointer; } /* 鼠标经过的选项,更改背景色 */ .menu-li:hover { background-color: antiquewhite; } /* 第一个选项,顶部两角是圆角 */ .menu-li:first-child { border-top-left-radius: 4px; border-top-right-radius: 4px; } /* 最后一个选项,底部两角是圆角,底部不需要边框 */ .menu-li:last-child { border-bottom: none; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; }</style><!-- 容器(相对定位) --><div class="box"> <!-- 画布 --> <canvas id="canvas" width="600" height="600"></canvas> <!-- 右键菜单(绝对定位,且默认是隐藏的) --> <div id="menu" class="menu-x" > <div class="menu-li">什么都不做</div> <div class="menu-li">什么都不做</div> <div class="menu-li">什么都不做</div> <div class="menu-li">什么都不做</div> <div class="menu-li" onclick="delEl()">删除</div> </div></div>
此时的效果如上图所示。
<br>
初始化画布,并生成图形
<script>// 文档加载后执行window.onload = function() { // 输出当前 fabric 版本 console.log(`Facrib.js版本:${fabric.version}`) // 初始化画布 init() // 禁止在菜单上的默认右键事件 menu.oncontextmenu = function(e) { e.preventDefault() }}// 初始化function init() { canvas = new fabric.Canvas('canvas', { fireRightClick: true, // 启用右键,button的数字为3 stopContextMenu: true, // 禁止默认右键菜单 }) // 矩形 const rect1 = new fabric.Rect({ left: 10, top: 510, fill: 'orange', width: 40, height: 40 }) // 圆角矩形 const rect2 = new fabric.Rect({ left: 510, top: 10, fill: 'pink', width: 40, height: 40, rx: 10, // 圆角x ry: 10, // 圆角y }) // 圆形 const circle = new fabric.Circle({ radius: 30, // 半径 fill: 'green', left: 20, top: 20, }) // 三角形 let triangle = new fabric.Triangle({ width: 80, // 底边宽度 height: 100, // 底边到定点的距离 fill: 'blue', left: 500, top: 480 }) // 将矩形添加到画布中 canvas.add(rect1, rect2, circle, triangle)}</script>
<br>
添加点击事件(判断右键)
<script>// 省略上面的部分代码function init() { // 省略部分代码...... // 将矩形添加到画布中 canvas.add(rect1, rect2, circle, triangle) // 按下鼠标 canvas.on('mouse:down', canvasOnMouseDown)} // 鼠标在画布上的点击事件function canvasOnMouseDown(opt) { // 判断:右键,且在元素上右键 // opt.button: 1-左键;2-中键;3-右键 // 在画布上点击:opt.target 为 null if (opt.button === 3 && opt.target) { // 获取当前元素 activeEl = opt.target menu.domReady = function() { console.log(123) } // 显示菜单,设置右键菜单位置 // 获取菜单组件的宽高 const menuWidth = menu.offsetWidth const menuHeight = menu.offsetHeight // 当前鼠标位置 let pointX = opt.pointer.x let pointY = opt.pointer.y // 计算菜单出现的位置 // 如果鼠标靠近画布右侧,菜单就出现在鼠标指针左侧 if (canvas.width - pointX <= menuWidth) { pointX -= menuWidth } // 如果鼠标靠近画布底部,菜单就出现在鼠标指针上方 if (canvas.height - pointY <= menuHeight) { pointY -= menuHeight } // 将菜单展示出来 menu.style = ` visibility: visible; left: ${pointX}px; top: ${pointY}px; z-index: 100; ` } else { hiddenMenu() }}// 隐藏菜单function hiddenMenu() { menu.style = ` visibility: hidden; left: 0; top: 0; z-index: -100; ` activeEl = null}// 删除元素function delEl() { canvas.remove(activeEl) hiddenMenu()}</script>
<br>
上面的代码中,通过 opt.target 是否为 null 来判断当前点击的对象。
opt.target === null ,就是点击在画布上(没有点击在图形元素上)。
如果你的项目需求是右键点击画布也展示不同菜单,你可以修改上面代码的判断。
<br><br>
代码仓库
<br><br>
推荐
<br> <br>
如果本文内容对你有所帮助,也请你帮我点个赞呗~
点赞 + 关注 + 收藏 = 学会了
边栏推荐
- [Yu Yue education] autumn 2021 reference materials of Tongji University
- 國產全中文-自動化測試軟件Apifox
- Virtual machine installation deepin system
- [high speed bus] Introduction to jesd204b
- 案例分享|智慧化的西部机场
- 4. Flask cooperates with a tag to link internal routes
- Here comes the chicken soup! Keep this quick guide for data analysts
- C# 图片显示占用问题
- How do I interview for a successful software testing position? If you want to get a high salary, you must see the offer
- How to recover deleted data in disk
猜你喜欢
![[Yu Yue education] autumn 2021 reference materials of Tongji University](/img/50/5136359b89a5d047fe648637643ad0.jpg)
[Yu Yue education] autumn 2021 reference materials of Tongji University

Application of intelligent robot in agricultural ecology

Analyze the space occupied by the table according to segments, clusters and pages

Analyzing the hands-on building tutorial in children's programming

Using Kube bench and Kube hunter to evaluate the risk of kubernetes cluster

Go Chan's underlying principles

Hcip day 17

Pyechats 1.19 generate a web version of Baidu map

Preparation for writing SAP ui5 applications using typescript

Dark horse notes -- map set system
随机推荐
Go GC garbage collection notes (three color mark)
2022-003arts: recursive routine of binary tree
Typescript function details
How to modify data file path in DM database
Cultivate primary and secondary school students' love for educational robots
Summary of MySQL key challenges (2)
Go implements leetcode rotation array
Latest: the list of universities and disciplines for the second round of "double first-class" construction was announced
黑马笔记---Map集合体系
Briefly introduce chown command
Pytest learning ----- pytest Interface Association framework encapsulation of interface automation testing
JS interview collection test question 1
fastText文本分类
Summary of database problems
Using Kube bench and Kube hunter to evaluate the risk of kubernetes cluster
7.1 Résumé du concours de simulation
js中的Map(含leetcode例题)
C# 图片显示占用问题
将光盘中的cda保存到电脑中
leetcode两数相加go实现