技術(shù)選型
在開發(fā)思維導(dǎo)圖庫blink-mind-react過程中,實現(xiàn)思維導(dǎo)圖中節(jié)點(NodeWidget)之間的連接線(Link)的技術(shù)選擇挣惰,有兩種:
- 使用canvas api繪制
- 使用SVG元素
因為思維導(dǎo)圖的布局方式我選用的是Flex 布局兄一,SVG元素可以像操作普通DOM 節(jié)點一樣進行操作,使用SVG 方案的話弥臼,可以把每兩個NodeWidget之間Link單獨用一個SVG元素來表示,一個NodeWidget有多少個子元素凰棉,這個NodeWidget的children中就包含多少個用SVG表示的Link供屉。將一條連接線封裝成一個組件叫做LinkWidget。這樣在布局Link的過程中呵萨,只需要關(guān)注和這個LinkWidget有關(guān)聯(lián)的兩個NodeWidget的位置以及位置的變化奏属。
而如果選用canvas方案的話,
- 將整個思維導(dǎo)圖中所有的Link 繪制到同一個canvas上
- 亦或者是把一個節(jié)點和其所有子節(jié)點的Link繪制在同一個canvas上
這兩種方法都會導(dǎo)致繪制Link時要關(guān)注的NodeWidget位置變化多于兩個潮峦,布局算法的復(fù)雜程度要高于SVG 方案囱皿。
基于以上考慮,在我的開發(fā)過程中忱嘹,使用SVG方案嘱腥。
需求分析
具體的需求如下:
思維導(dǎo)圖的布局方式可以進行配置,要能夠支持單側(cè)布局拘悦,雙側(cè)布局齿兔。思維導(dǎo)圖的布局方向需要支持上下左右四個方向,其中單側(cè)布局础米,這四個方向都要支持分苇。 而雙側(cè)布局,需要支持左右方向屁桑,和上下方向医寿。
舉個栗子,下圖是市面上一個軟件里面支持的幾種布局方式蘑斧,它的單向布局只支持三個方向糟红,朝左,朝右乌叶,朝下盆偿,雙向布局只支持左右。
實現(xiàn)思路
具體的代碼詳見LinkWidget.tsx
簡單實現(xiàn)的思路
首先將問題簡單化一點准浴,實現(xiàn)單向布局中朝右布局
如圖所示:
DOM 結(jié)構(gòu)如下
用于繪制Link的SVG元素放置在class='bm-link'的div元素下事扭,而對于同一個節(jié)點下的bm-link元素,其position都設(shè)置為absolute,left 和 top 都設(shè)置為0乐横。通俗來講求橄,就是bm-link和bm-children的BoundingRect是相同的今野。
單個link的SVG 內(nèi)容:
SVG 里面的path 元素是可以通過計算算出的。怎么算呢罐农?假設(shè)這個Link的From NodeWidget的key 是fromNodeKey,
To NodeWidget的key 是 toNodeKey, 通過這兩個key 就可以通過DOM的api 拿到這兩個NodeWidget的BoundingRect条霜,
根據(jù)這兩個BoundingRect還有SVG 元素本身的坐標系,即可算出Link的路徑涵亏。具體的計算過程可以參見這個庫里面的LinkWidget組件的代碼宰睡。在這里就不貼具體代碼了。