今天在群里有个小伙伴提出了这么个问题:如何在框选完成后给框选的区域添加一个右键菜单的功能,我看到了这个问题后也是有点懵,心里想着怎么还有这个需求,直接快捷键删除不是更好吗,谁知这位小伙伴也是这么写的,奈何客户要添加右键菜单的功能,所以说,客户最大。既然人家都提出这个需求呢,那就说明大概率情况下是可以做的,只是看自己想不想做了,下面我先来分析下我的思路,仅供参考,不过这个方案应该是能解决大部分的业务场景了

问题分析

  1. 框选完成?那就监听框选完成的事件,这个官方是有对应的事件的
  2. 框选完成才会触发右键?也就是说不框选是不能触发右键事件的
  3. 即使前面两个步骤都解决了,那我这个菜单坐标怎么确定?第一个想到是框选的时候会有左右的边界,就像如图这样,我是否可以根据这两个边界节点的坐标去动态计算?第二个方法就是不加右键的功能,直接在框选的容器的右上角添加一个dom,把操作按钮放在这里面,通过鼠标划入来控制显示和隐藏

  1. 但是从全局的角度分析了下,发现第三个步骤复杂度有点大,不是说不能实现,而是没有必要这么做;就像你去跑800米,正常情况下我们都是贴着最内道跑,而你非要在最外道跑。而且没有添加右键这个操作,不就满足不了需求了吗。
  2. 经过一轮分析后,决定还是来玩玩dom操作,因为只有dom是一直不变的,变的只是显示隐藏而已,从理论上来说,我们是可以获取到框选这个容器的dom实例的,然后再根据这个dom实例去触发右键的事件,然后我在这个右键里面添加我的业务操作不就行了吗?开干吧!

解决方法

步骤1

这里为了保险起见,我给框选插件的配置项添加了一个自定义的class类名,我可以根据我这个唯一的class去获取框选的容器

步骤二

开始玩dom,先获取到我自定义的这个class,然后再根据这个父级去获取真正的框选容器(框选容器的class需要自行打开浏览器的f12去找哈)

// 我自定义的class
const parent = document.getElementsByClassName('cu-selected-container')[0];
// 框选的容器
const selectInner = parent.getElementsByClassName('x6-widget-selection-inner')[0];
// 打印下看是个啥
console.log('seleeeee >>>', selectInner);

没错了,我获取到了,看下图

步骤三

经过前面两个步骤的处理,步骤三就轻松多了,步骤三主要做的事情就是监听框选完成的事件,看过官网的小伙伴都知道,官方大大给我们提供的事件还是挺多的事件,那小伙伴在这里可能就犯嘀咕了,我到底该用哪个呢?其实吧,我觉得这里用哪个事件更多取决你的业务场景,我这里为了节约时间,就直接使用selection:changed这个事件了。

:::warning

Tip:如果你框选的节点个数是0的话需要特殊处理下,不然控制台会报框选的容器不存在,我这里是根据selected的长度进行判断,不满足条件直接提前返回

:::

graph.on('selection:changed', ({ selected }) => {
if (selected.length === 0) return;
const parent = document.getElementsByClassName('cu-selected-container')[0];
const selectInner = parent.getElementsByClassName('x6-widget-selection-inner')[0];
selectInner.style.pointerEvents = 'unset';
console.log('seleeeee >>>', selectInner);
selectInner.addEventListener('contextmenu', event => {
event.preventDefault();
alert(1);
});
});

最后再看下效果吧,菜单的内容后面我再更新吧……

步骤四

原以为到第三个步骤就结束了,没想到还有个问题,就是我一直去框选,但是这期间我不去触发右击事件,直到最后我再右键,这时你再去点击alert的确定按钮会发现完全关不掉,我想着完了完了,是不是进入死循环了?于是我就多实验了几次,发现这个alert的次数是和我框选的次数是有关联的,于是就在想是哪里除了问题,经过一番排查后发现是事件的问题,好像是每次框选完后没有清空掉dom,于是我就从事件这里下手解决,决定在触发右键菜单之前先移除一下右键的事件(排他法,不管你有没有,先清空再说),果然问题得到了完美的解决


const handleContextMenu = event => {
event.preventDefault();
alert(1);
};
graph.on('selection:changed', ({ selected }) => {
if (selected.length === 0) return;
const parent = document.getElementsByClassName('cu-selected-container')[0];
const selectInner = parent.getElementsByClassName('x6-widget-selection-inner')[0];
selectInner.style.pointerEvents = 'unset';
console.log('seleeeee >>>', selectInner);
selectInner.removeEventListener('contextmenu', handleContextMenu);
selectInner.addEventListener('contextmenu', handleContextMenu);
});

总结

问题分析很关键,代码只是个工具,具体怎么走还是要我们自己去制定,所以在这一行待的时间久了,你会发现分析问题和关键时刻解决问题的能力是有多重要。顺便讲一下这个小功能我也是趁着下班前15分钟搞出来的,如果我直接跳过分析问题的步骤,我估计到节后也不一定能想到解决方案。好了,这个小问题的总结就到这吧,有空再更新菜单坐标的问题的解决思路吧。demo也同步更新了,想看效果的可以直接看antv demo

