go.js的基本使用方法詳解【與vue,react同理】
一、go.js的基本使用
引言:首先寫這篇文章是為了記錄一下自己用到的api,以及接觸到的設(shè)置方法,部分詳解有摘自其他博主的文章,我主要是在vue中使用,涉及到業(yè)務(wù)方面的就不過多解釋,react我也自測過,都是同一個套路,希望本篇文章能幫助到各位碼友?。?!
1.官方文檔
- 官方api: https://gojs.net/latest/api/
- 官方例子:https://gojs.net/latest/samples/orgChartStatic.html

- 左邊有許多例子,可以根據(jù)自己的需要挑選合適的例子使用
- 具體的設(shè)置api,比如按鈕,連接線什么的:https://gojs.net/latest/intro/buttons.html
2.安裝,以及去除水印的方法
npm install gojs --save
我目前裝的應(yīng)該現(xiàn)在最新版的 “gojs”: “^2.2.14”,
我在博客也搜到不少解決的方法,在這里就分享兩種方法:
第一種: 在node_modules中找到go.js,go.mjs,go-module.js路徑如下:node_modules/gojs/release/go.js,go.mjs,go-module.js (注意:最好是這三個文件都要改,有些碼友說設(shè)置了沒用,原因是只設(shè)置了go.js)
這一種也是我目前使用的方法: 在三個文件全局搜索 7ca11abfd022028846 然后將這一行的剩余部分全部刪除,下面是我已經(jīng)刪除后的照片:記得三個文件都要刪除


- 第二種方法:
搜索String.fromCharCode(a.charCodeAt(g)^b[(b[c]+b[d])%256]) 這段代碼后面會有個return f;

