流程圖控件GoJS教程:節(jié)點(diǎn)中的端口
GoJS是一款功能強(qiáng)大,快速且輕量級(jí)的流程圖控件,可幫助你在JavaScript 和HTML5 Canvas程序中創(chuàng)建流程圖,且極大地簡(jiǎn)化您的JavaScript / Canvas 程序。
GoJS現(xiàn)已更新至最新版本2.1發(fā)布,添加了動(dòng)畫功能,修復(fù)了一些bug,增強(qiáng)用戶體驗(yàn),趕快下載試試吧~
節(jié)點(diǎn)中的端口
盡管您可以控制鏈接在節(jié)點(diǎn)上的連接位置(在特定位置,沿著一個(gè)或多個(gè)側(cè)面或在與邊緣的相交處),但是有時(shí)您希望在鏈接上使用不同的邏輯和圖形位置應(yīng)該連接。鏈接可以連接的元素稱為 端口。節(jié)點(diǎn)中可以有任意數(shù)量的端口。默認(rèn)情況下,只有一個(gè)端口,即整個(gè)節(jié)點(diǎn),這導(dǎo)致將整個(gè)節(jié)點(diǎn)用作端口的效果,如您在所有前面的示例中所看到的。
要聲明Node中的特定元素是端口,請(qǐng)將GraphObject.portId屬性設(shè)置為字符串。請(qǐng)注意,與端口或鏈接相關(guān)的屬性可以應(yīng)用于節(jié)點(diǎn)的可視樹中的任何元素,這就是為什么它們是GraphObject而不是Node的屬性的原因。
類似于端口的GraphObjects只能位于Node或Group中,而不能位于Link或Adornment或簡(jiǎn)單Part中。因此,沒有理由嘗試在Link中的任何對(duì)象上設(shè)置GraphObject.portId。
單端口
在許多情況下,您想考慮與整個(gè)節(jié)點(diǎn)在邏輯上相關(guān)的鏈接,但是您不希望鏈接到整個(gè)節(jié)點(diǎn)。在這種情況下,每個(gè)節(jié)點(diǎn)只有一個(gè)端口,但是您不希望整個(gè)節(jié)點(diǎn)都充當(dāng)一個(gè)端口。
例如,考慮當(dāng)整個(gè)節(jié)點(diǎn)以一種通用方式充當(dāng)端口時(shí),鏈路如何連接到節(jié)點(diǎn)。該GraphObject.fromSpot和GraphObject.toSpot是在雙方的中段。因?yàn)檎麄€(gè)節(jié)點(diǎn)的高度都包含文本標(biāo)簽,所以邊的中間不是“圖標(biāo)”的中間,在這種情況下,該“圖標(biāo)”是一個(gè)圓。
diagram.nodeTemplate = $(go.Node, "Vertical", { fromSpot: go.Spot.Right, toSpot: go.Spot.Left }, // port properties on the node $(go.Shape, "Ellipse", { width: 30, height: 30, fill: "green" }), $(go.TextBlock, { font: "20px sans-serif" }, new go.Binding("text", "key")) ); var nodeDataArray = [ { key: "Alpha" }, { key: "Beta" } ]; var linkDataArray = [ { from: "Alpha", to: "Beta" } ]; diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
這種外觀看起來或行為不正確。確實(shí),我們希望鏈接連接到圓形Shape。
如果要讓特定元素充當(dāng)端口而不是整個(gè)節(jié)點(diǎn),則只需將其GraphObject.portId設(shè)置為空字符串即可。空字符串是默認(rèn)端口的名稱。
在此示例中,我們?cè)趫A形上設(shè)置GraphObject.portId。請(qǐng)注意,我們也將其他與端口相關(guān)的屬性(例如端口斑點(diǎn))移到了該對(duì)象。
diagram.nodeTemplate = $(go.Node, "Vertical", $(go.Shape, "Ellipse", { width: 30, height: 30, fill: "green", portId: "", // now the Shape is the port, not the whole Node fromSpot: go.Spot.Right, // port properties go on the port! toSpot: go.Spot.Left }), $(go.TextBlock, { font: "20px sans-serif" }, new go.Binding("text", "key")) ); var nodeDataArray = [ { key: "Alpha" }, { key: "Beta" } ]; var linkDataArray = [ { from: "Alpha", to: "Beta" } ]; diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
注意鏈接如何通過忽略文本標(biāo)簽很好地連接圓形。
一般端口
在節(jié)點(diǎn)中需要多個(gè)端口的圖表中也很常見。端口數(shù)量甚至可能動(dòng)態(tài)變化。
為了使鏈接數(shù)據(jù)對(duì)象能夠區(qū)分鏈接應(yīng)該連接到哪個(gè)端口,GraphLinksModel支持兩個(gè)附加的數(shù)據(jù)屬性,這些屬性標(biāo)識(shí)鏈接兩端節(jié)點(diǎn)中端口的名稱。 GraphLinksModel.getToKeyForLinkData標(biāo)識(shí)要連接的節(jié)點(diǎn); GraphLinksModel.getToPortIdForLinkData標(biāo)識(shí)節(jié)點(diǎn)內(nèi)的端口。同樣,GraphLinksModel.getFromKeyForLinkData和GraphLinksModel.getFromPortIdForLinkData標(biāo)識(shí)節(jié)點(diǎn)及其端口。
通常,GraphLinksModel假定不需要識(shí)別鏈接數(shù)據(jù)上的端口信息。如果要在鏈接數(shù)據(jù)上支持端口標(biāo)識(shí)符,則需要將GraphLinksModel.linkToPortIdProperty 和GraphLinksModel.linkFromPortIdProperty設(shè)置為鏈接數(shù)據(jù)屬性的名稱。如果未設(shè)置這些屬性,則所有端口標(biāo)識(shí)符都假定為空字符串,這是節(jié)點(diǎn)的一個(gè)默認(rèn)端口的名稱。
如果已將任何元素上的GraphObject.portId設(shè)置或綁定為非空字符串,則需要使用GraphLinksModel并將GraphLinksModel.linkToPortIdProperty 和GraphLinksModel.linkFromPortIdProperty設(shè)置為鏈接數(shù)據(jù)上兩個(gè)屬性的名稱,或者將需要對(duì)鏈接模板中的portId名稱進(jìn)行硬編碼(即Link.fromPortId和Link.toPortId),以便用戶能夠與這些端口鏈接。
diagram.nodeTemplate = $(go.Node, "Auto", $(go.Shape, "Rectangle", { fill: "lightgray" }), $(go.Panel, "Table", $(go.RowColumnDefinition, { column: 0, alignment: go.Spot.Left}), $(go.RowColumnDefinition, { column: 2, alignment: go.Spot.Right }), $(go.TextBlock, // the node title { column: 0, row: 0, columnSpan: 3, alignment: go.Spot.Center, font: "bold 10pt sans-serif", margin: new go.Margin(4, 2) }, new go.Binding("text", "key")), $(go.Panel, "Horizontal", { column: 0, row: 1 }, $(go.Shape, // the "A" port { width: 6, height: 6, portId: "A", toSpot: go.Spot.Left }), $(go.TextBlock, "A") // "A" port label ), $(go.Panel, "Horizontal", { column: 0, row: 2 }, $(go.Shape, // the "B" port { width: 6, height: 6, portId: "B", toSpot: go.Spot.Left }), $(go.TextBlock, "B") // "B" port label ), $(go.Panel, "Horizontal", { column: 2, row: 1, rowSpan: 2 }, $(go.TextBlock, "Out"), // "Out" port label $(go.Shape, // the "Out" port { width: 6, height: 6, portId: "Out", fromSpot: go.Spot.Right }) ) ) ); diagram.linkTemplate = $(go.Link, { routing: go.Link.Orthogonal, corner: 3 }, $(go.Shape), $(go.Shape, { toArrow: "Standard" }) ); diagram.layout = $(go.LayeredDigraphLayout, { columnSpacing: 10 }); diagram.model = $(go.GraphLinksModel, { linkFromPortIdProperty: "fromPort", // required information: linkToPortIdProperty: "toPort", // identifies data property names nodeDataArray: [ { key: "Add1" }, { key: "Add2" }, { key: "Subtract1" } ], linkDataArray: [ { from: "Add1", fromPort: "Out", to: "Subtract1", toPort: "A" }, { from: "Add2", fromPort: "Out", to: "Subtract1", toPort: "B" } ] });
繪制新鏈接
將GraphObject.fromLinkable和GraphObject.toLinkable 屬性中的一個(gè)或兩個(gè)設(shè)置為true可使用戶以交互方式在端口之間繪制新鏈接。
要繪制新鏈接,請(qǐng)?jiān)凇?Out”端口上向下拖動(dòng)鼠標(biāo),將其移動(dòng)(拖動(dòng))到附近的輸入端口,然后向上拖動(dòng)鼠標(biāo)以完成鏈接。
diagram.nodeTemplate = $(go.Node, "Auto", $(go.Shape, "Rectangle", { fill: "lightgray" }), $(go.Panel, "Table", $(go.RowColumnDefinition, { column: 0, alignment: go.Spot.Left}), $(go.RowColumnDefinition, { column: 2, alignment: go.Spot.Right }), $(go.TextBlock, // the node title { column: 0, row: 0, columnSpan: 3, alignment: go.Spot.Center, font: "bold 10pt sans-serif", margin: new go.Margin(4, 2) }, new go.Binding("text", "key")), $(go.Panel, "Horizontal", { column: 0, row: 1 }, $(go.Shape, // the "A" port { width: 6, height: 6, portId: "A", toSpot: go.Spot.Left, toLinkable: true, toMaxLinks: 1 }), // allow user-drawn links from here $(go.TextBlock, "A") // "A" port label ), $(go.Panel, "Horizontal", { column: 0, row: 2 }, $(go.Shape, // the "B" port { width: 6, height: 6, portId: "B", toSpot: go.Spot.Left, toLinkable: true, toMaxLinks: 1 }), // allow user-drawn links from here $(go.TextBlock, "B") // "B" port label ), $(go.Panel, "Horizontal", { column: 2, row: 1, rowSpan: 2 }, $(go.TextBlock, "Out"), // "Out" port label $(go.Shape, // the "Out" port { width: 6, height: 6, portId: "Out", fromSpot: go.Spot.Right, fromLinkable: true }) // allow user-drawn links to here ) ) ); diagram.linkTemplate = $(go.Link, { routing: go.Link.Orthogonal, corner: 3 }, $(go.Shape), $(go.Shape, { toArrow: "Standard" }) ); diagram.layout = $(go.LayeredDigraphLayout, { columnSpacing: 10 }); diagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal; diagram.model = $(go.GraphLinksModel, { linkFromPortIdProperty: "fromPort", // required information: linkToPortIdProperty: "toPort", // identifies data property names nodeDataArray: [ { key: "Add1" }, { key: "Add2" }, { key: "Subtract1" } ], linkDataArray: [ // no predeclared links ] });
默認(rèn)情況下,用戶不得在任何一對(duì)端口之間沿相同方向繪制多個(gè)鏈接,也不能繪制將節(jié)點(diǎn)與其自身連接的鏈接。
如本示例所示, 通過將GraphObject.toMaxLinks設(shè)置為1,用戶最多可以繪制一個(gè)進(jìn)入該端口的鏈接。并且由于該端口元素的GraphObject.fromLinkable為false,因此用戶將無法連接從該端口發(fā)出的任何鏈接。
如果要阻止用戶將一個(gè)Link連接到一個(gè)以上的Link,無論方向如何,都需要實(shí)現(xiàn)LinkingBaseTool.linkValidation或Node.linkValidation謂詞。
=====================================================
想要購買GoJS正版授權(quán)的朋友可以咨詢慧都官方客服。
更多精彩內(nèi)容,歡迎關(guān)注下方的微信公眾號(hào),及時(shí)獲取產(chǎn)品最新資訊▼▼▼