前言
此使用教程的内容只是个人制作产品时,根据需要实现功能进行文档记录,需要完整的使用文档需要自行去官方文档查看。
注意:本文档适用于开发类似思维导图的功能,需要其他样式可以查看官方文档的例子。
安装和引入Go.js
先安装
npm I gojs –save
然后组件按需引入或全局main.js引入,看自己需求。
使用时要在html中用个dom容器来渲染图像
<div id="chart-wrap">
<div id="chart-diagram"></div>
</div>
JS导入
// 在export之前
import go from 'gojs'
const MAKE = go.GraphObject.make; // 声明个全局的常量MAKE,用来“创造”所需图像配置
画板初始化
Vue中建议把初始化过程写在一个方法里,初始化内容为
init() {
var mySelf = this // 声明个Vue的指向
mySelf.myDiagram = MAKE(go.Diagram, 'chart-diagram', { // 创建画板并挂在Vue上(注意dom的id名称要对应)
//这里写画板配置
})
}
画板配置
基础配置
initialContentAlignment: go.Spot.Center, // 居中显示
isReadOnly: true, // 只读,无法编辑操作
allowMove: true, // 允许拖动画板
allowDragOut:true, // 允许拖拽节点
allowDelete: true, // 允许删除节点
allowCopy: true, // 允许复制节点
allowClipboard: true, // 允许粘贴节点
scale: 1.0, // 初始视图大小比例
minScale: 0.5, // 最小视图的缩小比例
maxScale: 1.5, // 最大视图的放大比例
scrollMargin: 500, // 默认下拖拽画布的时候边界是已最外的节点为边距,这个就是增加边距的,类似padding设置
fixedBounds: , //设置图表边界
'undoManager.isEnabled': true, // 支持 Ctrl-Z 和 Ctrl-Y 操作 (撤回和复原)
'toolManager.hoverDelay': 100, // tooltip提示显示延时
'toolManager.toolTipDuration': 10000, // tooltip持续显示时间
'grid.visible': true, // 显示网格
'toolManager.mouseWheelBehavior': go.ToolManager.WheelZoom, // 有鼠标滚轮事件放大和缩小,而不是向上和向下滚动
'clickCreatingTool.archetypeNodeData': { category: 'Normal', text: '新节点', notice: ''}, // 双击新建节点(可以写入节点的默认信息);
树结构配置
mySelf.myDiagram.layout = MAKE(go.TreeLayout, { // 树结构
angle: 0, //树结构的方向
layerSpacing: 35, //节点之间的距离
isOngoing: false, // 是否开启自动布局
isTreeExpanded:false // 是否展开子节点
})
连接线的配置
mySelf.myDiagram.linkTemplate =
MAKE(go.Link,
{
routing: go.Link.Orthogonal, // 线会自动90度转弯(AvoidsNodes自动绕开节点)
curve: go.Link.JumpGap, // 线与线相交会自动不重叠(还有go.Link.Bezier贝塞尔曲线)
corner: 3 // 拐角弧度
toEndSegmentLength: 30, //目的点线的固定距离(如果设置了自动拐角就是最短距离)
fromEndSegmentLength: 30, //出发点线的固定距离(如果设置了自动拐角就是最短距离)
fromShortLength, //设置线的出发点到端口的距离
toShortLength, //设置线的结束点到端口的距离
zOrder: -111, //图像层级
selectable: false, //连接线是否可选
fromSpot: go.Spot.LeftRightSides, //连线出发点强制为(new go.Spot(0.5, 0.5, 0, -25)为自定义)
toSpot: go.Spot.LeftRightSides, //连线目的点强制为
reshapable: true,
resegmentable: true,
relinkableFrom: true, //出发点是否可以改变
relinkableTo: true, //目标点是否可改变
adjusting: go.Link.Stretch,
fromMaxLinks: 1, //限制一个连接点的连接次数
toMaxLinks: 1, //限制一个连接点的连接次数
},
// 如果link数据有fromSpot,toSpot属性则可绑定
new go.Binding("fromSpot", "fromSpot", go.Spot.parse),
new go.Binding("toSpot", "toSpot", go.Spot.parse),
MAKE(go.Shape, {
strokeWidth: 2 // 节点连线宽度
stroke: '#57CFE3' // 节点连线颜色
}),
MAKE(go.Shape, {
toArrow: 'Standard',
scale: 3, // 箭头放大倍数
fill: '#57CFE3', // 箭头填充色
stroke: null // 外边框颜色
})
)
鼠标框选配置
mySelf.myDiagram.toolManager.dragSelectingTool = null // 禁止框选
mySelf.myDiagram.toolManager.dragSelectingTool.box = MAKE(go.Part,{
layerName: 'Tool', selectable: false },
MAKE(go.Shape,
{ name: 'SHAPE', fill: null, stroke: 'chartreuse', strokeWidth: 3 })
)
}
节点选中时边框的配置
selectionAdornmentTemplate:
MAKE(go.Adornment, "Auto",
MAKE (go.Shape, { fill: null,
stroke: "deepskyblue",
strokeWidth: 1.5,
strokeDashArray: [4, 2] }
),
MAKE (go.Placeholder)
)
全局缩略图的配置
let myOverview = MAKE(go.Overview, 'myOverviewDiv', { observed: mySelf.myDiagram }) // 'myOverviewDiv'为缩略图dom的id名;
其他配置
线段吸附网格
mySelf.myDiagram.toolManager.draggingTool.isGridSnapEnabled = true // 注意:要先打开网格
mySelf.myDiagram.toolManager.draggingTool.gridSnapCllSpot = go.Spot.MiddleBottom // 设置网格编辑捕捉对齐点(这个个人还没试出来是什么)
节点有关
节点初始化
建议将节点的初始化写在方法中,便于创建不同类型的节点,以下为例子
function initNode (node_type, color) {
mySelf.myDiagram.nodeTemplateMap.add(
node_type || 'Normal', // 默认节点为普通节点
MAKE(
go.Node,
'Vertical', // 节点默认内部的排列方式,垂直(还有Spot、Auto,下面会介绍)
new go.Binding('location', 'loc', go.Point.parse), //设定和绑定节点的初始位置
{这里可以写一些节点的配置},
// 这里是面板的配置…
})
// 不同节点初始化
initNode('Normal', '#5D7092') // 普通节点
initNode('Model', '#E8684A') // 模型节点
对于定制化的节点,建议一个类型一个初始化方法
节点内容分类
一个节点为Node,内部可以创建Panel,Shape,TextBlock,Picture。
- Panel:面板,可以把Shape,TextBlock,Picture向内堆放
- Shape:图像
- TextBlock:文本框
- Picture:图片
节点成员的布局方式
注意布局配置是有覆盖的先后顺序的,node和panel可以生效,Auto方式第一个配置的大小会自适应,且以其为边界裁切。
偷大佬的一张图:
节点配置
{
// 节点阴影设置
isShadowed: true,
shadowOffset: new go.Point(3, 3), //阴影的位置偏移
shadowColor: '#C5C1AA',
zOrder: 99999//层级
movable:false,//是否可拖动
deletable:false,//是否可删除
selectable: false, //是否可选择
selectionAdorned:false, //显示选中边框
copyable:false, //可复制的
location, //节点坐标,还不会用
minLocation: new go.Point(0, 0), //节点坐标最小位置
maxLocation: new go.Point(9999, 0), //节点坐标最大位置
isSelected:true, //默认fasle,true(操作型属性无法在模板定义,只能在节点生成后操作)例如,节点或线对象.isSelected=true;
reshapable:true, // 重塑(改变shape形状边界时使用,将影响节点大小)
resizable: true, // 可调整大小的(手动调整节点大小时,节点内容显示区域时使用)
resizeCellSize: new go.Size(10, 10), //可调整的范围
rotatable:true, // 可旋转的
//这三个一起配合,固定选中的节点框只选中名为BODY的面板
locationSpot: go.Spot.Center,
locationObjectName: 'BODY',
selectionObjectName: 'BODY'
//固定连接点位置
fromSpot: go.Spot.RightCenter,
toSpot: go.Spot.LeftCenter
desiredSize: new go.Size(160, 40), //设置大小
avoidable:false, //线绕开经过的节点,不从节点穿过,Link.routing 为AvoidsNodes才能使用
avoidableMargin: new go.Margin(12,12,12,12) // 线绕开经过的节点的边距,默认6,6,6,6
}
一些节点触发事件
tips:也可以写在图形,面板上,但我试过获取不到节点信息
// 鼠标移入事件 (e.event可以获取事件的记录信息,obj为不可读性的移入节点信息)
mouseEnter: (e, obj) => {},、
// 鼠标移出事件
mouseLeave: (e, obj) => {},
// 选中节点事件 (node.isSelected表示被选中的节点)
selectionChanged: (node) => {},
// 单击节点事件
click: (e, node) => {},
// 双击节点事件
doubleClick: (e, node) => {},
// 鼠标悬停事件
mouseHover: (e, node) => {
注意:需要在画布定义悬停时间myDiagram.toolManager.hoverDelay = 500 ;
},
// 线连接事件
linkConnected: function (node, link, port) {
每个参数会触发两次,第一次是出发节点,第二个是目的节点
console.log(port.portId) //可以获取到连线时,出发点和目的点的节点名称
},
// 线断开事件
linkDisconnected: function(node, link, port) {}
}
面板的配置
tips:面板是可以随意添加,它的功能就是一个画板,内部可以放入图形,文字框等;
// 声明创建一个新的面板对象,自定义方式可参考mySelf.myDiagram.nodeTemplate
MAKE(
go.Panel,
'Auto', // 布局为自动(还有自定义位置Position)
{
minSize: new go.Size(160, 40), //最小大小
visible: false, // 不可见
name: ‘BODY’//面板名称
},
MAKE( //图形
go.Shape,
'RoundedRectangle', //为圆角矩形(还有矩形'Rectangle')
{
fill: color || '#5D7092', // 内填充色
stroke: '#FFF', // 外边框颜色 null 为无
strokeWidth: 1, // 外边框粗细
angle: 0, // 应该是旋转角度
position: new go.Point(0, 95), //如果开启了自定义位置这个就要写
background '#e6eefb', //可以理解为是panel的背景
desiredSize: new go.Size(120, 100), //宽高 不设置宽高表示自适应
alignment: new go.Spot(1, 0.5, 100, 0) // 放在上一级的哪个位置,除了特定的值还可以自定义,前面两个参数表示几倍于上一级的宽高的位置,后面设置具体x,y的位置
},
new go.Binding('figure', 'figure') // 声明并创建一个新的图形
),
MAKE( // 编辑文本域
go.TextBlock,
'默认',
{
font: '12pt Helvetica, Arial, sans-serif',
stroke: 'whitesmoke',// 外边框颜色
width: 125, // 文本区域宽度,会覆盖minSize等但仍会生效
maxLines: 2, 最多显示几行
maxSize: new go.Size(360, NaN), // 最大大小,NaN表示自适应,这个目前试出来shape不能用,使用Spot布局这个属性无法使用
wrap: go.TextBlock.WrapFit, //文本域可换行,大小自适应(还有文本决定宽高go.TextBlock.WrapDesiredSize,文本不能换行go.TextBlock.None)使用需要设置宽高
editable: true, // 是否可编辑
textAlign: center, // 文本位置
margin: 12, // new go.Margin(2, 0)或new go.Margin(1, 0, 0, 1)
overflow: go.TextBlock.OverflowEllipsis // 超出文本框大小的文字...代替(go.TextBlock.OverflowClip 溢出遮挡)使用需要设置宽高
},
new go.Binding('text').makeTwoWay() // 注意:这里的text简写了
),
MAKE(go.Picture, //图片,一个panel不能同时有shape
{ source: noticeImg, // 一定要以import的方式引入图片import noticeImg from '.. '
width: 20,
height: 23
}
)
还可以配置连接点,推荐用函数来配置
)
连接点的配置
// 例子:配置四个连接点,注意在pannel配置
makePort('T', go.Spot.Top, true, true),
makePort('L', go.Spot.Left, true, true),
makePort('R', go.Spot.Right, true, true),
makePort('B', go.Spot.Bottom, true, true)
用函数可以配置不同的连接点
function makePort (name, spot, output, input) {
return MAKE(go.Shape, 'Circle', {
fill: '#44CCFF', // 颜色
opacity: 0, // 透明
stroke: null, //边框颜色
desiredSize: new go.Size(10, 10), //大小
alignment: spot, //放置在相对与外部配置位置的(go.Spot.Left
alignmentFocus: go.Spot.Center, //第二次调整
defaultAlignment // 尚不清楚
portId: name, // 连接点ID,没有名称可能无法触发连线
fromLinkable: output, //是否出发点可用true或者false
toLinkable: input, // 是否目的点可用
cursor: 'pointer', // 移入的时候鼠标显示什么
fromShortLength, //设置线的出发点到端口的距离
toShortLength, //设置线的结束点到端口的距离
fromSpot: spot, //连线出发点强制为(go.Sport.RightCenter/AllSides/)
toSpot: spot, // 连线目的点强制为
// 如果需要这两个属性生效,必须在节点存储的方式上写
this.$nextTick(() => {
this.myDiagram.model = MAKE(go.GraphLinksModel, {
linkFromPortIdProperty: 'fromPort',
linkToPortIdProperty: 'toPort',
nodeDataArray, //存储节点数据的变量
linkDataArray //存储连线数据的变量
})
})
})
}
右键点击配置
{
contextMenu:
MAKE('ContextMenu',
MAKE('ContextMenuButton',
MAKE(go.TextBlock, '清除计算'),
{ click: function () {
console.log('右键点击了')
} })
)
},
// 可放在面板的配置中,面板右键触发
节点数据
节点的数据都存放在实例化画板的model属性里。
第一种存储数据的方式
this.myDiagram.model.nodeDataArray = [] //节点数据 格式为[{ key: "Alpha", color: "lightblue", loc: "400 0" }]
this.myDiagram.model.linkDataArray = [] //连线数据 格式为[{ from: "Beta", to: "Alpha" }]
第二种存储数据的方式
// 只需存储节点信息,但内有父级节点属性,这样显得不易乱
this.diagram.model = new go.TreeModel([…])
如果想更新已渲染画板的数据,就需要执行
this.myDiagram.rebuildParts()
或者
this.diagram.model = new go.GraphLinksModel(
nodeDataArray, //此变量存储节点数据
linkDataArray //此变量存储线条数据
);
固定属性
节点上会有些原生的固定属性,例如category为节点类型,为字符串;text为节点文本,为字符串,loc可能为节点位置,为字符串格式为’xx xx’(这个还没验证)等等。具体根据需求可查看官方的文档。
监听API
空白背景点击事件
mySelf.myDiagram.addDiagramListener('BackgroundSingleClicked', function (e) {})
监听删除事件
mySelf.myDiagram.addDiagramListener('SelectionDeleted', function (e) {
e.subject.each(function (n) {
删除的东西会依次遍历出来
})
})
监听节点文本框修改事件
// 在TextBlock的配置中写
textEdited: function (tb, olds, news) {
console.log('oldString: ' + olds + 'newString: ' + news)
}
监听节点生成事件
mySelf.myDiagram.addDiagramListener('PartCreated', function (e) {
还没试出具体什么获取节点的信息
})
其他API
外联HTML
与画板的html同级
<div id="toolTipDIV" style="position: absolute; background: white; border: 2px solid #666666; z-index: 1000; display: none;">
<p id="toolTipParagraph">备注信息</p>
</div>
let myToolTip = MAKE(go.HTMLInfo, {
show: this.showToolTip, //展示时执行的方法
hide: this.hideToolTip //隐藏时执行的方法
})
在需要移入触发外联html的panel或node配置内
{
toolTip: myToolTip // 放在哪个配置就获取到哪个位置信息(obj参数)
}
在methods中的方法示例
showToolTip (obj, diagram) { // 鼠标移入备注图标显示文字
let toolTipDIV = document.getElementById('toolTipDIV')
var pt = diagram.lastInput.viewPoint
toolTipDIV.style.left = (pt.x + 10) + 'px'
toolTipDIV.style.top = (pt.y + 10) + 'px'
document.getElementById('toolTipParagraph').textContent = '备注: ' + this.showNoticeText
toolTipDIV.style.display = 'block'
},
hideToolTip () {
let toolTipDIV = document.getElementById('toolTipDIV')
toolTipDIV.style.display = 'none'
},
这个api也可以做一些移入指定面板的触发事件;
找到设定名称的面板
比如找到选中节点的面板
Let part = this.myDiagram.selection.first().findObject('NOTICE')
找到后可以修改这个面板的属性
part .setProperties({'visible': true})
放大或者缩小画板
this.myDiagram.scale += 0.1
this.myDiagram.scale -= 0.1
右键点击事件
contextClick : function(e: InputEvent, thisObj: GraphObject)
e.viewPoint能获取鼠标点击坐标
节点API
遍历一个节点的连接点
例子:把每个节点的连接点遍历出来,设置不透明(obj为节点的不可读信息)
obj.ports.each(item => {
item.opacity = 1
})
遍历一个节点的子节点
// Obj为不可读性的节点信息
obj.findTreeChildrenNodes().each(item => {})
遍历画板所有节点
this.myDiagram.nodes.each(function (node) {})
添加新节点
this.myDiagram.model.addNodeData({ category: 'Normal', text: '新节点',等其他属性 })
删除选中节点
this.myDiagram.commandHandler.deleteSelection()
删除所有节点
this.myDiagram.model.removeNodeData
获取选中节点的信息
this.myDiagram.selection.first() //想获取节点信息还需要加个data属性,连线信息加个links属性如果是选中节点数量
this.myDiagram.selection.size
编辑节点文本
this.myDiagram.commandHandler.editTextBlock()
修改节点属性
例如修改选中节点的某个属性
this.myDiagram.model.setDataProperty(this.myDiagram.selection.first(), 'category', 'Model')
这个方式修改的节点信息具有实时刷新性
另外想直接获取选中节点数据,修改或者添加属性,只能在实例化go.js的vue文件中才有效
通过节点属性key来找到节点
mySelf.myDiagram.model.findNodeDataForKey(xxx) //例如要找的节点key=’xxx’
通过名称寻找该节点下的图形,面板等
node.findObject('LATESTVAL') //node为该节点的不可读信息
修改该图形,面板等的属性
xxx.setProperties({'visible': false}) // xxx为通过findObject找到的图形,面板等
获取节点关联的线
node.findLinksConnected().each(function(link) {} //node为该节点的不可读信息
获取节点与之连线的节点
node.findNodesConnected().each(function (node) { 只要有连接关系,间接连接也算
connectedNodes.push(node.data)
})
获取以from方向连接的节点
node.findNodesOutOf().each(function (node) {})
获取以to方向连接该的节点
node. findNodesInto ().each(function (node) {})
连线API
连接线的生成事件
mySelf.myDiagram.addDiagramListener('LinkDrawn', function (e) {})
注意事项
在methods中想获取实例化的画板对象,需要通过this.$nextTick(()=>{})获取