想要的效果
在react中使用antvx6制作一个可以绘制流程图的组件
上图中,想实现从左侧圆拉出一条箭头连接到右侧圆,当箭头到达右侧圆范围内才显示连接桩(大圆四周的小圆圈),否则不显示。
遇到的问题
想要实现以上效果需要拖住箭头(鼠标左键按下),如果此时我们使用antvx6自带的node:mouseenter事件检测鼠标是否进入到圆的范围内,由于此时鼠标是按下状态,会有一个拖拽事件,所以node:mouseenter事件无法触发。也就是说,当拖拽箭头进入到监听的圆中,无法触发,但是不拖拽箭头是可以的。
如何解决
由于antvx6暂时提供的api无法直接实现当前效果,但是其提供了edge:change:target这个检测属性,当拖拽箭头时可以获取箭头的坐标,同时,node(圆)中也提供了position(位置)与size(长宽)方法,我们则可以根据position的x,y坐标与size提供的width与height属性计算出圆的圆心位置和半径,如圆心为(x1,y1),半径为radius,箭头的位置为(x2,y2)。则可以根据Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2))计算出箭头位置与圆心的距离,并与半径进行比较,如果符合判定条件就可以设置连接桩的属性来控制连接桩的显隐。
但是如何知道用户要将箭头连向哪个圆呢,我这里采取比较暴力的做法,每当向画布中添加圆时,将所有圆的node对象存在一个大的对象中,此大的对象包含所有的圆(node对象),每当拖动箭头时,则会遍历整个大的对象执行上述的计算。
注:若页面中圆过多,可能会过于占用资源。
代码
以下是控制链接桩显隐的函数。
const showPorts = (node: any, ports: any, visible: boolean) => {
ports.forEach((port: any) => {
//设置连接桩属性
node.setPortProp(
port.id,
'attrs/circle/style/visibility',
visible ? 'visible' : 'hidden',
)
})
}
判断两点距离与半径相比较的代码
const calueCirclePendingScope = (node: any, current: any) => {
//半径
const radius = node.size().width / 2;
const { x, y } = node.position();
const x2 = x + radius;
const y2 = y + radius;
const x1 = current.x;
const y1 = current.y;
const dis = Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2));
if (dis < radius + 10) {
showPorts(node, node.getPorts(), true);
} else {
showPorts(node, node.getPorts(), false);
}
}