有沒有專門做外貿(mào)的網(wǎng)站互聯(lián)網(wǎng)廣告管理暫行辦法
前言:參考 [AntV X6 官網(wǎng)](https://x6.antv.antgroup.com/)
一、簡介
X6 可以快速搭建 DAG 圖、ER 圖、流程圖、血緣圖等應(yīng)用。
二、快速上手
1. 安裝
npm install @antv/x6 --save# oryarn add @antv/x6# orpnpm add @antv/x6
2. 使用
2.1 初始畫布
在頁面中創(chuàng)建一個(gè)畫布容器,然后初始化畫布對(duì)象,可以通過配置設(shè)置畫布的樣式,比如背景顏色。
<script setup lang="ts">import { Graph } from "@antv/x6";const graph = new Graph({container: document.getElementById("container"),width: 800,height: 600,background: {color: "#F2F7FA",},});</script><template><div id="container"></div></template><style lang="scss" scoped></style>
2.2 渲染節(jié)點(diǎn)和邊
X6 支持 JSON 格式數(shù)據(jù),該對(duì)象中 nodes 代表節(jié)點(diǎn)數(shù)據(jù),edges 代表邊數(shù)據(jù),可以使用 attrs 屬性來定制節(jié)點(diǎn)和邊的樣式(可以類比 CSS)。
<script setup lang="ts">import { onMounted } from "vue";import { Graph } from "@antv/x6";const data = {nodes: [{id: "node1",shape: "rect",x: 40,y: 40,width: 100,height: 40,label: "hello",attrs: {// body 是選擇器名稱,選中的是 rect 元素body: {stroke: "#8f8f8f",strokeWidth: 1,fill: "#fff",rx: 6,ry: 6,},},},{id: "node2",shape: "rect",x: 160,y: 180,width: 100,height: 40,label: "world",attrs: {body: {stroke: "#8f8f8f",strokeWidth: 1,fill: "#fff",rx: 6,ry: 6,},},},],edges: [{shape: "edge",source: "node1",target: "node2",label: "x6",attrs: {// line 是選擇器名稱,選中的邊的 path 元素line: {stroke: "#8f8f8f",strokeWidth: 1,},},},],};onMounted(() => {const graph = new Graph({container: document.getElementById("container"),width: 800,height: 600,background: {color: "#F2F7FA",},});graph.fromJSON(data); // 渲染元素graph.centerContent(); // 居中顯示});</script><template><div id="container"></div></template><style lang="scss" scoped></style>
2.3 數(shù)據(jù)導(dǎo)出
使用 fromJSON 將 JSON 數(shù)據(jù)渲染到畫布中,使用 toJSON 將畫布中數(shù)據(jù)導(dǎo)出成 JSON,這樣我們就可以將畫布數(shù)據(jù)序列化后存儲(chǔ)到服務(wù)端。
graph.toJSON();
三、基礎(chǔ)
1. 畫布
1.1 畫布大小
h 設(shè)置 width、height,不設(shè)置以容器大小初始畫布。設(shè)置 autoResize,外層再嵌套一層寬高 100%的容器用來自適應(yīng)窗口大小。
<script setup lang="ts">import { onMounted } from "vue";import { Graph } from "@antv/x6";onMounted(() => {const graph = new Graph({container: document.getElementById("container"),autoResize: true,});});</script><template><div style="width: 100%; height: 100%"><div id="container"></div></div></template><style lang="scss" scoped></style>
1.2 背景與網(wǎng)格
可以通過 background 和 grid 兩個(gè)配置來設(shè)置畫布的背景以及網(wǎng)格。
const graph = new Graph({container: this.container,background: {color: "#F2F7FA",},grid: {visible: true,type: "doubleMesh",args: [{color: "#eee", // 主網(wǎng)格線顏色thickness: 1, // 主網(wǎng)格線寬度},{color: "#ddd", // 次網(wǎng)格線顏色thickness: 1, // 次網(wǎng)格線寬度factor: 4, // 主次網(wǎng)格線間隔},],},});
1.3 縮放與平移
設(shè)置 panning 拖拽、mousewheel 縮放
const graph = new Graph({panning: true,mousewheel: true,});
1.4 常用 API
graph.resize(800, 600):重置畫布大小
graph.zoom(0.2):將畫布縮放級(jí)別增加 0.2(默認(rèn)為 1)
graph.zoom(-0.2):將畫布縮放級(jí)別減少 0.2
graph.zoomTo(1.2):將畫布縮放級(jí)別設(shè)置為 1.2
graph.zoomToFit({ maxScale: 1 }):將畫布中元素縮小或者放大一定級(jí)別,讓畫布正好容納所有元素,可以通過 maxScale 配置最大縮放級(jí)別
graph.centerContent():將畫布中元素居中展示
2. 節(jié)點(diǎn)
2.1 添加節(jié)點(diǎn)
graph.addNode({shape: "rect", // 節(jié)點(diǎn)形狀x: 100, // 節(jié)點(diǎn)位置 x 坐標(biāo),單位為 px。y: 40, // 節(jié)點(diǎn)位置 y 坐標(biāo),單位為 px。width: 100, // 節(jié)點(diǎn)寬度,單位為 px。height: 40, // 節(jié)點(diǎn)高度,單位為 px。angle: 0, // 節(jié)點(diǎn)旋轉(zhuǎn)角度。});
2.2 內(nèi)置節(jié)點(diǎn)
X6 內(nèi)置節(jié)點(diǎn)形狀:rect 矩形、circle 圓形、ellipse 橢圓、polygon 多邊形、polyline 折線、path 路徑、image 圖片
// 公用樣式const commonAttrs = {body: {fill: "#fff",stroke: "#8f8f8f",strokeWidth: 1,},label: {refX: 0.5,refY: "100%",refY2: 4,textAnchor: "middle",textVerticalAnchor: "top",},};// rect 矩形graph.addNode({shape: "rect",x: 40,y: 40,width: 80,height: 40,label: "rect",attrs: commonAttrs,});// circle 圓形graph.addNode({shape: "circle",x: 180,y: 40,width: 40,height: 40,label: "circle",attrs: commonAttrs,});// ellipse 橢圓graph.addNode({shape: "ellipse",x: 280,y: 40,width: 80,height: 40,label: "ellipse",attrs: commonAttrs,});// path 路徑graph.addNode({shape: "path",x: 420,y: 40,width: 40,height: 40,// https://www.svgrepo.com/svg/13653/likepath: "M24.85,10.126c2.018-4.783,6.628-8.125,11.99-8.125c7.223,0,12.425,6.179,13.079,13.543c0,0,0.353,1.828-0.424,5.119c-1.058,4.482-3.545,8.464-6.898,11.503L24.85,48L7.402,32.165c-3.353-3.038-5.84-7.021-6.898-11.503c-0.777-3.291-0.424-5.119-0.424-5.119C0.734,8.179,5.936,2,13.159,2C18.522,2,22.832,5.343,24.85,10.126z",attrs: commonAttrs,label: "path",});// polygon 多邊形graph.addNode({shape: "polygon",x: 60,y: 150,width: 40,height: 40,points: "100,10 40,198 190,78 10,78 160,198",attrs: commonAttrs,label: "polygon",});// polyline 折線graph.addNode({shape: "polyline",x: 180,y: 150,width: 40,height: 40,label: "polyline",attrs: {body: {...commonAttrs.body,refPoints: "0,0 0,10 10,10 10,0",},label: commonAttrs.label,},});// image 圖片graph.addNode({shape: "image",x: 290,y: 150,width: 60,height: 40,imageUrl:"https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg",label: "image",attrs: commonAttrs,});
2.3?定制節(jié)點(diǎn)
使用 Graph.registerNode(NodeName, options, true) 注冊節(jié)點(diǎn)。
Graph.registerNode("custom-node",{inherit: "rect", // 繼承于 rect 節(jié)點(diǎn)width: 100,height: 40,markup: [{tagName: "rect", // 標(biāo)簽名稱selector: "body", // 選擇器},{tagName: "image",selector: "img",},{tagName: "text",selector: "label",},],attrs: {body: {stroke: "#8f8f8f",strokeWidth: 1,fill: "#fff",rx: 6,ry: 6,},img: {"xlink:href":"https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png",width: 16,height: 16,x: 12,y: 12,},},},true);const source = graph.addNode({shape: "custom-node", // 可以直接使用上面注冊過的 shapex: 40,y: 40,label: "hello",});const target = graph.addNode({shape: "custom-node",x: 160,y: 180,label: "world",});graph.addEdge({source,target,attrs: {line: {stroke: "#8f8f8f",strokeWidth: 1,},},});
2.4?修改節(jié)點(diǎn)
node.prop(path, value) 修改結(jié)構(gòu),node.attr(path, value) 修改樣式。
const node = graph.addNode({shape: 'rect',width: 100,height: 40,x: 100,y: 100,label: 'edge',})console.log(node.prop())// 結(jié)果{"angle": 0,"position": {"x": 100,"y": 100},"size": {"width": 100,"height": 40},"attrs": {"text": {"fontSize": 14,"fill": "#000000","refX": 0.5,"refY": 0.5,"textAnchor": "middle","textVerticalAnchor": "middle","fontFamily": "Arial, helvetica, sans-serif","text": "node"},"rect": {"fill": "#ffffff","stroke": "#333333","strokeWidth": 2},"body": {"refWidth": "100%","refHeight": "100%"}},"visible": true,"shape": "rect","id": "ab47cadc-4104-457c-971f-50fbb077508a","zIndex": 1}node.prop('size', { width: 120, height: 50 }) // 修改 x 坐標(biāo)node.attr('rect/fill', '#ccc') // 修改填充色,等價(jià)于 node.prop('attrs/rect/fill', '#ccc')
3. 邊
3.1 添加邊
除了從 Cell 繼承屬性外,還支持以下選項(xiàng)
source 源節(jié)點(diǎn)或起始點(diǎn)。
target 目標(biāo)節(jié)點(diǎn)或目標(biāo)點(diǎn)。
vertices 路徑點(diǎn)。
router 路由。
connector 連接器。
labels 標(biāo)簽。
defaultLabel 默認(rèn)標(biāo)簽。
graph.addEdge({shape: "edge",source: "node1",target: "node2",});
3.2 配置邊
3.2.1 source/target
邊的源和目標(biāo)節(jié)點(diǎn)(點(diǎn))
graph.addEdge({source: rect1, // 源節(jié)點(diǎn)target: rect2, // 目標(biāo)節(jié)點(diǎn)});graph.addEdge({source: "rect1", // 源節(jié)點(diǎn) IDtarget: "rect2", // 目標(biāo)節(jié)點(diǎn) ID});graph.addEdge({source: { cell: rect1, port: "out-port-1" }, // 源節(jié)點(diǎn)和連接樁 IDtarget: { cell: "rect2", port: "in-port-1" }, // 目標(biāo)節(jié)點(diǎn) ID 和連接樁 ID});graph.addEdge({source: "rect1", // 源節(jié)點(diǎn) IDtarget: { x: 100, y: 120 }, // 目標(biāo)點(diǎn)});
3.2.2 vertices
路徑點(diǎn)。邊從起始點(diǎn)開始,按順序經(jīng)過路徑點(diǎn),最后到達(dá)終止點(diǎn)。
graph.addEdge({source: rect1,target: rect2,vertices: [{ x: 100, y: 200 },{ x: 300, y: 120 },],});
3.2.3 router
路由 router 將對(duì) vertices 進(jìn)一步處理,并在必要時(shí)添加額外的點(diǎn),然后返回處理后的點(diǎn)。例如,經(jīng)過 orth 路由處理后,邊的每一條鏈接線段都是水平或垂直的。
內(nèi)置路由:normal、orth、oneSide、manhattan、metro、er、自定義路由
graph.addEdge({source: rect1,target: rect2,vertices: [{ x: 100, y: 200 },{ x: 300, y: 120 },],// 如果沒有 args 參數(shù),可以簡寫為 router: 'orth'router: {name: "orth",args: {},},});
3.2.4 connector
連接器 connector 將路由 router 返回的點(diǎn)加工成渲染邊所需要的 pathData。例如,rounded 連接器將連線之間的倒角處理為圓弧倒角。
內(nèi)置連接器:normal、rounded、smooth、jumpover、自定義連接器
graph.addEdge({source: rect1,target: rect2,vertices: [{ x: 100, y: 200 },{ x: 300, y: 120 },],router: "orth",// 如果沒有 args 參數(shù),可以簡寫寫 connector: 'rounded'connector: {name: "rounded",args: {},},});
3.2.5 labels
用于設(shè)置標(biāo)簽文本、位置、樣式等。通過數(shù)組形式支持多標(biāo)簽,labels 指定的每一項(xiàng)都將與 defaultLabel 進(jìn)行 merge 后使用。
const edge = graph.addEdge({source: rect1,target: rect2,labels: [{attrs: {label: {text: "edge",},},},],});// 或const edge = graph.addEdge({source: rect1,target: rect2,labels: ["edge"], // 通過 labels 可以設(shè)置多個(gè)標(biāo)簽,當(dāng)只設(shè)置標(biāo)簽文本是可以簡化為此寫法});// 或const edge = graph.addEdge({source: rect1,target: rect2,label: "edge", // 通過 label 設(shè)置單個(gè)標(biāo)簽,當(dāng)只設(shè)置標(biāo)簽文本是可以簡化為此寫法});
3.2.6 defaultLabel
默認(rèn)標(biāo)簽。默認(rèn)標(biāo)簽可以簡化標(biāo)簽配置項(xiàng),labels 指定的每一項(xiàng)都將與 defaultLabel 進(jìn)行 merge 后使用。
3.3 使用箭頭
我們定義了 sourceMarker 和 targetMarker 兩個(gè)特殊屬性來為邊定制起始和終止箭頭。例如,對(duì) Shape.Edge 我們可以通過 line 選擇器來指定起始和終止箭頭。
3.3.1 內(nèi)置箭頭
block、classic、diamond、cross、async、path、circle、circlePlus、ellipse
graph.addEdge({shape: "edge",sourece: [100, 100],target: [500, 500],attrs: {line: {sourceMarker: "block", // 實(shí)心箭頭targetMarker: {name: "ellipse", // 橢圓rx: 10, // 橢圓箭頭的 x 半徑ry: 6, // 橢圓箭頭的 y 半徑},},},});
3.3.2 自定義箭頭
我們也可以通過 tagName 指定的 SVG 元素來渲染箭頭,例如下面我們使用 <path> 元素來渲染箭頭,箭頭默認(rèn)繼承邊的填充色 fill 和邊框色 stroke。
graph.addEdge({shape: "edge",sourece: [100, 100],target: [500, 500],attrs: {line: {sourceMarker: {tagName: "path",d: "M 20 -10 0 0 20 10 Z",},targetMarker: {tagName: "path",fill: "yellow", // 使用自定義填充色stroke: "green", // 使用自定義邊框色strokeWidth: 2,d: "M 20 -10 0 0 20 10 Z",},},},});
3.4 定制邊
和節(jié)點(diǎn)一樣,我們可以通過 markup 和 attrs 來定制邊的形狀和樣式,也可以注冊自定義邊來達(dá)到復(fù)用效果。
Graph.registerEdge("double-edge", {inherit: "edge",markup: [{tagName: "path",selector: "outline",attrs: {fill: "none",},},{tagName: "path",selector: "line",attrs: {fill: "none",cursor: "pointer",},},],attrs: {line: {connection: true,stroke: "#dddddd",strokeWidth: 4,strokeLinejoin: "round",targetMarker: {tagName: "path",stroke: "#000000",d: "M 10 -3 10 -10 -2 0 10 10 10 3",},},outline: {connection: true,stroke: "#000000",strokeWidth: 6,strokeLinejoin: "round",},},});graph.addEdge({shape: "double-edge",source: [100, 100],target: [400, 100],});
3.5 修改邊
和節(jié)點(diǎn)類似,在渲染完成之后,我們還可以通過 API 修改邊的所有屬性。edge.prop(path, value) 修改邊布局,edge.attr(path, value) 修改邊樣式
const edge = graph.addEdge({source: [200, 140],target: [500, 140],label: 'edge',})console.log(edge.prop())// 輸出結(jié)果{"shape": "edge","attrs": {"lines": {"connection": true,"strokeLinejoin": "round"},"wrap": {"strokeWidth": 10},"line": {"stroke": "#333","strokeWidth": 2,"targetMarker": "classic"}},"id": "9d5e4f54-1ed3-429e-8d8c-a1526cff2cd8","source": {"x": 200,"y": 140},"target": {"x": 500,"y": 140},"labels": [{"attrs": {"label": {"text": "edge"}}}],"zIndex": 1}edge.prop('target', { x: 300, y: 300 }) // 修改終點(diǎn)edge.attr('line/stroke', '#ccc') // 修改邊顏色,等價(jià)于 edge.prop('attrs/line/stroke', '#ccc')
4. 連接樁
4.1 配置連接樁
在注冊節(jié)點(diǎn)的時(shí)候通過 ports 配置連接樁
Graph.registerNode("custom-node-width-port",{inherit: "rect",width: 100,height: 40,attrs: {body: {stroke: "#8f8f8f",strokeWidth: 1,fill: "#fff",rx: 6,ry: 6,},},ports: {groups: {top: {position: "top",attrs: {circle: {magnet: true,stroke: "#8f8f8f",r: 5,},},},bottom: {position: "bottom",attrs: {circle: {magnet: true,stroke: "#8f8f8f",r: 5,},},},},},},true);const source = graph.addNode({shape: "custom-node-width-port",x: 40,y: 40,label: "hello",ports: {items: [{id: "port_1",group: "bottom",},{id: "port_2",group: "bottom",},],},});const target = graph.addNode({shape: "custom-node-width-port",x: 160,y: 180,label: "world",ports: {items: [{id: "port_3",group: "top",},{id: "port_4",group: "top",},],},});graph.addEdge({source: { cell: source, port: "port_2" },target: { cell: target, port: "port_3" },attrs: {line: {stroke: "#8f8f8f",strokeWidth: 1,},},});
4.2 修改連接樁
節(jié)點(diǎn)上有豐富的 API 對(duì)連接樁進(jìn)行增、刪、改操作。
// 添加連接樁node.addPort({group: "top",attrs: {text: {text: "xx",},},});// 刪除連接樁node.removePort(portId);// 更新連接樁node.portProp(portId, "attrs/circle/stroke", color);
4.3 連接樁位置
連接樁布局算法只能通過 groups 中的 position 選項(xiàng)來指定
absolute 絕對(duì)定位。
left 矩形節(jié)點(diǎn)左側(cè)均勻分布。
right 矩形節(jié)點(diǎn)右側(cè)均勻分布。
top 矩形節(jié)點(diǎn)頂部均勻分布。
bottom 矩形節(jié)點(diǎn)底部均勻分布。
line 沿指定的線均勻分布。
ellipse 沿橢圓圓弧分布。
ellipseSpread 沿橢圓均勻分布。
4.4 連接樁標(biāo)簽位置
在 groups 的 label.position 選項(xiàng)和節(jié)點(diǎn)的 items.label.position 選項(xiàng)中都可以指定標(biāo)簽的位置。
left 標(biāo)簽位于連接樁左側(cè)。
right 標(biāo)簽位于連接樁右側(cè)。
top 標(biāo)簽位于連接樁上方。
bottom 標(biāo)簽位于連接樁下方。
inside 標(biāo)簽位于節(jié)點(diǎn)內(nèi)圍(靠近邊線的內(nèi)側(cè))。
outside 標(biāo)簽位于節(jié)點(diǎn)外圍(靠近邊線的外側(cè))。
insideOriented 標(biāo)簽位于節(jié)點(diǎn)內(nèi)圍,而且根據(jù)所在方位自動(dòng)調(diào)整文本的方向。
outsideOriented 標(biāo)簽位于節(jié)點(diǎn)外圍,而且根據(jù)所在方位自動(dòng)調(diào)整文本的方向。
radial 標(biāo)簽位于圓形或橢圓形節(jié)點(diǎn)的外圍。
radialOriented 標(biāo)簽位于圓形或橢圓形節(jié)點(diǎn)的外圍,并使標(biāo)簽文本自動(dòng)沿圓弧方向旋轉(zhuǎn)。
5. 交互
5.1 連線
連線交互規(guī)則都是通過 connecting 配置來完成。下面介紹一些常用的功能。
5.1.1 allowXXX
可以通過 allowXXX 配置來定義連線能否連接到對(duì)應(yīng)的位置。默認(rèn)支持以下項(xiàng):
allowBlank:是否允許連接到畫布空白位置的點(diǎn),默認(rèn)為 true。
allowLoop:是否允許創(chuàng)建循環(huán)連線,即邊的起始節(jié)點(diǎn)和終止節(jié)點(diǎn)為同一節(jié)點(diǎn),默認(rèn)為 true。
allowNode:是否允許邊連接到節(jié)點(diǎn)(非節(jié)點(diǎn)上的連接樁),默認(rèn)為 true。
allowEdge:是否允許邊連接到另一個(gè)邊,默認(rèn)為 true。
allowPort:是否允許邊連接到連接樁,默認(rèn)為 true。
allowMulti:是否允許在相同的起始節(jié)點(diǎn)和終止之間創(chuàng)建多條邊,默認(rèn)為 true。
new Graph({connecting: {allowNode: true, // boolean},});// 函數(shù)形式,多用于動(dòng)態(tài)控制連接限制new Graph({connecting: {allowNode(args) {return true;},},});
5.1.2 router/connector
在邊教程中我們知道,可以在添加邊的時(shí)候指定 router 和 connector,如果整個(gè)畫布中大部分邊的 router 或者 connector 是一樣的,我們可以直接配置在 connecting 中,這樣就可以避免在邊中重復(fù)配置。
new Graph({connecting: {router: "orth",connector: "rounded",},});
5.1.3 createEdge
在上面的 demo 中,我們可以從節(jié)點(diǎn)、連接樁拉出一條連線出來,那你可能會(huì)問,什么樣的元素能拉出連線呢?這是 X6 設(shè)計(jì)非常巧妙的一個(gè)地方,只要具備 magnet=true 屬性的元素,都可以拉出連線。而且在 connecting 中可以通過 createEdge 方法配置拉出連線的樣式。
new Graph({connecting: {createEdge() {return this.createEdge({shape: "edge",attrs: {line: {stroke: "#8f8f8f",strokeWidth: 1,},},});},},});
5.2 組合
有時(shí)候我們需要將一個(gè)節(jié)點(diǎn)拖動(dòng)到另一個(gè)節(jié)點(diǎn)中,使其成為另一節(jié)點(diǎn)的子節(jié)點(diǎn),這時(shí)我們可以通過 embedding 選項(xiàng)來開啟,在節(jié)點(diǎn)被移動(dòng)時(shí)通過 findParent 指定的方法返回父節(jié)點(diǎn)。
const graph = new Graph({embedding: {enabled: true,findParent({ node }) {// 獲取移動(dòng)節(jié)點(diǎn)的包圍盒const bbox = node.getBBox()// 找到 data 中配置 { parent: true } 的節(jié)點(diǎn),并且移動(dòng)節(jié)點(diǎn)和找到的節(jié)點(diǎn)包圍盒相交時(shí),返回 truereturn this.getNodes().filter((node) => {const data = node.getData<{ parent: boolean }>()if (data && data.parent) {const targetBBox = node.getBBox()return bbox.isIntersectWithRect(targetBBox)}return false})},},})
5.3 高亮
可以通過 highlighting 選項(xiàng)來指定觸發(fā)某種交互時(shí)的高亮樣式,如:
new Graph({highlighting: {// 連接樁可以被連接時(shí)在連接樁外圍圍渲染一個(gè)包圍框magnetAvailable: {name: "stroke",args: {attrs: {fill: "#fff",stroke: "#A4DEB1",strokeWidth: 4,},},},// 連接樁吸附連線時(shí)在連接樁外圍圍渲染一個(gè)包圍框magnetAdsorbed: {name: "stroke",args: {attrs: {fill: "#fff",stroke: "#31d0c6",strokeWidth: 4,},},},},});
支持的 highlighting 配置項(xiàng)有:
default 默認(rèn)高亮選項(xiàng),當(dāng)以下幾種高亮配置缺省時(shí)被使用。
embedding 拖動(dòng)節(jié)點(diǎn)進(jìn)行嵌入操作過程中,節(jié)點(diǎn)可以被嵌入時(shí)被使用。
nodeAvailable 連線過程中,節(jié)點(diǎn)可以被鏈接時(shí)被使用。
magnetAvailable 連線過程中,連接樁可以被鏈接時(shí)被使用。
magnetAdsorbed 連線過程中,自動(dòng)吸附到連接樁時(shí)被使用。
5.4 交互限制
可以通過配置 interacting 來啟動(dòng)、禁用一些元素的交互行為,如果畫布上元素純預(yù)覽,不能進(jìn)行任何交互,可以直接設(shè)置為 false。
new Graph({interacting: false,});
如果需要更細(xì)節(jié)的定義允許哪些交互、禁用哪些交互,我們可以針對(duì)不同的屬性值進(jìn)行配置,支持的屬性包括:
nodeMovable 節(jié)點(diǎn)是否可以被移動(dòng)。
magnetConnectable 當(dāng)在具有 magnet 屬性的元素上按下鼠標(biāo)開始拖動(dòng)時(shí),是否觸發(fā)連線交互。
edgeMovable 邊是否可以被移動(dòng)。
edgeLabelMovable 邊的標(biāo)簽是否可以被移動(dòng)。
arrowheadMovable 邊的起始/終止箭頭(在使用 arrowhead 工具后)是否可以被移動(dòng)。
vertexMovable 邊的路徑點(diǎn)是否可以被移動(dòng)。
vertexAddable 是否可以添加邊的路徑點(diǎn)。
vertexDeletable 邊的路徑點(diǎn)是否可以被刪除。
6. 事件
6.1 視圖交互事件
通過鼠標(biāo)、鍵盤或者各種可交互的組件與應(yīng)用產(chǎn)生交互時(shí)觸發(fā)的事件。
6.1.1 鼠標(biāo)事件
單擊 cell:click node:click node:port:click edge:click blank:click
雙擊 cell:dblclick node:dblclick node:port:dblclick edge:dblclick blank:dblclick
右鍵 cell:contextmenu node:contextmenu node:port:contextmenu edge:contextmenu blank:contextmenu
鼠標(biāo)按下 cell:mousedown node:mousedown node:port:mousedown edge:mousedown blank:mousedown
移動(dòng)鼠標(biāo) cell:mousemove node:mousemove node:port:mousemove edge:mousemove blank:mousemove
鼠標(biāo)抬起 cell:mouseup node:mouseup node:port:mouseup edge:mouseup blank:mouseup
鼠標(biāo)滾輪 cell:mousewheel node:mousewheel - edge:mousewheel blank:mousewheel
鼠標(biāo)進(jìn)入 cell:mouseenter node:mouseenter node:port:mouseenter edge:mouseenter graph:mouseenter
鼠標(biāo)離開 cell:mouseleave node:mouseleave node:port:mouseleave edge:mouseleave graph:mouseleave
除了 mouseenter 和 mouseleave 外,事件回調(diào)函數(shù)的參數(shù)都包含鼠標(biāo)相對(duì)于畫布的位置 x、y 和鼠標(biāo)事件對(duì)象 e 等參數(shù)。
graph.on("cell:click", ({ e, x, y, cell, view }) => {});graph.on("node:click", ({ e, x, y, node, view }) => {});graph.on("edge:click", ({ e, x, y, edge, view }) => {});graph.on("blank:click", ({ e, x, y }) => {});graph.on("cell:mouseenter", ({ e, cell, view }) => {});graph.on("node:mouseenter", ({ e, node, view }) => {});graph.on("edge:mouseenter", ({ e, edge, view }) => {});graph.on("graph:mouseenter", ({ e }) => {});
6.1.2 自定義點(diǎn)擊事件
我們可以在節(jié)點(diǎn)/邊的 DOM 元素上添加自定義屬性 event 或 data-event 來監(jiān)聽該元素的點(diǎn)擊事件,例如:
node.attr({// 表示一個(gè)刪除按鈕,點(diǎn)擊時(shí)刪除該節(jié)點(diǎn)image: {event: "node:delete",xlinkHref: "trash.png",width: 20,height: 20,},});
可以通過綁定的事件名 node:delete 或通用的 cell:customevent、node:customevent、edge:customevent 事件名來監(jiān)聽。
graph.on("node:delete", ({ view, e }) => {e.stopPropagation();view.cell.remove();});graph.on("node:customevent", ({ name, view, e }) => {if (name === "node:delete") {e.stopPropagation();view.cell.remove();}});
6.1.3 畫布縮放/平移
事件名 回調(diào)參數(shù) 說明
scale { sx: number; sy: number; ox: number; oy: number } 縮放畫布時(shí)觸發(fā),sx 和 sy 是縮放比例,ox 和 oy 是縮放中心。
resize { width: number; height: number } 改變畫布大小時(shí)觸發(fā),width 和 height 是畫布大小。
translate { tx: number; ty: number } 平移畫布時(shí)觸發(fā),tx 和 ty 分別是 X 和 Y 軸的偏移量。
graph.on("scale", ({ sx, sy, ox, oy }) => {});graph.on("resize", ({ width, height }) => {});graph.on("translate", ({ tx, ty }) => {});
6.1.4 節(jié)點(diǎn)或邊平移
事件名 回調(diào)參數(shù) 說明
node:move { e: Dom.MouseDownEvent; x: number; y: number; node: Node; view: NodeView } 開始移動(dòng)節(jié)點(diǎn)時(shí)觸發(fā)。
node:moving { e: Dom.MouseMoveEvent; x: number; y: number; node: Node; view: NodeView } 移動(dòng)節(jié)點(diǎn)時(shí)觸發(fā)。
node:moved { e: Dom.MouseUpEvent; x: number; y: number; node: Node; view: NodeView } 移動(dòng)節(jié)點(diǎn)后觸發(fā)。
edge:move { e: Dom.MouseDownEvent; x: number; y: number; node: Node; view: NodeView } 開始移動(dòng)邊時(shí)觸發(fā)。
edge:moving { e: Dom.MouseMoveEvent; x: number; y: number; node: Node; view: NodeView } 移動(dòng)邊時(shí)觸發(fā)。
edge:moved { e: Dom.MouseUpEvent; x: number; y: number; node: Node; view: NodeView } 移動(dòng)邊后觸發(fā)。
參數(shù)中的 x 和 y 是鼠標(biāo)相對(duì)于畫布的坐標(biāo)。
graph.on("node:moved", ({ e, x, y, node, view }) => {});
6.1.5 節(jié)點(diǎn)嵌入
事件名 回調(diào)參數(shù) 說明
node:embed { e: Dom.MouseDownEvent; x: number; y: number; node: Node; view: NodeView, currentParent: Node } 開啟嵌入,在開始拖動(dòng)節(jié)點(diǎn)時(shí)觸發(fā)。
node:embedding { e: Dom.MouseMoveEvent; x: number; y: number; node: Node; view: NodeView, currentParent: Node, candidateParent: Node } 尋找目標(biāo)節(jié)點(diǎn)過程中觸發(fā)。
node:embedded { e: Dom.MouseUpEvent; x: number; y: number; node: Node; view: NodeView, previousParent: Node, currentParent: Node } 完成節(jié)點(diǎn)嵌入后觸發(fā)。
6.1.6 邊連接/取消連接
當(dāng)拖動(dòng)邊的起始/終止箭頭將邊連接到節(jié)點(diǎn)/邊或者將邊從節(jié)點(diǎn)/邊上分離后觸發(fā) edge:connected。
我們可以通過 isNew 來判斷連線完成后,對(duì)應(yīng)的邊是否是新創(chuàng)建的邊。比如從一個(gè)連接樁開始,創(chuàng)建了一條邊并連接到另一個(gè)節(jié)點(diǎn)/連接樁,此時(shí) isNew 就為 true。
graph.on("edge:connected", ({ isNew, edge }) => {if (isNew) {// 對(duì)新創(chuàng)建的邊進(jìn)行插入數(shù)據(jù)庫等持久化操作}});
特別注意的是,參數(shù)中的 previous... 是記錄操作終端在連接/取消連接之前的狀態(tài),并不是指 sourceCell,在創(chuàng)建新邊后獲取 sourceCell 時(shí)不能使用 previousCell,正確的使用方式是:
graph.on("edge:connected", ({ isNew, edge }) => {if (isNew) {const source = edge.getSourceCell();}});
6.2 節(jié)點(diǎn)/邊
6.2.1 添加/刪除/修改
當(dāng)節(jié)點(diǎn)/邊被添加到畫布時(shí),觸發(fā)以下事件:
added
cell:added
node:added(僅當(dāng) cell 是節(jié)點(diǎn)時(shí)才觸發(fā))
edge:added(僅當(dāng) cell 是邊時(shí)才觸發(fā))
當(dāng)節(jié)點(diǎn)/邊被移除時(shí),觸發(fā)以下事件:
removed
cell:removed
node:removed(僅當(dāng) cell 是節(jié)點(diǎn)時(shí)才觸發(fā))
edge:removed(僅當(dāng) cell 是邊時(shí)才觸發(fā))
當(dāng)節(jié)點(diǎn)/邊發(fā)生任何改變時(shí),觸發(fā)以下事件:
changed
cell:changed
node:changed(僅當(dāng) cell 是節(jié)點(diǎn)時(shí)才觸發(fā))
edge:changed(僅當(dāng) cell 是邊時(shí)才觸發(fā))
可以在節(jié)點(diǎn)/邊上監(jiān)聽:
cell.on("added", ({ cell, index, options }) => {});cell.on("removed", ({ cell, index, options }) => {});cell.on("changed", ({ cell, options }) => {});
或者在 Graph 上監(jiān)聽:
graph.on("cell:added", ({ cell, index, options }) => {});graph.on("cell:removed", ({ cell, index, options }) => {});graph.on("cell:changed", ({ cell, options }) => {});graph.on("node:added", ({ node, index, options }) => {});graph.on("node:removed", ({ node, index, options }) => {});graph.on("node:changed", ({ node, options }) => {});graph.on("edge:added", ({ edge, index, options }) => {});graph.on("edge:removed", ({ edge, index, options }) => {});graph.on("edge:changed", ({ edge, options }) => {});
6.2.2 change:xxx
當(dāng)調(diào)用 setXxx(val, options) 和 removeXxx(options) 方法去改變節(jié)點(diǎn)/邊的數(shù)據(jù)時(shí),并且 options.silent 不為 true 時(shí),都將觸發(fā)對(duì)應(yīng)的 change 事件,并觸發(fā)節(jié)點(diǎn)/邊重繪。例如:
cell.setZIndex(2);cell.setZIndex(2, { silent: false });cell.setZIndex(2, { anyKey: "anyValue" });
6.3 動(dòng)畫
transition:start 動(dòng)畫開始時(shí)觸發(fā)
transition:progress 動(dòng)畫過程中觸發(fā)
transition:complete 動(dòng)畫完成時(shí)觸發(fā)
transition:stop 動(dòng)畫被停止時(shí)觸發(fā)
transition:finish 動(dòng)畫完成或被停止時(shí)觸發(fā)
cell.on("transition:start", (args: Animation.CallbackArgs) => {});cell.on("transition:progress", (args: Animation.ProgressArgs) => {});cell.on("transition:complete", (args: Animation.CallbackArgs) => {});cell.on("transition:stop", (args: Animation.StopArgs) => {});cell.on("transition:finish", (args: Animation.CallbackArgs) => {});graph.on("cell:transition:start", (args: Animation.CallbackArgs) => {});graph.on("cell:transition:progress", (args: Animation.ProgressArgs) => {});graph.on("cell:transition:complete", (args: Animation.CallbackArgs) => {});graph.on("cell:transition:stop", (args: Animation.StopArgs) => {});graph.on("cell:transition:finish", (args: Animation.CallbackArgs) => {});graph.on("node:transition:start", (args: Animation.CallbackArgs) => {});graph.on("node:transition:progress", (args: Animation.ProgressArgs) => {});graph.on("node:transition:complete", (args: Animation.CallbackArgs) => {});graph.on("node:transition:stop", (args: Animation.StopArgs) => {});graph.on("node:transition:finish", (args: Animation.CallbackArgs) => {});graph.on("edge:transition:start", (args: Animation.CallbackArgs) => {});graph.on("edge:transition:progress", (args: Animation.ProgressArgs) => {});graph.on("edge:transition:complete", (args: Animation.CallbackArgs) => {});graph.on("edge:transition:stop", (args: Animation.StopArgs) => {});graph.on("edge:transition:finish", (args: Animation.CallbackArgs) => {});
6.4?視圖
由于 X6 實(shí)現(xiàn)了異步的渲染調(diào)度算法,所以節(jié)點(diǎn)的添加不一定意味著掛載到畫布上。節(jié)點(diǎn)在被掛載到畫布時(shí)以及從畫布上卸載時(shí)會(huì)分別觸發(fā)單獨(dú)的事件。
事件名 回調(diào)參數(shù) 說明
view:mounted { view: CellView } 節(jié)點(diǎn)被掛載到畫布上時(shí)觸發(fā)。
view:unmounted { view: CellView } 節(jié)點(diǎn)從畫布上卸載時(shí)觸發(fā)。
graph.on("view:mounted", ({ view }) => {});graph.on("view:unmounted", ({ view }) => {});
大家還有經(jīng)常需要在調(diào)用 fromJSON 或者 resetCells 后監(jiān)聽畫布完成渲染事件,這時(shí)候可以使用 render:done 事件來監(jiān)聽
graph.on('render:done', () => {// pass})graph.fromJSON([...])
7. 數(shù)據(jù)
7.1 導(dǎo)出
我們可以調(diào)用 graph.toJSON() 方法來導(dǎo)出圖中的節(jié)點(diǎn)和邊,返回一個(gè)具有 { cells: [] } 結(jié)構(gòu)的對(duì)象,其中 cells 數(shù)組按渲染順序保存節(jié)點(diǎn)和邊。
其中,導(dǎo)出的節(jié)點(diǎn)結(jié)構(gòu)如下:
{id: string,shape: string,position: {x: numbery: number},size: {width: numberheight: number},attrs: object,zIndex: number,}
邊的結(jié)構(gòu)如下:
{id: string,shape: string,source: object,target: object,attrs: object,zIndex: number,}
7.2 導(dǎo)入
支持節(jié)點(diǎn)/邊元數(shù)據(jù)數(shù)組 graph.fromJSON(cells: (Node.Metadata | Edge.Metadata)[])。
graph.fromJSON([{id: "node1",x: 40,y: 40,width: 100,height: 40,label: "Hello",shape: "rect",},{id: "node2",x: 40,y: 40,width: 100,height: 40,label: "Hello",shape: "ellipse",},{id: "edge1",source: "node1",target: "node2",shape: "edge",},]);
或者提供一個(gè)包含 cells、nodes、edges 的對(duì)象,按照 [...cells, ...nodes, ...edges] 順序渲染。
graph.fromJSON({nodes: [],edges: [],});
通常,我們通過 graph.fromJSON(...) 來渲染 graph.toJSON() 導(dǎo)出的數(shù)據(jù)。