贝塞尔曲线(Bezier curve)实现节点连接

背景

长久以来都想找一个画流程图的工具,有几个需求,可以将组件拖到绘图面板中,并且组件间可以通过线进行关联,在属性面板可以配置组件的属性,这里的组件可能是html的组件,也可能是一个功能,为什么需要这么一个东西呢?如果有这东西,很多想法就可以实现,比如

  • 工作流
  • 服务编排

但一直找不到满意的框架,很大原因就是这些框架颜值太低,直到遇到NodeRed,NodeRed是物联网开发工具,提供可视化界面通过配置就能实现物联网程序的开发,让我感兴趣的是NodeRed可视化界面,颜值高,操作便利,简洁不花哨

贝塞尔曲线(Bezier curve)实现节点连接_第1张图片

因为NodeRed是开源的,也花了一段时间去研究他的代码,想把可视化工具抽离出为我所用,种种原因失败了,既然抽离不出来,能不能自己实现一个?之前从来没想过自己开发一个,但细想觉得并不难实现,可视化界面核心有两点

  • 组件的绘制
  • 连接线的绘制

整个界面都是通过svg相关标签实现,组件的绘制相对比较简单,就是一些svg元素组合,卡在了连接线这里,因为NodeRed节点连接线操作平滑,曲线合理,一开始以为是用很复杂的算法实现的,在源码里去找这个算法,其实是把问题想复杂了,这个就是一条普通的贝塞尔曲线,既然知道了实现的原理,自己做一个也不难,这一篇博客就介绍如何用贝塞尔曲线实现节点连接。

贝塞尔曲线

我本身不是数学专业,对贝塞尔曲线在数学上的原理我也不懂,我觉得也没必要弄懂,就当作一个工具用,贝塞尔曲线就是可以实现两个点平滑的进行连接的一个工具,贝塞尔曲线又四个点进行控制,一个起点一个终点,两个控制点,通过对控制点的调整可以实现曲线像皮筋一样变形,达到我们想要的效果。

这里有个很棒的网站 可以进行在线绘制贝塞尔曲线

实现

从上面可以看出,两个控制点的位置决定了曲线的路径,所以这两个点的位置很重要,我查看了NodeRed的实现,NodeRed是分别选取距离起点水平75px和终点75px两个点作为控制点,以下图为例

贝塞尔曲线(Bezier curve)实现节点连接_第2张图片

两个节点之间距离长是200px,宽是160px,曲线的svg代码如下

M代表起点(340,260),C后面跟着两个控制点(415,260),(465,100)最后(540,100)是终点,第一个控制点和起点Y是相同的,说明在同一个水平面上,x相距415-340=75,第二个控制点和终点也是Y相同,x相距540-465=75,就算改变组件位置,这个长度依然不会变,效果和下面这个是一样的

贝塞尔曲线(Bezier curve)实现节点连接_第3张图片

既然知道了规则,我们就自己实现一个,以下是距离75px的效果,基本和NodeRed一样

参考代码:







可以尝试更改level查看不同长度的效果,以下是距离一半的效果

就修改了level的长度为距离的一半

...
let off = Math.abs(event.clientX - x1);
let level = off / 2;
...

总结

后续我们也会讨论如何实现节点拖拽

你可能感兴趣的