gojs 拓扑图虚线动画效果

0. 效果及场景描述

先放一张效果图,简单描述下业务场景,有一台设备报错后,边框标红展示,且虚线线段置为灰色不再流动,进行告警展示。

1. gojs初始化

网上很多gojs的基础使用,npm安装及介绍就不过多赘述了。

npm 安装引入后,所需页面引入后,进行全局的声明:

import go from 'gojs'

const $ = go.GraphObject.make; // 该声明方便接下来的使用

2. 虚线设置方法

核心就是name设置, 通过状态对线条名字赋值,为下一步动画筛选正常状态的设备做铺垫

  $(go.Shape, {strokeWidth: 4, strokeDashArray: [6, 5]}, // 线条设置为虚线效果
              new go.Binding("name", param => {
                return mySelf.nameSet(param); // 通过状态对线条名字赋值,为下一步动画筛选正常状态的设备做铺垫
              }),
              new go.Binding("stroke", param => {
                return mySelf.colorSet(param);
              })),
          $(go.Shape,
              {toArrow: "Standard", stroke: null}, // 箭头效果
              new go.Binding("stroke", param => {
                return mySelf.colorSet(param);
              }),
              new go.Binding("fill", param => {
                return mySelf.colorSet(param);
              })),
          $(go.Panel, "Auto",
              $(go.Shape, "RoundedRectangle",  // 连杆形状   左边的圆角矩形
                  {fill: "transparent", stroke: null}),
              $(go.TextBlock, // 断开报警信息文字,上图中灰色虚线上的红色X
                  {
                    textAlign: "center",
                    font: "18pt helvetica, arial, sans-serif",
                    stroke: "red",
                    margin: 2,
                    editable: true
                  },
                  new go.Binding("text").makeTwoWay()),
              $(go.TextBlock, new go.Binding('text', 'text'))
          ));

3. 动态设置颜色或名称赋值的方法

 nameSet(param) {
      switch (param.type) {
        case 0:
          return "dashedLink";
        case 1:
          return "";
        default:
          return "dashedLink";
      }
    },
    colorSet(param) {
      switch (param.type) {
        case 0:
          return "#43a298";
        case 1:
          return "#999";
        default:
          return "#43a298";
      }
    },
    backgroundSet(param) {
      switch (param.type) {
        case 0:
          return "#43a298";
        case 1:
          return "#ff5e62";
        default:
          return "#43a298";
      }
    },

4. 虚线动画效果

核心就是通过对线条名称筛选,定位状态正常的线条做动画处理

animation() {
      const loop = () => {
        const mySelf = this;
        // clearTimeout(this.animationTimer);
        mySelf.animationTimer = setTimeout(() => {
          const oldskips = mySelf.myDiagram.skipsUndoManager;
          mySelf.myDiagram.skipsUndoManager = true;
          // 虚线动画
          mySelf.myDiagram.links.each((link) => {
            const dashedLinkShape = link.findObject("dashedLink"); // 选择名称为dashedLink进行动画加载
            if (dashedLinkShape) {
              const off = dashedLinkShape.strokeDashOffset - 3;
              // 设置(移动)笔划划动画
              dashedLinkShape.strokeDashOffset = (off <= 0) ? 60 : off;
            }
          });
          mySelf.myDiagram.skipsUndoManager = oldskips;
          loop();
        }, 100);
      }
      loop()
    }

5. 数据源设置

其中节点和线段中的type表示告警状态,0:正常;1:告警

data() {
    return {
      animationTimer: null,
      nodeData: [
        {category: "dashed", text: "192.168.0.1", key: 0, source: require('@/assets/img/icon-server.png')},
        {category: "dashed", text: "192.168.2.1", key: 1, source: require('@/assets/img/icon-device.png')},
        {category: "dashed", text: "192.168.3.1", key: 2, source: require('@/assets/img/icon-device.png')},
        {category: "dashed", text: "192.168.4.1", key: 3, type: 1, source: require('@/assets/img/icon-router.png')},
        {category: "dashed", text: "192.168.5.1", key: 4, source: require('@/assets/img/icon-router.png')},
        {category: "dashed", text: "192.168.6.1", key: 5, type: 1, source: require('@/assets/img/icon-trans.png')},
      ],
      linkData: [
        {from: 0, to: 1, type: 0},
        {from: 1, to: 3, type: 1, text: 'x'},
        {from: 1, to: 2, type: 0},
        {from: 1, to: 4, type: 0},
        {from: 2, to: 5, type: 1, text: 'x'},
      ],
    }
  },

 6. 汇总