「AntV」x6 框选添加右键菜单的更多相关文章

  1. 给tkinter文本框添加右键菜单

    给tkinter文本框添加右键菜单 需求:直接右键点击使用tkinter创建的文本框是不会弹出菜单的.我们需要实现右键点击tkinter框架下的Entry对象.Text对象后弹出右键菜单可复制.粘贴和 ...

  2. Beyond Compare 3添加右键菜单

    目前是在Beyond Compare 3.1.9版本上试验可行,其他版本上尚未测试. 添加右键菜单步骤: 1.新建为.bat后缀的文本,将下面“添加右键菜单批处理”复制到此文本中. 2.将批处理移动到 ...

  3. C# DataGridView添加右键菜单的简单应用

    首先,参考了下以下文章: https://blog.csdn.net/qin_zhangyongheng/article/details/23773757 感谢. 项目中要在DataGridView中 ...

  4. pyqt5-为QListWidget添加右键菜单

    如何在pyqt5下为QListWidget添加右键菜单? 能百度到的均是pyqt4下的,有些貌似并不好用. 在尝试了很多方法后,下面贴出可用的方法: from PyQt4 import QtCore, ...

  5. 添加右键菜单命令 在此处打开命令窗口(E)(带图标)

    @color 0A @title 添加右键菜单命令 在此处打开命令窗口(^&E)(带图标) by wjshan0808 @echo off reg add HKCR\Directory\Bac ...

  6. 仅在TabControl中的Tab中添加右键菜单

    若想实现仅在TabControl中的Tab中添加右键菜单,可在XAML中通过使用样式得到: <TabControl> <TabControl.ItemContainerStyle&g ...

  7. [cb] Unity Editor 添加右键菜单

    需求 为Unity的Editor窗口添加右键菜单 实现代码 // This example shows how to create a context menu inside a custom Edi ...

  8. Arcengine 二次开发添加右键菜单

    最近在搞arcengine 二次开发,遇到了好多问题,也通过网上查资料试着慢慢解决了,把解决的步骤记录下来,有需要帮助的可以看一下,也欢迎各位来批评指正. 想给自己的map application在图 ...

  9. DevExpress使用教程:XtraGridControl动态添加右键菜单

    在使用 GridControl 的时候经常需要添加右键菜单.一般的做法是自己创建菜单项,然后注册GridView的Mouse-Click事件,然后Show出定义好的菜单.但是涉及到一些单击事件会收到编 ...

  10. 『实践』百度地图给map添加右键菜单(判断是否为marker)

      var map; var s;//经度 var w;//纬度 $(document).ready(function(){ $(".mune").load("jsp/c ...

随机推荐

  1. 2022-01-18:将数组分成两个数组并最小化数组和的差。 给你一个长度为 2 * n 的整数数组。你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之

    2022-01-18:将数组分成两个数组并最小化数组和的差. 给你一个长度为 2 * n 的整数数组.你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之 ...

  2. Vue 打包后报 Uncaught SyntaxError: Unexpected token ‘<‘

    根本原因在于你的vue.config.js里的publishPath设置的路径是相对路径还是绝对路径 大家都是看别人设置成 process.env.NODE_ENV==='production' ? ...

  3. Netty实战(二)

    一.环境准备 Netty需要的运行环境很简单,只有2个. JDK 1.8+ Apache Maven 3.3.9+ 二.Netty 客户端/服务器概览 如图,展示了一个我们将要编写的 Echo 客户端 ...

  4. Request header field userRole is not allowed by Access-Control-Allow-Headers in preflight response.

    今使用axios 请求数据过程中遇到同事设置的请求头,在我请求的接口中部不被允许,于是老是提示Request header field userRole is not allowed by Acces ...

  5. Cesium中监听MOUSE_MOVE事件获取经纬度和高度

    有时候在这个圆球上获取精确的经度纬度还不容易,特别是高度 还好在cesium提供了接口,看 let selft = this; const scene = this.viewer.scene; var ...

  6. rest framwork 4 分页功能

    分页功能: 常遇到问题,当数据记录超过1000万条,如何进行分页显示问题,这时就考虑分页功能, restframework 分页实现有三种 第一种:看n页,每页显示n条数据: PageNumberPa ...

  7. [TSG开发]法如扫描仪SDK探幽-1.旧版SDK采集流程、问题解析、常见参数

    做什么 法如扫描仪是一个三维的激光扫描仪,可以通过特定的作业模式将空间以三维激光点云的形式保存下来,并且通过特定的算法得出一些想要的具体参数. 这个SDK探幽日志主要是对目前SDK开发中遇到的一些问题 ...

  8. SD协议-命令响应

    1.CRC 发送命令或数据的时候,都需要经过芯片的IO口,SD Host和SD卡是通过PCB的走线连接在一起的,SD Host IO --> PCB线 --> SD Card IO,PCB ...

  9. karyoploteR: 基因组数据可视化 R 包

    karyoploteR,是一个适用于所有基因组数据(any data on any genome)非圆环布局(non-circular layouts)的可视化 R/Bioconductor 包.开发 ...

  10. 深入探究for...range语句

    1. 引言 在Go语言中,我们经常需要对数据集合进行遍历操作.对于数组来说,使用for语句可以很方便地完成遍历.然而,当我们面对其他数据类型,如map.string 和 channel 时,使用普通的 ...