在return f 前加上以下代碼
// 注意了: 如果你是2022版本的話需要,將? 1998-2021 Northwoods Software 改成 ? 1998-2022 Northwoods Software
// 這個你可以在水印上查看是哪個年限以及哪個版本:
if(f.indexOf(‘GoJS 2.1 evaluation')>-1
|| f.indexOf(‘? 1998-2021 Northwoods Software')>-1
|| f.indexOf(‘Not for distribution or production use')>-1
|| f.indexOf(‘gojs.net')>-1
){
return ‘';
}else{
return f
}
查看水印年限還有版本是2.1還是2.2的:

這個是加入后的圖片(自己網(wǎng)上偷懶找的?。?br />

3.在vue中使用go.js
- 使用案例Flowchart
- 我們在初始化之前最好使用ref來設(shè)置 他的id屬性
- 我已經(jīng)將他封裝成為一個組件,具體注釋代碼里面也有,可以直接粘貼使用
- 注意: 我改了不少原有的樣式和結(jié)構(gòu),比如: Start我改成了長方形什么的,加了收縮功能

<!--
@description:Flowchart drawing, dedicated to customization
@date:Created in 2022/7/24 15:55
@modified By:luofei-create
@version: 1.0.0
-->
<template>
<div>
<div>
<!-- 主畫布區(qū)域 -->
<div ref="diagram">
<canvas
tabindex="0"
width="954"
height="700">
This text is displayed if your browser does not support the CanvasHTML element.
</canvas>
<div>
<div></div>
</div>
</div>
<!-- 右邊組件拖拽 -->
<div ref="myPaletteDiv" v-show="isRight">
<canvas
tabindex="0"
width="560"
height="700">
</canvas>
<div>
<div>
工具組件
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'example',
data() {
return {
myDiagramRefs: null, //這個是為了將初始化的結(jié)構(gòu)保存起來,可以調(diào)用go.js的方法
};
},
props: {
//父組件傳過來的json數(shù)據(jù)
jsonData: {
type: Object,
require: true,
default: () => ({}),
},
// 是否展示右側(cè)的工具欄
isRight: {
type: Boolean,
default: () => true,
},
},
watch: {
//監(jiān)聽json數(shù)據(jù), 再次初始化
jsonData: {
handler(n, o) {
this.load();
},
},
},
mounted() {
//調(diào)用test方法,初始化畫布
this.test();
},
methods: {
test() {
// 初始化go.js
const $ = go.GraphObject.make; // 為了定義模板的簡潔性
const myDiagram = $(
go.Diagram,
this.$refs.diagram,
// 'my-diagram-div', // id掛載dome節(jié)點
// 這里是控制那個菱形在連線的時候出現(xiàn)文字的,我暫時不需要,所以注釋掉
{
// LinkDrawn: showLinkLabel,
// LinkRelinked: showLinkLabel,
'draggingTool.dragsTree': true,
'undoManager.isEnabled': true, //是否可以粘貼復(fù)制等,delete建刪除
},
);
this.myDiagramRefs = myDiagram;
// 當(dāng)修改文檔時,在標(biāo)題中添加一個“*”,并啟用“保存”按鈕
myDiagram.addDiagramListener('Modified', e => {
const button = document.getElementById('SaveButton');
if (button) button.disabled = !myDiagram.isModified;
const idx = document.title.indexOf('*');
if (myDiagram.isModified) {
if (idx < 0) {
myDiagram.layout = $(go.TreeLayout, { angle: 90 });
}
} else if (idx >= 0) document.title = document.title.slice(0, idx);
});
// 節(jié)點模板的Helper定義
function nodeStyle() {
return [
// 節(jié)點。 location來自于節(jié)點數(shù)據(jù)的“l(fā)oc”屬性,由Point轉(zhuǎn)換。 解析靜態(tài)方法。
// 如果節(jié)點。 location發(fā)生變化時,它更新節(jié)點數(shù)據(jù)的“l(fā)oc”屬性,并使用Point轉(zhuǎn)換回來。 stringify靜態(tài)方法。
new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(
go.Point.stringify,
),
{
// 這個節(jié)點位置位于每個節(jié)點的中心
locationSpot: go.Spot.Center,
},
];
}
// 定義一個用于創(chuàng)建通常是透明的“端口”的函數(shù)。
function makePort(name, align, spot, output, input) {
const horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
return $(go.Shape, {
fill: 'transparent',
strokeWidth: 0,
width: horizontal ? NaN : 8, // 如果不是水平拉伸,寬度只有8
height: !horizontal ? NaN : 8, // 如果不是垂直拉伸,也就是8英尺高
alignment: align, // 對齊主形狀上的端口
stretch: horizontal
? go.GraphObject.Horizontal
: go.GraphObject.Vertical,
portId: name, // 將此對象聲明為“端口”
fromSpot: spot, // 聲明此端口的鏈接可能連接到哪里
fromLinkable: output, // 聲明用戶是否可以從這里繪制鏈接
toSpot: spot, // 聲明此端口的鏈接可能連接到哪里
toLinkable: input, // 聲明用戶是否可以在此繪制鏈接
cursor: 'pointer', // 顯示不同的游標(biāo)以指示潛在的鏈接點
mouseEnter: (e, port) => {
// PORT參數(shù)將是這個Shape
if (!e.diagram.isReadOnly) port.fill = 'rgba(255,0,255,0.5)';
},
mouseLeave: (e, port) => (port.fill = 'transparent'),
});
}
// 文字顏色
function textStyle() {
return {
font: 'bold 11pt Lato, Helvetica, Arial, sans-serif',
stroke: '#F8F8F8',
};
}
//這一句是我自己加上的,目的是為了在連線的時候可以幫我自動對齊
myDiagram.layout = $(go.TreeLayout, { angle: 90 });
// 定義普通節(jié)點的Node模板
myDiagram.nodeTemplateMap.add(
'', // 自己定義模板名稱
$(
go.Node,
'Spot',
{
resizable: true,
resizeObjectName: 'SHAPE',
selectionObjectName: 'SHAPE',
margin: new go.Margin(10, 0, 10, 0),
},
nodeStyle(),
// 主要對象是一個面板,它圍繞著一個矩形形狀的TextBlock
$(
go.Panel,
'Auto',
$(
go.Shape,
'Rectangle',
{
name: 'SHAPE',
fill: '#282c34',
stroke: '#00A9C9',
margin: new go.Margin(0, 0, 0, 0),
strokeWidth: 1.5, // strokeWidh表示Step的盒子邊框大小
},
new go.Binding('figure', 'figure'),
),
$(
go.TextBlock,
textStyle(),
{
margin: 8,
maxSize: new go.Size(560, NaN),
wrap: go.TextBlock.WrapFit,
editable: true,
},
new go.Binding('text').makeTwoWay(),
),
),
//這里也是我自己加的,目的是為了可以像樹一樣可以收縮展開
$('TreeExpanderButton',
{
margin: new go.Margin(0, 0, 0, 20),
alignment: go.Spot.Bottom,
alignmentFocus: go.Spot.Top,
},
{ visible: true }),
// 四個命名端口,每邊一個:
makePort('T', go.Spot.Top, go.Spot.TopSide, false, true), //表示端口哪里可以鏈接,哪里不可以鏈接
makePort('L', go.Spot.Left, go.Spot.LeftSide, true, true),
makePort('R', go.Spot.Right, go.Spot.RightSide, true, true),
makePort('B', go.Spot.Bottom, go.Spot.BottomSide, true, false),
),
);
// 菱形的樣式 -> 改成長方形
myDiagram.nodeTemplateMap.add(
'Conditional',
$(
go.Node,
'Spot',
{
resizable: true,
resizeObjectName: 'SHAPE',
selectionObjectName: 'SHAPE',
},
nodeStyle(),
$(
go.Panel,
'Auto',
$(
go.Shape,
'Rectangle',
{
name: 'SHAPE',
fill: '#282c34',
stroke: 'rgba(98, 251, 243)',
strokeWidth: 1.5,
},
new go.Binding('figure', 'figure'),
),
$(
go.TextBlock,
textStyle(),
{
margin: 8,
maxSize: new go.Size(560, NaN),
wrap: go.TextBlock.WrapFit,
editable: true,
},
new go.Binding('text').makeTwoWay(),
),
),
$('TreeExpanderButton',
{ alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top },
{ visible: true }),
// four named ports, one on each side:
makePort('T', go.Spot.Top, go.Spot.TopCenter, false, true),
makePort('L', go.Spot.Left, go.Spot.LeftCenter, true, true),
makePort('R', go.Spot.Right, go.Spot.RightCenter, true, true),
makePort('B', go.Spot.Bottom, go.Spot.BottomCenter, true, false),
),
);
// 圓形開始
myDiagram.nodeTemplateMap.add(
'Start',
$(
go.Node,
'Spot',
{
resizable: true,
resizeObjectName: 'SHAPE',
selectionObjectName: 'SHAPE',
},
nodeStyle(),
$(
go.Panel,
'Spot',
$(
go.Shape,
'Rectangle', // 決定形狀: Circle代表圓形,Rectangle代表正方形或者長方形,Diamond代表菱形
{
name: 'SHAPE',
desiredSize: new go.Size(90, 40),
fill: '#282c34',
stroke: '#09d3ac',
strokeWidth: 1.5,
},
),
$(
go.TextBlock,
'Start',
textStyle(),
{
margin: 8,
maxSize: new go.Size(360, NaN),
wrap: go.TextBlock.WrapFit,
editable: true,
},
new go.Binding('text').makeTwoWay(),
),
),
$('TreeExpanderButton',
{ alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top },
{ visible: true }),
// three named ports, one on each side except the top, all output only:
makePort('T', go.Spot.Top, go.Spot.TopCenter, false, true),
makePort('L', go.Spot.Left, go.Spot.LeftCenter, true, true),
makePort('R', go.Spot.Right, go.Spot.RightCenter, true, true),
makePort('B', go.Spot.Bottom, go.Spot.BottomCenter, true, false),
),
);
// 原型,結(jié)束樣式
myDiagram.nodeTemplateMap.add(
'End',
$(
go.Node,
'Table',
nodeStyle(),
{
resizable: true,
resizeObjectName: 'SHAPE',
selectionObjectName: 'SHAPE',
},
$(
go.Panel,
'Spot',
$(go.Shape, 'Circle', {
desiredSize: new go.Size(60, 60),
fill: '#282c34',
stroke: '#DC3C00',
strokeWidth: 3.5,
}),
$(go.TextBlock, 'End', textStyle(), new go.Binding('text')),
),
$('TreeExpanderButton',
{ alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top },
{ visible: true }), // three named ports, one on each side except the bottom, all input only:
makePort('T', go.Spot.Top, go.Spot.Top, false, true),
makePort('L', go.Spot.Left, go.Spot.Left, false, true),
makePort('R', go.Spot.Right, go.Spot.Right, false, true),
),
);
// taken from ../extensions/Figures.js:
go.Shape.defineFigureGenerator('File', (shape, w, h) => {
const geo = new go.Geometry();
const fig = new go.PathFigure(0, 0, true); // starting point
geo.add(fig);
fig.add(new go.PathSegment(go.PathSegment.Line, 0.75 * w, 0));
fig.add(new go.PathSegment(go.PathSegment.Line, w, 0.25 * h));
fig.add(new go.PathSegment(go.PathSegment.Line, w, h));
fig.add(new go.PathSegment(go.PathSegment.Line, 0, h).close());
const fig2 = new go.PathFigure(0.75 * w, 0, false);
geo.add(fig2);
// The Fold
fig2.add(new go.PathSegment(go.PathSegment.Line, 0.75 * w, 0.25 * h));
fig2.add(new go.PathSegment(go.PathSegment.Line, w, 0.25 * h));
geo.spot1 = new go.Spot(0, 0.25);
geo.spot2 = go.Spot.BottomRight;
return geo;
});
// 定義comment文本樣式
myDiagram.nodeTemplateMap.add(
'Comment',
$(
go.Node,
'Auto',
nodeStyle(),
$(go.Shape, 'File', {
fill: '#282c34',
stroke: '#DEE0A3',
strokeWidth: 3,
}),
$(
go.TextBlock,
textStyle(),
{
margin: 8,
maxSize: new go.Size(200, NaN),
wrap: go.TextBlock.WrapFit,
textAlign: 'center',
editable: true,
},
new go.Binding('text').makeTwoWay(),
),
// 沒有端口,因為不允許鏈接連接注釋
),
);
//替換linkTemplateMap中默認(rèn)的Link模板
myDiagram.linkTemplate = $(
go.Link, // the whole link panel
{
routing: go.Link.AvoidsNodes,
curve: go.Link.JumpOver,
corner: 5,
toShortLength: 4,
relinkableFrom: true,
margin: new go.Margin(10, 0, 10, 0),
relinkableTo: true,
reshapable: true,
resegmentable: true,
// mouse-overs subtly highlight links:
mouseEnter: (e, link) => (link.findObject('HIGHLIGHT').stroke = 'rgba(30,144,255,0.2)'),
mouseLeave: (e, link) => (link.findObject('HIGHLIGHT').stroke = 'transparent'),
selectionAdorned: false,
},
new go.Binding('points').makeTwoWay(),
$(
go.Shape, // 高光形狀,通常是透明的
{
isPanelMain: true,
strokeWidth: 8,
stroke: 'transparent',
name: 'HIGHLIGHT',
},
),
$(
go.Shape, // 鏈接路徑形狀,或者樣式也可以設(shè)置
{ isPanelMain: true, stroke: 'gray', strokeWidth: 2 },
new go.Binding('stroke', 'isSelected', sel => (sel ? 'dodgerblue' : 'gray')).ofObject(),
),
$(
go.Shape, // 箭頭
{ toArrow: 'standard', strokeWidth: 0, fill: 'gray' },
),
$(
go.Panel,
'Auto', //鏈接標(biāo)簽,通常不可見
{
visible: false,
name: 'LABEL',
segmentIndex: 2,
segmentFraction: 0.5,
},
new go.Binding('visible', 'visible').makeTwoWay(),
$(
go.Shape,
'RoundedRectangle', // 鏈接標(biāo)簽,通常不可見的標(biāo)簽形狀
{ fill: '#F8F8F8', strokeWidth: 0 },
),
//這里是由于我不需要菱形那個形狀,有需要的可以不用注釋,還有連接線上的文字 Yes
// $(
// go.TextBlock,
// 'Yes',
// {
// textAlign: 'center',
// font: '10pt helvetica, arial, sans-serif',
// stroke: '#333333',
// editable: true,
// },
// new go.Binding('text').makeTwoWay(),
// ),
),
);
// 如果鏈接來自“條件”節(jié)點,則使其可見。
// 這個監(jiān)聽器由“LinkDrawn”和“LinkRelinked”diagramevent調(diào)用。
function showLinkLabel(e) {
const label = e.subject.findObject('LABEL');
if (label !== null) label.visible = e.subject.fromNode.data.category === 'Conditional';
}
// LinkingTool和RelinkingTool使用的臨時鏈接也是正交的:
myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;
// 調(diào)用load???????????
// 人造數(shù)據(jù)
// this.load(myDiagram); // 從一些JSON文本加載一個初始圖
//啟動初始化畫布數(shù)據(jù)
myDiagram.model = go.Model.fromJson(this.jsonData);
const myPalette = $(
go.Palette,
this.$refs.myPaletteDiv, // must name or refer to the DIV HTML element
{
// Instead of the default animation, use a custom fade-down
'animationManager.initialAnimationStyle': go.AnimationManager.None,
InitialAnimationStarting: animateFadeDown, // Instead, animate with this function
nodeTemplateMap: myDiagram.nodeTemplateMap, // share the templates used by myDiagram
model: new go.GraphLinksModel([
// specify the contents of the Palette
{ category: 'Start', text: '開始' },
{ Category: 'Assess', text: '業(yè)務(wù)組件' },
{ category: 'Conditional', text: '業(yè)務(wù)組件' },
{ category: 'End', text: '結(jié)束組件' },
{ category: 'Comment', text: 'Comment' },
]),
},
);
// 這是默認(rèn)動畫的重新實現(xiàn),只不過它是從向下淡入,而不是向上淡入。
function animateFadeDown(e) {
const { diagram } = e;
const animation = new go.Animation();
animation.isViewportUnconstrained = true; // 因此,圖表定位規(guī)則允許動畫從屏幕外開始
animation.easing = go.Animation.EaseOutExpo;
animation.duration = 900;
//淡出“向下”,換句話說,從上面淡出
animation.add(
diagram,
'position',
diagram.position.copy().offset(0, 200),
diagram.position,
);
animation.add(diagram, 'opacity', 0, 1);
animation.start();
}
},
// 保存功能,我將數(shù)據(jù)傳到父組件中
save() {
const data = this.myDiagramRefs.model.toJson();
this.$emit('getJsonDataList', data); //導(dǎo)出數(shù)據(jù)
this.myDiagramRefs.isModified = false;
},
// 初始化數(shù)據(jù),形成畫布
load() {
this.myDiagramRefs.model = go.Model.fromJson(this.jsonData);
this.myDiagramRefs.isModified = true;
},
printDiagram() {
const svgWindow = window.open();
if (!svgWindow) return; // failure to open a new Window
const printSize = new go.Size(700, 960);
const bnds = myDiagram.documentBounds;
let { x } = bnds;
let { y } = bnds;
while (y < bnds.bottom) {
while (x < bnds.right) {
const svg = myDiagram.makeSvg({
scale: 1.0,
position: new go.Point(x, y),
size: printSize,
});
svgWindow.document.body.appendChild(svg);
x += printSize.width;
}
x = bnds.x;
y += printSize.height;
}
setTimeout(() => svgWindow.print(), 1);
},
},
};
</script>
<style scoped>
.example{
margin-top: 5px;
}
.example-box{
width: 100%;
display: flex;
justify-content: space-between;
}
.myPaletteDiv{
width: 160px;
background-color: rgb(24, 43, 133);
position: relative;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
}
.canvas-right{
position: absolute;
top: 0px;
left: 0px;
z-index: 2;
user-select: none;
touch-action: none;
width: 160px;
height: 700px;
overflow: hidden;
}
.right-box{
position: absolute;
width: 160px;
height: 700px;
overflow: hidden;
z-index: 1;
}
.right-box-item{
position: absolute;
width: 1px;
height: 1px
}
/* 主畫布區(qū)域 */
.myDiagramDiv{
flex-grow: 1;
height: 700px;
margin-right: 2px;
background-color: rgb(24, 43, 133);
position: relative;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
cursor: auto;
}
.canvas-left{
position: absolute;
top: 0px;
left: 0px;
z-index: 2;
user-select: none;
touch-action: none;
width: 954px;
height: 700px;
cursor: auto;
}
.left-box{
position: absolute;
width: 954px;
height: 700px;
z-index: 1;
}
.left-box-item{
position: absolute; width: 1px; height: 1px
}
.text{
color: rgba(255,0,255,0.5);
background: #00A9C9;
}
</style>二、加入的一些功能以及代碼實現(xiàn)
1. 加入樹形收縮節(jié)點
- 代碼片段

- 效果圖:

2.可收縮大小
代碼片段

效果圖:

樣式什么的可以自己設(shè)置
三、翻譯部分文檔
一.按鈕
為了您的方便,我們定義了幾個常用的面板。 這些按鈕包括"Button"、“TreeExpanderButton”、“SubGraphExpanderButton”、“PanelExpanderButton”、“ContextMenuButton"和"CheckBoxButton”。 "ContextMenuButton"通常在"ContextMenu"面板內(nèi)使用; “復(fù)選框按鈕”用于實現(xiàn)“復(fù)選框”面板。
在調(diào)用GraphObject.make時,可以像使用面板派生類一樣使用這些預(yù)定義的面板。 它們被實現(xiàn)為面板中GraphObjects的簡單可視化樹,具有預(yù)先設(shè)置的屬性和事件處理程序。
1.一般的按鈕
diagram.nodeTemplate =
$(go.Node, "Auto",
{ locationSpot: go.Spot.Center },
$(go.Shape, "Rectangle",
{ fill: "gold" }),
$(go.Panel, "Vertical",
{ margin: 3 },
$("Button",
{ margin: 2,
click: incrementCounter },
$(go.TextBlock, "Click me!")),
$(go.TextBlock,
new go.Binding("text", "clickCount",
function(c) { return "Clicked " + c + " times."; }))
)
);
function incrementCounter(e, obj) {
var node = obj.part;
var data = node.data;
if (data && typeof(data.clickCount) === "number") {
node.diagram.model.commit(function(m) {
m.set(data, "clickCount", data.clickCount + 1);
}, "clicked");
}
}
diagram.model = new go.GraphLinksModel(
[ { clickCount: 0 } ]);

- 按鈕只是控制形狀的面板,它將圍繞著你所賦予的任何內(nèi)容。 邊界形狀命名為“ButtonBorder”,以便您可以輕松設(shè)置或綁定其屬性。
- 由所有“Button”定義的事件處理程序使用了額外的屬性,這些屬性沒有在API中定義,但你可以在“Button”的定義中看到:Buttons.js。 這些屬性參數(shù)化按鈕的外觀。
diagram.nodeTemplate =
$(go.Node, "Auto",
{ locationSpot: go.Spot.Center },
$(go.Shape, "Rectangle",
{ fill: "gold" }),
$(go.Panel, "Vertical",
{ margin: 3 },
$("Button",
{
margin: 2,
// 設(shè)置邊框?qū)傩园粹o的形狀
"ButtonBorder.fill": "fuchsia",
// 設(shè)置“按鈕”本身事件處理程序使用的屬性
"_buttonFillOver": "pink",
click: function(e, button) { alert(button.findObject("ButtonBorder").fill); }
},
$(go.TextBlock, "fuchsia button\nwith pink highlight", { margin: 2, textAlign: "center" })
),
$("Button",
{
margin: 2,
// 設(shè)置邊框?qū)傩园粹o的形狀
"ButtonBorder.figure": "Circle",
"ButtonBorder.fill": "cyan",
"ButtonBorder.stroke": "darkcyan",
"ButtonBorder.strokeWidth": 3,
// 設(shè)置“按鈕”本身事件處理程序使用的屬性
"_buttonFillOver": "white",
"_buttonStrokeOver": "cyan",
"_buttonFillPressed": "lightgray",
click: function(e, button) { alert(button.findObject("ButtonBorder").stroke); }
},
$(go.TextBlock, "Circular\nbutton", { margin: 2, textAlign: "center" })
),
$("Button",
{
margin: 2,
click: function(e, button) { alert(button.findObject("PIC").source); }
},
// 按鈕內(nèi)容可以是任何東西——它不一定是一個TextBlock
$(go.Picture, "images/50x40.png", { name: "PIC", width: 50, height: 40 })
),
$("Button",
{
margin: 2,
// 按鈕也可以通過設(shè)置或數(shù)據(jù)綁定禁用:
isEnabled: false,
click: function(e, button) { alert("won't be alerted"); }
},
$(go.TextBlock, "disabled", { stroke: "gray" })
)
)
);
diagram.model = new go.GraphLinksModel([ { } ]);
2.樹擴展按鈕 (TreeExpanderButtons)
這個也是我自己需要引入的按鈕,上文已經(jīng)介紹
擴展和折疊子樹是很常見的。 通過在節(jié)點模板中添加“TreeExpanderButton”的實例,很容易讓用戶控制這一點。 該按鈕調(diào)用CommandHandler。 collapseTree或CommandHandler。 expandTree取決于Node.isTreeExpanded的值。 按鈕圖標(biāo)的形狀。 圖隨節(jié)點值的變化而變化。 isTreeExpanded變化。
diagram.nodeTemplate =
$(go.Node, "Spot",
$(go.Panel, "Auto",
$(go.Shape, "Rectangle",
{ fill: "gold" }),
$(go.TextBlock, "Click small button\nto collapse/expand subtree",
{ margin: 5 })
),
$("TreeExpanderButton",
{ alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top },
{ visible: true })
);
diagram.layout = $(go.TreeLayout, { angle: 90 });
diagram.model = new go.GraphLinksModel(
[ { key: 1 },
{ key: 2 } ],
[ { from: 1, to: 2 } ] );

- “TreeExpanderButton”是一個“按鈕”,它持有一個顯示“減線”或“增線”圖形的形狀,這取決于Node.isTreeExpanded的值。 該形狀被命名為“ButtonIcon”,因此您可以輕松地設(shè)置或綁定它的屬性,以及“ButtonBorder”和“Button”本身的屬性。
diagram.nodeTemplate =
$(go.Node, "Spot",
$(go.Panel, "Auto",
$(go.Shape, "Rectangle",
{ fill: "gold" }),
$(go.TextBlock, "Click small button\nto collapse/expand subtree",
{ margin: 5 })
),
$("TreeExpanderButton",
{
// set the two additional properties used by "TreeExpanderButton"
// that control the shape depending on the value of Node.isTreeExpanded
"_treeExpandedFigure": "TriangleUp",
"_treeCollapsedFigure": "TriangleDown",
// set properties on the icon within the border
"ButtonIcon.fill": "darkcyan",
"ButtonIcon.strokeWidth": 0,
// set general "Button" properties
"ButtonBorder.figure": "Circle",
"ButtonBorder.stroke": "darkcyan",
"_buttonStrokeOver": "darkcyan"
},
{ alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top },
{ visible: true })
);
diagram.layout = $(go.TreeLayout, { angle: 90 });
diagram.model = new go.GraphLinksModel(
[ { key: 1 },
{ key: 2 } ],
[ { from: 1, to: 2 } ] );

3.SubGraphExpanderButtons
還經(jīng)常需要展開和折疊包含子圖的組。 您可以通過向組模板添加“SubGraphExpanderButton”的實例來讓用戶控制這一點。 該按鈕調(diào)用CommandHandler。 collapseSubGraph或CommandHandler。 expandSubGraph取決于Group.isSubGraphExpanded的值。 按鈕圖標(biāo)的形狀。 圖隨Group值的變化而變化。 isSubGraphExpanded變化。
diagram.groupTemplate =
$(go.Group, "Auto",
$(go.Shape, "Rectangle",
{ fill: "gold" }),
$(go.Panel, "Vertical",
{ margin: 5,
defaultAlignment: go.Spot.Left },
$(go.Panel, "Horizontal",
$("SubGraphExpanderButton",
{ margin: new go.Margin(0, 3, 5, 0) }),
$(go.TextBlock, "Group")
),
$(go.Placeholder)
)
);
diagram.model = new go.GraphLinksModel(
[ { key: 0, isGroup: true },
{ key: 1, group: 0 },
{ key: 2, group: 0 },
{ key: 3, group: 0 } ] );

“SubGraphExpanderButton”類似于“TreeExpanderButton”,因為它是一個“按鈕”,其邊框形狀圍繞圖標(biāo)形狀。 該形狀被命名為“ButtonIcon”,因此您可以輕松地設(shè)置或綁定它的屬性,以及“ButtonBorder”和“Button”本身的屬性。
diagram.groupTemplate =
$(go.Group, "Auto",
$(go.Shape, "Rectangle",
{ fill: "gold" }),
$(go.Panel, "Vertical",
{ margin: 5,
defaultAlignment: go.Spot.Left },
$(go.Panel, "Horizontal",
$("SubGraphExpanderButton",
{
// 設(shè)置"SubGraphExpanderButton"使用的兩個附加屬性
// 根據(jù)Group.isSubGraphExpanded的值來控制形狀
"_subGraphExpandedFigure": "TriangleUp",
"_subGraphCollapsedFigure": "TriangleDown",
// set other properties on the button icon
"ButtonIcon.angle": -45,
// 和按鈕邊框上的屬性或按鈕本身
"ButtonBorder.opacity": 0.0
}),
$(go.TextBlock, "Group")
),
$(go.Placeholder)
)
);
diagram.model = new go.GraphLinksModel(
[ { key: 0, isGroup: true },
{ key: 1, group: 0 },
{ key: 2, group: 0 },
{ key: 3, group: 0 } ] );

4.面板擴展按鈕 (PanelExpanderButtons)
通常希望展開和折疊節(jié)點的一部分,從而顯示或隱藏有時不需要的細(xì)節(jié)。 通過在節(jié)點模板中添加“PanelExpanderButton”的實例,很容易讓用戶控制這一點。 GraphObject的第二個參數(shù)。 make應(yīng)該是一個字符串,用于命名節(jié)點中GraphObject. make的元素。 您希望按鈕切換的可視屬性。
diagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape,
{ fill: "gold" }),
$(go.Panel, "Table",
{ defaultAlignment: go.Spot.Top, defaultColumnSeparatorStroke: "black" },
$(go.Panel, "Table",
{ column: 0 },
$(go.TextBlock, "List 1",
{ column: 0, margin: new go.Margin(3, 3, 0, 3),
font: "bold 12pt sans-serif" }),
$("PanelExpanderButton", "LIST1",
{ column: 1 }),
$(go.Panel, "Vertical",
{ name: "LIST1", row: 1, column: 0, columnSpan: 2 },
new go.Binding("itemArray", "list1"))
),
$(go.Panel, "Table",
{ column: 1 },
$(go.TextBlock, "List 2",
{ column: 0, margin: new go.Margin(3, 3, 0, 3),
font: "bold 12pt sans-serif" }),
$("PanelExpanderButton", "LIST2",
{ column: 1 }),
$(go.Panel, "Vertical",
{ name: "LIST2", row: 1, column: 0, columnSpan: 2 },
new go.Binding("itemArray", "list2"))
)
)
);
diagram.model = new go.GraphLinksModel([
{
key: 1,
list1: [ "one", "two", "three", "four", "five" ],
list2: [ "first", "second", "third", "fourth" ]
}
]);

“PanelExpanderButton”類似于“TreeExpanderButton”或“SubGraphExpanderButton”,因為它是一個“按鈕”,其邊框形狀圍繞圖標(biāo)形狀。 然而,此面板綁定形狀。 幾何字符串而不是Shape.figure。
diagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape,
{ fill: "gold" }),
$(go.Panel, "Table",
{ defaultAlignment: go.Spot.Top, defaultColumnSeparatorStroke: "black" },
$(go.Panel, "Table",
{ column: 0 },
$(go.TextBlock, "List 1",
{ column: 0, margin: new go.Margin(3, 3, 0, 3),
font: "bold 12pt sans-serif" }),
$("PanelExpanderButton", "LIST1",
{ column: 1,
// 設(shè)置"PanelExpanderButton"使用的兩個附加屬性
// 根據(jù)GraphObject.visible的值來控制形狀
// 命名為“LIST1”的對象的
"_buttonExpandedFigure": "M0 0 L10 0",
"_buttonCollapsedFigure": "M0 5 L10 5 M5 0 L5 10",
"ButtonIcon.stroke": "blue",
height: 16
}),
$(go.Panel, "Vertical",
{ name: "LIST1", row: 1, column: 0, columnSpan: 2 },
new go.Binding("itemArray", "list1"))
),
$(go.Panel, "Table",
{ column: 1 },
$(go.TextBlock, "List 2",
{ column: 0, margin: new go.Margin(3, 3, 0, 3),
font: "bold 12pt sans-serif" }),
$("PanelExpanderButton", "LIST2",
{ column: 1,
// 設(shè)置"PanelExpanderButton"使用的兩個附加屬性
// 根據(jù)GraphObject.visible的值來控制形狀
// 命名為“LIST1”的對象的
"_buttonExpandedFigure": "F M0 10 L5 0 10 10z",
"_buttonCollapsedFigure": "F M0 0 L10 0 5 10z",
"ButtonIcon.strokeWidth": 0,
"ButtonIcon.fill": "blue"
}),
$(go.Panel, "Vertical",
{ name: "LIST2", row: 1, column: 0, columnSpan: 2 },
new go.Binding("itemArray", "list2"))
)
)
);
diagram.model = new go.GraphLinksModel([
{
key: 1,
list1: [ "one", "two", "three", "four", "five" ],
list2: [ "first", "second", "third", "fourth" ]
}
]);

