gojs 流程图框架-编辑类模板(二)

栏目: Html · 发布时间: 6年前

内容简介:上一章我们了解了如何使用 gojs 完成基本的节点和连接线的绘制, gojs 中还可以对节点或边进行自由拖动, 编辑等功能; 本章将基于上一章编写的流程图代码, 为这些节点设置装饰器模板完成后的效果图:建议下载源码, 对照本文进行学习, 源码地址:

上一章我们了解了如何使用 gojs 完成基本的节点和连接线的绘制, gojs 中还可以对节点或边进行自由拖动, 编辑等功能; 本章将基于上一章编写的流程图代码, 为这些节点设置装饰器模板

完成后的效果图:

gojs 流程图框架-编辑类模板(二)

建议下载源码, 对照本文进行学习, 源码地址: github.com/muzqi/sampl…

选择节点装饰器

在默认情况下, 我们用鼠标点击某个节点. 该节点会被一个蓝色的框所包裹,

gojs 流程图框架-编辑类模板(二)
这个框就是 选择节点装饰器

, 如果我们想改变这个框的样式, 我们就需要为节点设置模板

编写模板

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))
复制代码

代码注释:

  1. 我们使用 go.Adornment 对象, 创建一个模板, 这实际上跟我们之前学到的节点模板思路是完全一样的, 定义它的 布局方式 , 再定义它的 形状 等属性
  2. 定义形状, 在这里我们定义了一个描边为黄色的虚线选择节点装饰器
  3. 设置 go.Placeholder 对象的目的是, 让装饰器自适应节点的大小; 反之, 我们可以自定义装饰器的大小

引入模板

我们来到定义节点模板的地方, 并为 go.Node 对象设置装饰器模板

diagram.nodeTemplateMap.add('node1',
    $(go.Node, go.Panel.Position,
        // ...
        {
            // [1]
            selectable: true,
            // [2]
            selectionAdornmentTemplate: nodeSelectionAdornmentTemplate
        }
        // ...
    )
)
复制代码

代码注释:

selectable
selectionAdornmentTemplate
gojs 流程图框架-编辑类模板(二)

调整节点大小装饰器

用过 ps 的同学应该都知道, Ctrl + T 后, 能够唤出调整大小的操作装饰器, 我们现在需要给节点添加一个这样的装饰器, 让它支持 resize 操作

gojs 流程图框架-编辑类模板(二)

编写模板

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))
)
复制代码

代码注释:

  1. 同样, 我们还是使用 go.Adornment 来定义装饰器; 在这里, 我们布局方式使用了go.Panel.Spot
  2. 我们定义了四个 go.Shape , 来表示装饰器的四个拖拽顶点

引入模板

diagram.nodeTemplateMap.add('node1',
    $(go.Node, go.Panel.Position,
        // ...
        {
            resizable: true,
            resizeAdornmentTemplate: nodeResizeAdornmentTemplate
        }
        // ...
    )
)
复制代码
gojs 流程图框架-编辑类模板(二)

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' }
            // ...
        )
    )
)
复制代码

代码注释:

  1. 设置 resizeObjectNameTEXT
  2. 将一个文字块元素的名字设置为 TEXT
gojs 流程图框架-编辑类模板(二)

如上图所示, 只有文字块被允许设置大小了

旋转节点装饰器

相比较前面的装饰器, 旋转节点装饰器存在一个巨坑;你会发现当你绘制出一个 把手 后, 你除了使用 Position 来绝对定位它, 否则你很难将其相对定位居中展示

官方的实例(其实他并没有被写到文档中去, 而是在demo文件中找到的方法)是将 go.RotatingTool 这个对象给改写掉了, 在初始化的时候, 就将 把手的位置默认居中

gojs 流程图框架-编辑类模板(二)

请看以下代码:

编写模板

// [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())
})
复制代码

代码注释:

  1. 我们重新定义了一个类, 这个类继承了 go.RotatingTool
  2. 我们在这个类中, 定义了 把手 的位置默认是在顶部居中
  3. 使用 go.Adornment 对象制作模板, 这个模板只负责 把手 最终长成什么样子
  4. 在初始化 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

只要具备这三个属性, 任何元素都能够拖出或者接收连接线, 并使两个节点产生连接关系

简单实现

gojs 流程图框架-编辑类模板(二)
<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),
  )
  
// ...
复制代码

实现效果如下:

gojs 流程图框架-编辑类模板(二)

下章继续讲解, 连接线的编辑模板

(未完待续)


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序员面试算法宝典

程序员面试算法宝典

猿媛之家 / / 机械工业 / 2018-09-01 / 69.0

一起来看看 《程序员面试算法宝典》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具