From 876908e922fbbaafc21f3b67ec514fccc02a419b Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Tue, 11 Apr 2023 22:25:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/pages/Doc/zh/course15/index.md | 123 +++++++++++++++++++++++- web/src/pages/Doc/zh/course15/index.vue | 98 ++++++++++++++++++- web/src/pages/Doc/zh/course16/index.md | 2 +- web/src/pages/Doc/zh/course16/index.vue | 4 +- web/src/pages/Edit/components/Edit.vue | 2 +- 5 files changed, 224 insertions(+), 5 deletions(-) diff --git a/web/src/pages/Doc/zh/course15/index.md b/web/src/pages/Doc/zh/course15/index.md index 9e7b5c95..1f4d7a91 100644 --- a/web/src/pages/Doc/zh/course15/index.md +++ b/web/src/pages/Doc/zh/course15/index.md @@ -1,3 +1,124 @@ # 如何渲染一个右键菜单 -编写中。。。 \ No newline at end of file +右键菜单可以方便的完成一些功能,大体上分两种,一是在画布上点击右键,二是在节点上点击右键,两者的功能肯定是不一样的,甚至根节点和其他节点功能上也有些不同,比如根节点不能添加同级节点,也不能被删除等等。 + +右键菜单的UI界面需要你自行开发,可以设置成绝对定位或固定定位,然后让它显示在鼠标右键点击的位置即可。 + +## 右键菜单的显示和隐藏 + +首先监听`node_contextmenu`事件在右键点击节点时显示菜单: + +```js +// 当前右键点击的类型 +const type = ref('') +// 如果点击的节点,那么代表被点击的节点 +const currentNode = shallowRef(null) +// 菜单显示的位置 +const left = ref(0) +const top = ref(0) +// 是否显示菜单 +const show = ref(false) + +mindMap.on('node_contextmenu', (e, node) => { + type.value = 'node' + left.value = e.clientX + 10 + top.value = e.clientY + 10 + show.value = true + currentNode.value = node +}) +``` + +你可以根据当前点击的节点来判断一些操作是否可用。比如根节点不能删除,不能插入同级节点,又比如同级第一个节点不能再被往上移,同级最后一个节点不能被往下移。 + +对于画布的处理会比较麻烦,不能直接监听`contextmenu`事件,因为会和右键多选节点冲突,所以需要结合`mousedown`事件和`mouseup`事件来处理。 + +```js +// 记录鼠标右键按下的位置 +const mousedownX = ref(0) +const mousedownY = ref(0) +const isMousedown = ref(false) + +mindMap.on('svg_mousedown', (e) => { + // 如果不是右键点击直接返回 + if (e.which !== 3) { + return + } + mousedownX.value = e.clientX + mousedownY.value = e.clientY + isMousedown.value = true +}) + +mindMap.on('mouseup', (e) => { + if (!isMousedown.value) { + return + } + isMousedown.value = false + // 如果鼠标松开和按下的距离大于3,则不认为是点击事件 + if ( + Math.abs(mousedownX.value - e.clientX) > 3 || + Math.abs(mousedownX.value - e.clientY) > 3 + ) { + hide() + return + } + type.value = 'svg' + left.value = e.clientX + 10 + top.value = e.clientY + 10 + show.value = true +}) +``` + +很简单,其实就是判断鼠标按下和松开的距离是否很小,是的话就认为是点击事件,否则应该是鼠标拖动。 + +右键菜单显示了,肯定就需要隐藏,当左键点击了画布、左键点击了节点、左键点击了展开收起按钮时都需要隐藏右键菜单。 + +```js +const hide = () => { + show.value = false + left.value = 0 + top.value = 0 + type.value = '' +} +mindMap.on('node_click', hide) +mindMap.on('draw_click', hide) +mindMap.on('expand_btn_click', hide) +``` + +## 复制、剪切、粘贴的实现 + +接下来介绍一下复制、剪切、粘贴的实现。 + +一般来说你的右键菜单中肯定也会添加这三个按钮,另外快捷键操作也是必不可少的,但是这三个快捷键是没有内置的,所以你需要自己注册一下: + +```js +mindMap.keyCommand.addShortcut('Control+c', copy) +mindMap.keyCommand.addShortcut('Control+v', paste) +mindMap.keyCommand.addShortcut('Control+x', cut) +``` + +如需删除调用`removeShortcut`方法即可。 + +接下来实现一下这三个方法: + +```js +// 保存复制/剪切的节点的数据,后续可以原来粘贴 +let copyData = null + +const copy = () => { + copyData = mindMap.renderer.copyNode() +} + +const cut = () => { + mindMap.execCommand('CUT_NODE', _copyData => { + copyData = _copyData + }) +} + +const paste = () => { + mindMap.execCommand('PASTE_NODE', copyData) +} +``` + +## 完整示例 + +