本篇主要記錄流程圖的實現過程中的難點和核心技術點,先上效果圖:
節點可以任意拖拽,曲線跟隨變化
正在連接的線
1、節點實現
流程圖是基於SVG繪制的,節點主要利用 g
和 foreignObject
的特性來實現:
<g class="pane-node">
<foreignObject width="180" height="50">
<body xmlns="http://www.w3.org/1999/xhtml">
<div class="pane-node-content">
<span class="iconfont icon-datas"></span>
<span class="name" :title="item.name">{{item.name}}</span>
<!-- 節點進 -->
<div class="pane-port-list in">
......
</div>
<!-- 節點出 -->
<div class="pane-port-list out">
......
</div>
</div>
</body>
</foreignObject>
</g>
- g元素:特性是可以包裹元素,並進行位置變化,這樣拖拽的時候獲取對應的坐標改變
transform
的值就可以整體移動了; - foreignObject標簽:借助
<foreignObject>
標簽,可以直接在SVG內部嵌入XHTML元素,尤其一些需要css進行控制的樣式類,但是這個兼容性較差,主要是IE瀏覽器。
2、曲線的繪制
核心代碼:
<g class="pane-link">
<path class="connector-wrap" :d="`M ${pos.startS} Q ${pos.curveS} T ${pos.endS}`"></path>
<path
class="target-marker"
d="M 5 0 L 0 3.6327126400268037 L 5 7.265425280053607 Z"
:transform="`translate(${item.endPosX - 4},${item.endPosY + 4}) scale(1,1) rotate(-90)`"
></path>
</g>
這里使用的是svg
中的path
中的M Q T
:
M
:moveto
這里是初始節點的底部連接點Q
:quadratic Bézier curve
二次貝塞爾曲線
【截圖源於網絡】
T
:smooth quadratic Bézier curveto
二次貝塞爾曲線平滑延伸
【截圖源於網絡】
這里的
T
指的是通過一個控制點推斷出一個新的控制點,T前面必須是一個Q命令或者是另一個T命令
由此可見,只要確認三個點(起點,控制點,終點),就可以繪制出平滑好看的曲線啦~
/**
* startPosX 起節點的左上角x
* endPosX 終節點的左上角x
* sizeX 節點的一半寬度 sizeY 是節點的高度
/
// 起始點
let startS = `${startPosX + sizeX} ${startPosY + sizeY}`;
// 二次貝爾曲線
let curveS = `${startPosX + sizeX} ${startPosY + sizeY + 40} ${
this.endNode
? (startPosX + endPosX+ 2 * sizeX) / 2
: (startPosX + endPosX+ sizeX) / 2
} ${(startPosY + endPosY + 20) / 2}`;
// 終點
let endS = `${this.endNode ? endPosX + sizeX : endPosX} ${endPosY}`;
至於節點的拖拽就比較簡單了,點擊移動的時候獲取位置信息更transform
的translate
屬性即可。