其实第一次用gojs,感觉是把基础canvas扩展的很好,建议新手入门还是多看下api,官网API地址点这里☞GoJS API

可以满足大部分的使用场景,真的强大~

最后贴上全部的代码

<template>
  <div id="myDiagramDiv"></div>
</template>

<script>
import go from 'gojs'

const $ = go.GraphObject.make;
export default {
  data() {
    return {
      animationTimer: null,
      nodeData: [
        {category: "dashed", text: "192.168.0.1", key: 0, source: require('@/assets/img/icon-server.png')},
        {category: "dashed", text: "192.168.2.1", key: 1, source: require('@/assets/img/icon-device.png')},
        {category: "dashed", text: "192.168.3.1", key: 2, source: require('@/assets/img/icon-device.png')},
        {category: "dashed", text: "192.168.4.1", key: 3, type: 1, source: require('@/assets/img/icon-router.png')},
        {category: "dashed", text: "192.168.5.1", key: 4, source: require('@/assets/img/icon-router.png')},
        {category: "dashed", text: "192.168.6.1", key: 5, type: 1, source: require('@/assets/img/icon-trans.png')},
      ],
      linkData: [
        {from: 0, to: 1, type: 0},
        {from: 1, to: 3, type: 1, text: 'x'},
        {from: 1, to: 2, type: 0},
        {from: 1, to: 4, type: 0},
        {from: 2, to: 5, type: 1, text: 'x'},
      ],
    }
  },
  mounted() {
    this.init();
    this.animation();
  },
  destroyed() {
    clearTimeout(this.animationTimer);
  },
  methods: {
    init() {
      class DemoForceDirectedLayout extends go.ForceDirectedLayout { //布局
        makeNetwork(coll) {
          const net = super.makeNetwork(coll);
          net.vertexes.each(vertex => {
            const node = vertex.node;
            if (node !== null) vertex.isFixed = node.isSelected;
          });
          return net;
        }
      }

      const mySelf = this;
      mySelf.myDiagram =
          $(go.Diagram, "myDiagramDiv",  // 为DIV.HTML元素创建一个画布
              {
                initialContentAlignment: go.Spot.Center, // 居中显示
                "undoManager.isEnabled": false, // 支持 Ctrl-Z 和 Ctrl-Y 操作
                "toolManager.hoverDelay": 100, //tooltip提示显示延时
                "toolManager.toolTipDuration": 10000, //tooltip持续显示时间
                isReadOnly: true,//只读
                "grid.visible": false, //显示网格
                allowMove: false, //允许拖动
                allowDragOut: false,
                allowDelete: false,
                allowCopy: false,
                allowClipboard: true, initialAutoScale: go.Diagram.Uniform,  // 缩放以使所有内容都适合
                "toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom, //有鼠标滚轮事件放大和缩小,而不是向上和向下滚动
                layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
                    {angle: 90, layerSpacing: 90})
              });
      // 节点模板设置
      mySelf.myDiagram.nodeTemplate =
          $(go.Node, "auto",
              $(go.Shape,
                  {
                    width: 150,
                    height: 70,
                    fill: $(go.Brush, "Linear", {0: "#f2fcfe", 1: "#c9d6ff"}), // 背景色渐变设置
                    strokeWidth: 3,
                  }, new go.Binding("stroke", param => {
                    return mySelf.backgroundSet(param); // 根据设备状态设置边框颜色
                  })),
              $(go.Picture,
                  {margin: new go.Margin(17, 0, 0, 12), width: 40, height: 40, background: "transparent"},
                  new go.Binding("source")),
              $(go.TextBlock, {//声明一个可编辑文本域
                    font: "11pt Helvetica, Arial, sans-serif",
                    width: 130,
                    textAlign: 'end',
                    maxSize: new go.Size(30, NaN),
                    wrap: go.TextBlock.None,
                    editable: true,
                    margin: new go.Margin(30, 0, 0, 10), // 文本margin的设置,遵循css规则:上右下左
                  },
                  new go.Binding("stroke", param => {
                    return mySelf.backgroundSet(param); // 根据设备状态设置文字颜色
                  }),
                  new go.Binding("text").makeTwoWay()
              ),
          );
      // 节点之间的连线模板
      mySelf.myDiagram.linkTemplate = $(go.Link,
          {selectable: false}, // 是否可以选中
          {
            routing: go.Link.AvoidsNodes,
            curve: go.Link.JumpOver,
            corner: 0,
            toShortLength: 0
          }, // 曲度相关
          new go.Binding("points").makeTwoWay(),
          $(go.Shape, {strokeWidth: 4, strokeDashArray: [6, 5]}, // 线条设置为虚线效果
              new go.Binding("name", param => { // 通过状态对线条名字赋值,为下一步动画筛选正常状态的设备做铺垫
                return mySelf.nameSet(param);
              }),
              new go.Binding("stroke", param => {
                return mySelf.colorSet(param);
              })),
          $(go.Shape,
              {toArrow: "Standard", stroke: null}, // 箭头效果
              new go.Binding("stroke", param => {
                return mySelf.colorSet(param);
              }),
              new go.Binding("fill", param => {
                return mySelf.colorSet(param);
              })),
          $(go.Panel, "Auto",
              $(go.Shape, "RoundedRectangle",  // 连杆形状   左边的圆角矩形
                  {fill: "transparent", stroke: null}),
              $(go.TextBlock, // 断开报警信息文字,上图中灰色虚线上的红色X
                  {
                    textAlign: "center",
                    font: "18pt helvetica, arial, sans-serif",
                    stroke: "red",
                    margin: 2,
                    editable: true
                  },
                  new go.Binding("text").makeTwoWay()),
              $(go.TextBlock, new go.Binding('text', 'text'))
          ));
      mySelf.myDiagram.model.nodeDataArray = mySelf.nodeData;
      mySelf.myDiagram.model.linkDataArray = mySelf.linkData;
    },
    nameSet(param) {
      switch (param.type) {
        case 0:
          return "dashedLink";
        case 1:
          return "";
        default:
          return "dashedLink";
      }
    },
    colorSet(param) {
      switch (param.type) {
        case 0:
          return "#43a298";
        case 1:
          return "#999";
        default:
          return "#43a298";
      }
    },
    backgroundSet(param) {
      switch (param.type) {
        case 0:
          return "#43a298";
        case 1:
          return "#ff5e62";
        default:
          return "#43a298";
      }
    },
    animation() {
      const loop = () => {
        const mySelf = this;
        // clearTimeout(this.animationTimer);
        mySelf.animationTimer = setTimeout(() => {
          const oldskips = mySelf.myDiagram.skipsUndoManager;
          mySelf.myDiagram.skipsUndoManager = true;
          // 虚线动画
          mySelf.myDiagram.links.each((link) => {
            const dashedLinkShape = link.findObject("dashedLink"); // 选择名称为dashedLink进行动画加载
            if (dashedLinkShape) {
              const off = dashedLinkShape.strokeDashOffset - 3;
              // 设置(移动)笔划划动画
              dashedLinkShape.strokeDashOffset = (off <= 0) ? 60 : off;
            }
          });
          mySelf.myDiagram.skipsUndoManager = oldskips;
          loop();
        }, 100);
      }
      loop()
    }
  }
}
</script>

<style lang="less" scoped>
#myDiagramDiv {
  height: 900px;
}

</style>

猜你喜欢

转载自blog.csdn.net/jinse29/article/details/129705183
今日推荐