内容简介:上一章我们了解了如何使用 gojs 完成基本的节点和连接线的绘制, gojs 中还可以对节点或边进行自由拖动, 编辑等功能; 本章将基于上一章编写的流程图代码, 为这些节点设置装饰器模板完成后的效果图:建议下载源码, 对照本文进行学习, 源码地址:
上一章我们了解了如何使用 gojs 完成基本的节点和连接线的绘制, gojs 中还可以对节点或边进行自由拖动, 编辑等功能; 本章将基于上一章编写的流程图代码, 为这些节点设置装饰器模板
完成后的效果图:
建议下载源码, 对照本文进行学习, 源码地址: github.com/muzqi/sampl…
选择节点装饰器
在默认情况下, 我们用鼠标点击某个节点. 该节点会被一个蓝色的框所包裹,
这个框就是选择节点装饰器
, 如果我们想改变这个框的样式, 我们就需要为节点设置模板
编写模板
const nodeSelectionAdornmentTemplate = // [1] $(go.Adornment, go.Panel.Auto, // [2] $(go.Shape, { fill: null, stroke: 'yellow', strokeWidth: 1, strokeDashArray: [6, 6, 2, 2] }), // [3] // { width: 500, height: 200 } $(go.Placeholder)) 复制代码
代码注释:
- 我们使用
go.Adornment
对象, 创建一个模板, 这实际上跟我们之前学到的节点模板思路是完全一样的, 定义它的 布局方式 , 再定义它的 形状 等属性 - 定义形状, 在这里我们定义了一个描边为黄色的虚线选择节点装饰器
- 设置
go.Placeholder
对象的目的是, 让装饰器自适应节点的大小; 反之, 我们可以自定义装饰器的大小
引入模板
我们来到定义节点模板的地方, 并为 go.Node
对象设置装饰器模板
diagram.nodeTemplateMap.add('node1', $(go.Node, go.Panel.Position, // ... { // [1] selectable: true, // [2] selectionAdornmentTemplate: nodeSelectionAdornmentTemplate } // ... ) ) 复制代码
代码注释:
selectable selectionAdornmentTemplate
调整节点大小装饰器
用过 ps 的同学应该都知道, Ctrl + T
后, 能够唤出调整大小的操作装饰器, 我们现在需要给节点添加一个这样的装饰器, 让它支持 resize
操作
编写模板
const makeNodeResizeShapeOption = (cursor, alignment) => ({ cursor, alignment, desiredSize: new go.Size(12, 12), fill: 'lightyellow', stroke: 'yellow' }) const nodeResizeAdornmentTemplate = // [1] $(go.Adornment, go.Panel.Spot, $(go.Placeholder), // [2] $(go.Shape, makeNodeResizeShapeOption('nw-resize', go.Spot.TopLeft)), $(go.Shape, makeNodeResizeShapeOption('ne-resize', go.Spot.TopRight)), $(go.Shape, makeNodeResizeShapeOption('se-resize', go.Spot.BottomLeft)), $(go.Shape, makeNodeResizeShapeOption('sw-resize', go.Spot.BottomRight)) ) 复制代码
代码注释:
- 同样, 我们还是使用
go.Adornment
来定义装饰器; 在这里, 我们布局方式使用了go.Panel.Spot - 我们定义了四个
go.Shape
, 来表示装饰器的四个拖拽顶点
引入模板
diagram.nodeTemplateMap.add('node1', $(go.Node, go.Panel.Position, // ... { resizable: true, resizeAdornmentTemplate: nodeResizeAdornmentTemplate } // ... ) ) 复制代码
resizeObjectName
调整大小装饰器引入时还可以传入一个 resizeObjectName
值, 表示指定需要应用装饰器的元素, 这个元素可以是 go.Shape
go.Picture
go.Text
任何 gojs
的元素
diagram.nodeTemplateMap.add('node1', $(go.Node, go.Panel.Position, // ... { resizable: true, // [1] resizeObjectName: 'TEXT' resizeAdornmentTemplate: nodeResizeAdornmentTemplate }, // ... $(go.TextBlock, // [2] { name: 'TEXT' } // ... ) ) ) 复制代码
代码注释:
- 设置
resizeObjectName
为TEXT
- 将一个文字块元素的名字设置为
TEXT
如上图所示, 只有文字块被允许设置大小了
旋转节点装饰器
相比较前面的装饰器, 旋转节点装饰器存在一个巨坑;你会发现当你绘制出一个 把手 后, 你除了使用 Position
来绝对定位它, 否则你很难将其相对定位居中展示
官方的实例(其实他并没有被写到文档中去, 而是在demo文件中找到的方法)是将 go.RotatingTool
这个对象给改写掉了, 在初始化的时候, 就将 把手的位置默认居中
请看以下代码:
编写模板
// [1] const makeTopRotatingTool = () => ( class TopRotatingTool extends go.RotatingTool { updateAdornments(part) { go.RotatingTool.prototype.updateAdornments.call(this, part) var adornment = part.findAdornment('Rotating') if (adornment !== null) { // [2] adornment.location = part.rotateObject.getDocumentPoint(new go.Spot(0.5, 0, 0, -30)) // above middle top } } rotate(newangle) { go.RotatingTool.prototype.rotate.call(this, newangle + 90) } } ) // [3] const nodeRotateAdornmentTemplate = $(go.Adornment, $(go.Shape, 'Circle', { cursor: 'pointer', desiredSize: new go.Size(7, 7), fill: 'lightyellow', stroke: 'yellow' }), $(go.Shape, { geometryString: 'M3.5 7 L3.5 30', isGeometryPositioned: true, stroke: 'yellow', strokeWidth: 1.5, strokeDashArray: [4, 2] }) ) // [4] const diagram = $(go.Diagram, 'diagram', { 'initialContentAlignment': go.Spot.Center, 'undoManager.isEnabled': true, 'rotatingTool': $(makeTopRotatingTool()) }) 复制代码
代码注释:
- 我们重新定义了一个类, 这个类继承了
go.RotatingTool
- 我们在这个类中, 定义了 把手 的位置默认是在顶部居中
- 使用
go.Adornment
对象制作模板, 这个模板只负责 把手 最终长成什么样子 - 在初始化
diagram
的时候, 引用自定义的 工具 类makeTopRotatingTool
引用模板
diagram.nodeTemplateMap.add('node1', $(go.Node, go.Panel.Position, // ... { rotatable: true, // [1] // rotateObjectName: 'TEXT' rotateAdornmentTemplate: nodeRotateAdornmentTemplate, // [2] locationSpot: go.Spot.Center }, // ... ) ) 复制代码
代码注释:
rotateObjectName locationSpot
拖拽创建连接线
前面我们已经将所有节点的装饰器添加完成, 最后, 我们需要实现从一个节点到另一个节点, 手动拖出连接线的功能;
为了更清晰的展示这个功能, 我们重新建立一块画布, 单独讲解;
实现原理
在 gojs 模板中, 任何一个元素, 都具备这三个属性:
port
只要具备这三个属性, 任何元素都能够拖出或者接收连接线, 并使两个节点产生连接关系
简单实现
<div id="port" style="width: 1000px; height: 500px"></div> 复制代码
const portDiagram = $(go.Diagram, 'port', { 'initialContentAlignment': go.Spot.Center, 'undoManager.isEnabled': true }) // 指定被创建的连接线的模板 portDiagram.linkTemplate = $(go.Link, $(go.Shape, { stroke: 'black', strokeWidth: 3 }) ) // 指定被创建的节点的模板 portDiagram.nodeTemplate = $(go.Node, new go.Binding('position'), $(go.Shape, { fill: 'blue', fromLinkable: true, toLinkable: true }, new go.Binding('portId', 'key') ) ) portDiagram.model = new go.GraphLinksModel( [ { key: '1', position: new go.Point(500, 0) }, { key: '2', position: new go.Point(0, 0) } ] ) 复制代码
细心的同学就会发现了, 现在我们的整个节点作为一个 port
, 只要鼠标点击拖动节点, 就会拉出一条连接线, 但如果我们需要移动节点怎么办?
所以通常情况下, 我们会在节点中绘制几个点, 让这几个点具备拖拽接收连接线的功能;
改写上面的代码:
// ... const makePort = (portId, spot) => ( $(go.Shape, { cursor: 'pointer', fill: 'red', width: 10, height: 10, alignment: spot, portId, fromLinkable: true, toLinkable: true }) ) portDiagram.nodeTemplate = $(go.Node, go.Panel.Spot, new go.Binding('position'), $(go.Shape, { fill: 'blue' }), makePort('T', go.Spot.Top), makePort('B', go.Spot.Bottom), makePort('L', go.Spot.Left), makePort('R', go.Spot.Right), ) // ... 复制代码
实现效果如下:
下章继续讲解, 连接线的编辑模板
(未完待续)
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- C++源码流程图分析!
- R语言绘制流程图(二)
- 自己调研的常用开源流程图组件
- yEd 3.21 发布,流程图绘制工具
- BPMN学习第一步:简单的流程图
- 使用markdown画流程图/甘特图 - Mermaid
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。