zoukankan      html  css  js  c++  java
  • gojs 实用高级用法

    大家,新年好!

    历史文章:

    本文介绍的是在使用 gojs 制作图的过程中,你可能会碰到的问题的一些解决方案。

    gojs 是一个非常强大的可视化关系的js库。

    1. 取消更新动画

    问题:更新数据的时候,会触发渲染,有渲染动画,用户体验不好。

    方案:初始数据绘制,有动画;更新数据绘制,无动画。

    代码实现:

    // 后面所用到的 diagram 都是 gojs 创建的实例
    // diagram_container 为图容器dom id
    diagram = $(go.Diagram, 'diagram_container') 
    

    方案一:

    function updateData (nodeArr = [], linkArr = [], hasAnimation = true ) {
      if (hasAnimation) {
        diagram.model = new go.GraphLinksModel(nodeArr, linkArr);
      } else {
        diagram.model.nodeDataArray = nodeArr
        diagram.model.linkDataArray = linkArr
      }
    }
    
    // 初始化实例后处理,只用一次
    diagram.animationManager.canStart = function(reason) {
      if (reason === 'Model') return false
      return true
    }
    

    方案二:

    // 绑定数据至 diagram,绘制图
    function updateData (nodeArr = [], linkArr = [], hasAnimation = true ) {
      if (hasAnimation) {
        diagram.model = new go.GraphLinksModel(nodeArr, linkArr);
      } else {
        diagram.model.nodeDataArray = nodeArr
        diagram.model.linkDataArray = linkArr
        diagram.animationManager.stopAnimation()
      }
    }
    

    方案三:

    // 绑定数据至 diagram,绘制图
    function updateData (nodeArr = [], linkArr = [], hasAnimation = true) {
      diagram.model = new go.GraphLinksModel(nodeArr, linkArr);
      if (diagram.animationManager) {
        // Default 有动画,None 没有动画
        diagram.animationManager.initialAnimationStyle = hasAnimation ? go.AnimationManager.Default : go.AnimationManager.None;
      }
    }
    

    2. 导出图(含可视区外的部分)

    问题:导出图,利用原生 canvas 相关 api 实现的导出图片,只包含可视区内的

    解决:利用 gojs 提供的 api 处理

    背后原理:利用数据重新绘制一份图,所有数据节点都在的图可视区内,然后利用原生 canvas 相关 api 实现导出图片

    代码实现:

    function downloadImg = ({
      imgName = 'dag',
      bgColor = 'white',
      imgType = 'image/png'
    }= {}) {
      diagram.makeImageData({
        scale: 2,
        padding: new go.Margin(50, 70),
        maxSize: new go.Size(Infinity, Infinity),
        background: bgColor,
        type: imgType,
        returnType: 'blob',
        callback: (blob: any) => {
          const url = window.URL.createObjectURL(blob)
          const fileName = imgName + '.png'
          const aEl = document.createElement('a')
          aEl.style.display = 'none'
          aEl.href = url
          aEl.download = fileName
    
          // IE 11
          if (window.navigator.msSaveBlob !== undefined) {
            window.navigator.msSaveBlob(blob, fileName)
            return
          }
    
          document.body.appendChild(aEl)
          requestAnimationFrame(function() {
            aEl.click()
            window.URL.revokeObjectURL(url)
            document.body.removeChild(aEl)
          })
        }
      })
    }
    

    3. 禁用 ctrl 相关快捷键

    // 禁用 ctl 相关操作
    diagram.commandHandler.doKeyDown = function() {
      const e = diagram.lastInput
      const control = e.control || e.meta
      const key = e.key
    
      // 取消 Ctrl+A/Z/Y/G  A-全选、Z-撤销、Y-重做、G-分组
      if (control && ['A', 'Z', 'Y', 'G'].includes(key)) return
      // 取消 Del/Backspace 删除键
      if (key === 'Del' || key === 'Backspace') return
    
      go.CommandHandler.prototype.doKeyDown.call(this)
    }
    

    4. 画布滚动模式,无限滚动 or 局部滚动

    问题:mac 上 触摸键能左滑右滑控制浏览器页面前进后退,很容易触发

    方案:开启无限滚动,避免用户不小心触发了浏览器的前进后退

    代码实现:

    function infiniteScroll = (infiniteScroll) {
      this.diagram.scrollMode = infiniteScroll ? go.Diagram.InfiniteScroll : go.Diagram.DocumentScroll
    }
    

    5. 展开收起多层嵌套的组

    问题:组多层嵌套,全部展开后,点击单个组收起第一次无效,第二次点击才生效

    代码实现:

    方式一:nodeArr 没有绑定 展开收起 属性

    // groupIds 为所有 group 的ids,从外到内。 一开始遍历组装数据的时候就收集好
    // groupIdsReverse 为所有 group 的ids,从内到外
    // 全部展开,从外到内
    // 全部收起,从内到外
    function setExpandCollapse (isExpand, groupIds, groupIdsReverse) {
      // 展开和折叠需要从两个方向处理,再次展开折叠交互才正常,否则第一次点无效,需要点第二次材有限
      let arr = isExpand ? groupIds : groupIdsReverse;
      let group;
    
      arr.forEach(id => {
        group = diagram.findNodeForKey(id);
        group.isSubGraphExpanded = isExpand;
      })
    },
    

    方式二:nodeArr 绑定 展开收起 属性 isExpanded

    function setExpandCollapse (isExpand) {
      const { nodeDataArray, linkDataArray } = diagram.model
      const newNodeArr = nodeDataArray.map(v => {
        if (v.isGroup) {
          return {...v, isExpanded: isExpand}
        }
        return v
      })
    
      // 上面的方法
      updateData(newNodeArr, linkArr, false)
    }
    

    6. 给图元素加动画

    • 虚线动画
    • icon loading 旋转动画

    代码实现:

    function loop = () {
      const animationTimer = setTimeout(() => {
        clearTimeout(animationTimer)
        const oldskips = diagram.skipsUndoManager;
        diagram.skipsUndoManager = true;
    
        // 虚线动画
        diagram.links.each((link: any) => {
          const dashedLinkShape = link.findObject("dashedLink");
          if (dashedLinkShape) {
            const off = dashedLinkShape.strokeDashOffset - 3;
            // 设置(移动)笔划划动画
            dashedLinkShape.strokeDashOffset = (off <= 0) ? 60 : off;
          }
        });
    
        // loading 旋转
        diagram.nodes.each((node: any) => {
          const loadingShape = node.findObject("loading");
          if (loadingShape) {
            const angle = loadingShape.angle + 20;
            // 设置(移动)笔划划动画
            loadingShape.angle = (angle == 0) ? 360 : angle;
          }
        });
    
        diagram.skipsUndoManager = oldskips;
        loop();
      }, 180);
    }
    loop()
    

    7. 修改框选的样式

    问题:框选样式:默认是红色的,和自定义的图颜色不匹配

    diagram.toolManager.dragSelectingTool.box = $(go.Part,
      { layerName: "Tool", selectable: false },
      $(go.Shape,
        { name: "SHAPE", fill: 'rgba(104, 129, 255, 0.2)', stroke: 'rgba(104, 129, 255, 0.5)', strokeWidth: 2 }));
    

    希望对你有帮助,如果有帮助,请点个攒,谢谢!

  • 相关阅读:
    医疗器械那些事
    内审员学习1
    BA
    GMP文件分类与编码管理规程
    杂-电工学
    产品学习1
    模拟电子技术1
    电路组装1
    Unable to simultaneously satisfy constraints.
    xcode
  • 原文地址:https://www.cnblogs.com/EnSnail/p/15754962.html
Copyright © 2011-2022 走看看