5.ContextMenuButtons和快捷菜單 (ContextMenuButtons and ContextMenus)
盡管您可以以任何您選擇的方式實現(xiàn)上下文菜單,但通常使用預(yù)定義的“ContextMenuButton”。
diagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, "Rectangle",
{ fill: "gold" }),
$(go.TextBlock, "Use ContextMenu!",
{ margin: 5 })
);
diagram.nodeTemplate.contextMenu =
$("ContextMenu",
$("ContextMenuButton",
$(go.TextBlock, "Shift Left"),
{ click: function(e, obj) { shiftNode(obj, -20); } }),
$("ContextMenuButton",
$(go.TextBlock, "Shift Right"),
{ click: function(e, obj) { shiftNode(obj, +20); } })
);
function shiftNode(obj, dist) {
var adorn = obj.part;
var node = adorn.adornedPart;
node.diagram.commit(function(d) {
var pos = node.location.copy();
pos.x += dist;
node.location = pos;
}, "Shift");
}
diagram.model = new go.GraphLinksModel(
[ { key: 1 } ] );

“ContextMenuButton”只是一個設(shè)置了一些屬性的“按鈕”。 其中一個屬性是GraphObject。 它被設(shè)置為go.GraphObject.Horizontal,這樣“ContextMenu”中的所有“ContextMenuButton”都將被拉伸到相同的寬度。 但是你可以在它的“ButtonBorder”形狀和按鈕本身上設(shè)置所有常用的屬性。
diagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, "Rectangle",
{ fill: "gold" }),
$(go.TextBlock, "Use ContextMenu!",
{ margin: 5 })
);
diagram.nodeTemplate.contextMenu =
$("ContextMenu",
$("ContextMenuButton",
{
"ButtonBorder.fill": "yellow",
"_buttonFillOver": "cyan",
"_buttonFillPressed": "lime"
},
$(go.TextBlock, "Shift Left"),
{ click: function(e, obj) { shiftNode(obj, -20); } }
),
$("ContextMenuButton",
{
"ButtonBorder.fill": "yellow",
"_buttonFillOver": "cyan",
"_buttonFillPressed": "lime"
},
$(go.TextBlock, "Shift Right"),
{ click: function(e, obj) { shiftNode(obj, +20); } }
),
$("ContextMenuButton",
{ isEnabled: false },
$(go.TextBlock, "Shift Right", { stroke: "gray" }),
{ click: function(e, obj) { alert("won't be alerted"); } }
)
);
function shiftNode(obj, dist) {
var adorn = obj.part;
var node = adorn.adornedPart;
node.diagram.commit(function(d) {
var pos = node.location.copy();
pos.x += dist;
node.location = pos;
}, "Shift");
}
diagram.model = new go.GraphLinksModel(
[ { key: 1 } ] );

