欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

gojs一些实用的高级用法

程序员文章站 2022-03-02 23:11:02
目录1. 取消更新动画2. 导出图(含可视区外的部分)3. 禁用 ctrl 相关快捷键4. 画布滚动模式,无限滚动 or 局部滚动5. 展开收起多层嵌套的组6. 给图元素加动画7. 修改框选的样式1....

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 }));

以上所述是小编给大家介绍的gojs一些实用的高级用法,希望对大家有所帮助。在此也非常感谢大家对网站的支持!