当前位置:网站首页>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>
如果本文内容对你有所帮助,也请你帮我点个赞呗~
点赞 + 关注 + 收藏 = 学会了
边栏推荐
- Briefly introduce chown command
- Fasttext text text classification
- Rhcsa --- work on the third day
- Pytest learning ----- pytest assertion of interface automation testing
- The reason why sizeof (ARR) / sizeof (arr[0]) is used in the function to calculate the length of the array is incorrect
- 7.1 simulation summary
- Essence and physical meaning of convolution (deep and brief understanding)
- Hcip day 17
- 摆正元素(带过渡动画)
- 从数组中找出和为目标的下标
猜你喜欢
农业生态领域智能机器人的应用
2022-003arts: recursive routine of binary tree
About PROFIBUS: communication backbone network of production plant
Hcip day 17
How to modify data file path in DM database
Video cover image setting, put cover images into multiple videos in the simplest way
Application of intelligent robot in agricultural ecology
No logic is executed after the El form is validated successfully
Mathematical knowledge (Euler function)
Fabric.js IText设置指定文字的颜色和背景色
随机推荐
黑马笔记---Set系列集合
画波形图_数字IC
Find the subscript with and as the target from the array
National all Chinese Automatic Test Software apifox
Common errors of dmrman offline backup
List of common bugs in software testing
Preparation for writing SAP ui5 applications using typescript
The El cascader echo only selects the questions that are not displayed
Video multiple effects production, fade in effect and border background are added at the same time
Differential identities (help find mean, variance, and other moments)
Mapping settings in elk (8) es
The reason why sizeof (ARR) / sizeof (arr[0]) is used in the function to calculate the length of the array is incorrect
函数栈帧的创建和销毁
LeetCode 241. 为运算表达式设计优先级(分治/记忆化递归/动态规划)
Mysql重点难题(2)汇总
Change deepin to Alibaba image source
Dark horse notes -- Set Series Collection
Feign realizes file uploading and downloading
go实现leetcode旋转数组
CubeMx DMA笔记