6.CheckBoxButtons和復(fù)選框(CheckBoxButtons and CheckBoxes)
- “CheckBoxButton”是一個“按鈕”,它被配置為切換數(shù)據(jù)屬性的布爾值。 默認(rèn)情況下,當(dāng)值為false時按鈕是清晰的,當(dāng)值為true時顯示一個復(fù)選標(biāo)記,但是可以進行大量的定制。
- 定義“CheckBoxButton”時的第一個參數(shù)應(yīng)該是一個字符串,該字符串指定保存“CheckBoxButton”的已檢查狀態(tài)的數(shù)據(jù)屬性。 如果不希望單擊按鈕來切換數(shù)據(jù)屬性的值,請指定一個數(shù)據(jù)屬性名稱,該名稱為空字符串。
- 在“CheckBox”面板的定義中使用了“CheckBoxButton”,這是一種將任何GraphObject關(guān)聯(lián)為“CheckBoxButton”標(biāo)簽的方便方式。
- “復(fù)選框”示例中顯示了許多具有各種自定義的“復(fù)選框”示例。
7.按鈕的定義(Button Definitions)
- 所有預(yù)定義按鈕的實現(xiàn)都在Extensions目錄下的buttons .js中提供。 在創(chuàng)建自己的按鈕時,您可能希望復(fù)制并改編這些定義。
- 這些定義可能不是GoJS中GraphObject.make使用的實際標(biāo)準(zhǔn)按鈕實現(xiàn)的最新描述。
- 注意,這些按鈕的定義使用了GraphObject.defineBuilder靜態(tài)函數(shù)。 它擴展了GraphObject的行為。 允許通過帶有可選參數(shù)的名稱創(chuàng)建相當(dāng)復(fù)雜的可視樹。 你可以在整個示例和擴展中找到各種控件的定義
相關(guān)文章
javaScript如何跳出多重循環(huán)break、continue
這篇文章主要為大家詳細(xì)介紹了javaScript如何跳出多重循環(huán)break、continue,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09
Nuxt3?布局layouts和NuxtLayout的使用詳解
layouts是Nuxt3提供的一種方便開發(fā)者快速實現(xiàn)自定義布局的約定,是基于Vue3的一個開發(fā)框架,基于服務(wù)器端渲染SSR,可以更加方便的用于Vue的SEO優(yōu)化,這篇文章主要介紹了Nuxt3?布局layouts和NuxtLayout的使用,需要的朋友可以參考下2023-04-04

