当前位置:网站首页>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>
如果本文内容对你有所帮助,也请你帮我点个赞呗~
点赞 + 关注 + 收藏 = 学会了
边栏推荐
- Mathematical knowledge (Euler function)
- 将光盘中的cda保存到电脑中
- CubeMx DMA笔记
- What data does the main account of Zhengda Meiou 4 pay attention to?
- [Yu Yue education] autumn 2021 reference materials of Tongji University
- 黑马笔记---Map集合体系
- Global and Chinese market of cell culture freezers 2022-2028: Research Report on technology, participants, trends, market size and share
- No logic is executed after the El form is validated successfully
- Latest: the list of universities and disciplines for the second round of "double first-class" construction was announced
- Acelems Expressway microgrid energy efficiency management platform and intelligent lighting solution intelligent lighting tunnel
猜你喜欢

Video cover image setting, put cover images into multiple videos in the simplest way

Mathematical knowledge -- understanding and examples of fast power

What data does the main account of Zhengda Meiou 4 pay attention to?

Differential identities (help find mean, variance, and other moments)

将光盘中的cda保存到电脑中

Ansible installation and use
![[common error] the DDR type of FPGA device is selected incorrectly](/img/f3/be66bcfafeed581add6d48654dfe34.jpg)
[common error] the DDR type of FPGA device is selected incorrectly

关于Steam 教育的知识整理

解决:代理抛出异常错误

06 装饰(Decorator)模式
随机推荐
Video multiple effects production, fade in effect and border background are added at the same time
数学知识——快速幂的理解及例题
Hcip day 17
培养中小学生对教育机器人的热爱之心
黑马笔记---Set系列集合
Global and Chinese market of hydrocyclone desander 2022-2028: Research Report on technology, participants, trends, market size and share
Fabric.js 背景不受视口变换影响
Go Chan's underlying principles
Online incremental migration of DM database
Typescript function details
js中的Map(含leetcode例题)
创新永不止步——nVisual网络可视化平台针对Excel导入的创新历程
Rhcsa --- work on the third day
06 decorator mode
Fabric.js IText设置指定文字的颜色和背景色
Analyzing the hands-on building tutorial in children's programming
Leetcode 18 problem [sum of four numbers] recursive solution
el form 表单validate成功后没有执行逻辑
2022 Alibaba global mathematics competition, question 4, huhushengwei (blind box problem, truck problem) solution ideas
数学知识(欧拉函数)