GoJs实现Tab和Enter新增下级和同级节点

428 阅读3分钟

前言

上文中说到了通过图标来新增节点和切换父级节点,而在有些可视化图形在新增同级节点和下级节点的时候会用到类似xmind的快捷键,也就是用Tab键来快速新增下级节点,用Enter键来快速新增同级节点,本文主要是实现这两种方式。

准备工作

和上文的新增和切换一样,本文将依然采用相同的数据。首先显示的数据如下

//data
nodes: [
  { key: "1", text: "三国",parent:0  },
  { key: "1-1", text: "魏",parent:1  },
  { key: "1-2", text: "蜀",parent:1 },
  { key: "1-3", text: "吴",parent:1  },
],
links: [
  {
    from: "1",
    to: "1-1",
  },
  {
    from: "1",
    to: "1-2",
  },
  {
    from: "1",
    to: "1-3",
  },
],

//methods
this.myDiagram.nodeTemplate = $$(
  go.Node,
  "Auto",
  $$(
    go.Shape,
    "Rectangle",
    { fill:"#0000FF" },
  ),
  $$(
    go.Panel,"Horizontal",{margin:new go.Margin(3,10)},
    $$(go.TextBlock,{stroke:"#FFF",margin:new go.Margin(3,10),click:this.nodeClick, font: "23px 微软雅黑,sans-serif ",editable: true,}, new go.Binding("text", "text")),
    $$(go.Panel,"Auto",$$(go.Shape, "Rectangle", {strokeWidth: 0,width: 50,height: 50,cursor: "pointer",click: this.visNode,fill: "transparent",}),
    $$(go.Shape,{fill:"#FFF",width: 50,margin:new go.Margin(3,10),click: this.visNode, height: 50,angle: 180,geometry:VisIcon}),),
    $$(go.Panel,"Auto",$$(go.Shape, "Rectangle", {strokeWidth: 0,width: 50,height: 50,cursor: "pointer",click: this.lowLevelNode,fill: "transparent",}),
    $$(go.Shape,{fill:"#FFF",width: 50,margin:new go.Margin(3,10),click: this.lowLevelNode, height: 50,angle: 180,geometry:lowLevelIcon}))
  ),
);

image.png 其节点的样式和上篇文章类似,只是换了两个图标,左边图标后面绑定新增同级节点的事件,右面图标绑定新增下级节点的事件。

新增下级节点

新增下级节点的方法上文已经提到过。其示例代码如下

lowLevelNode(code,obj){
    let nodeData = obj.part.data
    this.oldNodeData = obj
    let newNodeData = {text:"下级节点",parent:nodeData.key}
    let newLinkData = {}
    let newKey = JSON.parse(JSON.stringify(nodeData.key + "-" + this.getNewNum(nodeData.key)));
    newNodeData.key = newKey
    newLinkData.from = nodeData.key
    newLinkData.to = newKey
    this.myDiagram.model.addNodeData(newNodeData);
    this.myDiagram.model.addLinkData(newLinkData);
},

5.gif 新增节点的方法还是根据点击节点为起点设置为新节点的parent以及linksto属性。然后执行新增节点和新增连线的方法就行。

新增同级节点

新增同级节点的思路就是以当前节点通过parent去寻找上级节点,然后parent为新增节点的parent。然后parent为新增连线的from,通过计算出同级节点数来动态修改新节点的key这里可以注意一点就是,如果是属性布局可以依靠parent字段来保证上下级关系,不用link数据,但是其他的布局方式是需要的,这里就是把两种都给添加上。其示例如下

visNode(code,obj){
    let nodeData = obj.part.data
    this.oldNodeData = obj
    let newNodeData = {text:"同级节点",parent:nodeData.parent}
    let newLinkData = {}
    let newKey = nodeData.key.slice(0, nodeData.key.length - 1) + this.getNewNum(nodeData.parent);
    newNodeData.key = newKey
    newLinkData.from = nodeData.parent
    newLinkData.to = newKey
    this.myDiagram.model.addNodeData(newNodeData);
    this.myDiagram.model.addLinkData(newLinkData);
},

5.gif

分别通过Tab键和Enter键来新增节点

这里需要注意Tab键的keyCode9EnterkeyCode13。然后通过工具类commandHandler.doKeyDown来获取到按键的对象信息,其代码如下

this.myDiagram.commandHandler.doKeyDown = function (event) {
    let e = event || window.event || arguments.callee.caller.arguments[0];
    if (e && e.keyCode == 9) {
      _this.lowLevelNode('下级',_this.oldNodeData);
    }
    if (e && e.keyCode == 13) {
      _this.visNode('同级',_this.oldNodeData);
    }
};

首先是对案件对象的一个兼容性处理,然后分别判断案件对象的keyCode去执行新增同级节点和新增下级节点的方法。这里需要注意,这里重新调用该方法是获取不到其点击事件的第二个参数obj的,因此需要你在点击图标的时候用变量接收一下点击事件的obj,然后再案件的这个工具类的回调函数中传递过去,本示例中使用的是oldNodeData此处因为无法录制案件,所以就放对应的操作图片了,如果有兴趣的话可以自己尝试一下。

操作中的一些小问题兼容

由上面的例子中可以看出,是需要先点击选中操作的节点,然后才对选中操作的节点进行一个新增同级和下级节点的操作。因此如果只是在两个点击事件里面去接收一下的话就会出现问题。例如点击图标之外的的区域选中节点的话就无法获取到节点的obj,因此在使用按键的时候就会报错,因此可以给左面的文字部分也加上一个点击事件接收一下选中节点的obj

nodeClick(code,obj){
    this.oldNodeData = obj
}

总结

本文是通过工具类来兼容按键的点击之后根据keyCode来判断不同的按键点击之后去执行原本绑定的一个操作逻辑来实现脑图部分的快捷键操作。