前言

此使用教程的内容只是个人制作产品时,根据需要实现功能进行文档记录,需要完整的使用文档需要自行去官方文档查看。

注意:本文档适用于开发类似思维导图的功能,需要其他样式可以查看官方文档的例子。


安装和引入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(()=>{})获取

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