阅读 34

思维导图开发-技术选择-七种武器(1)之SVG

技术选型

在开发思维导图库blink-mind-react过程中,实现思维导图中节点(NodeWidget)之间的连接线(Link)的技术选择,有两种:

  1. 使用canvas api绘制
  2. 使用SVG元素

因为思维导图的布局方式我选用的是Flex 布局,SVG元素可以像操作普通DOM 节点一样进行操作,使用SVG 方案的话,可以把每两个NodeWidget之间Link单独用一个SVG元素来表示,一个NodeWidget有多少个子元素,这个NodeWidget的children中就包含多少个用SVG表示的Link。将一条连接线封装成一个组件叫做LinkWidget。这样在布局Link的过程中,只需要关注和这个LinkWidget有关联的两个NodeWidget的位置以及位置的变化。

而如果选用canvas方案的话,

  1. 将整个思维导图中所有的Link 绘制到同一个canvas上
  2. 亦或者是把一个节点和其所有子节点的Link绘制在同一个canvas上

这两种方法都会导致绘制Link时要关注的NodeWidget位置变化多于两个,布局算法的复杂程度要高于SVG 方案。

基于以上考虑,在我的开发过程中,使用SVG方案。

需求分析

具体的需求如下:

思维导图的布局方式可以进行配置,要能够支持单侧布局,双侧布局。思维导图的布局方向需要支持上下左右四个方向,其中单侧布局,这四个方向都要支持。 而双侧布局,需要支持左右方向,和上下方向。

举个栗子,下图是市面上一个软件里面支持的几种布局方式,它的单向布局只支持三个方向,朝左,朝右,朝下,双向布局只支持左右。

实现思路

具体的代码详见LinkWidget.tsx

简单实现的思路

首先将问题简单化一点,实现单向布局中朝右布局

如图所示:

DOM 结构如下

用于绘制Link的SVG元素放置在class='bm-link'的div元素下,而对于同一个节点下的bm-link元素,其position都设置为absolute,left 和 top 都设置为0。通俗来讲,就是bm-link和bm-children的BoundingRect是相同的。

单个link的SVG 内容:

SVG 里面的path 元素是可以通过计算算出的。怎么算呢?假设这个Link的From NodeWidget的key 是fromNodeKey, To NodeWidget的key 是 toNodeKey, 通过这两个key 就可以通过DOM的api 拿到这两个NodeWidget的BoundingRect, 根据这两个BoundingRect还有SVG 元素本身的坐标系,即可算出Link的路径。具体的计算过程可以参见这个库里面的LinkWidget组件的代码。在这里就不贴具体代码了。

关注下面的标签,发现更多相似文章
评论