• 图形化引擎antv/G6自定义节点创建紧凑树


    1.参考: G6 TreeGraph树图默认展开几层节点

    graph.data(data)
            graph.render()
            graph.fitCenter() // 移到图中心
            setTimeout(() => {
              // 1 默认展开两层节点,之后,重新渲染
              G6.Util.traverseTree(data, function(item) {
                console.log(item)
                if (item.depth > 0) {
                  //collapsed为true时默认收起
                  item.collapsed = true
                }
              })
              graph.render()
              graph.fitCenter() // 移到图中心
            }, 10)

    2.树形节点增删改,需要重新调用  graph.render()或者 graph.layout()

    3.树形图,右键菜单插件

    以此为例,右键菜单的触发事件回调函数:  handleMenuClick

    const menu = new G6.Menu({
              offsetX: 10,
              offsetY: 10,
              itemTypes: ['node'],
              getContent(e) {
                const {item} = e
                console.log(item.getModel())
                let {bqglParentUuid} = item.getModel()
    
                if (bqglParentUuid == 'root') {
                  return ``
                }
                const outDiv = document.createElement('div')
                outDiv.innerHTML = `<ul class="ant-cascader-menu">
                  <li class="add">增加节点</li>
                  <li class="addClassification">增加分类</li>
                  <li class="del">删除节点</li>
                  <li class="proview">查看节点</li>
                  <li class="edit">编辑节点</li>
                </ul>`
                return outDiv
              },
              handleMenuClick: (target, item) => {
                var nodeId = item.get('id')
    
                const newParentData = graph.findDataById(nodeId)
                let newchildren = newParentData.children
                switch (target.className) {
                  case 'add':
                    var childData = {
                      id: 'child-data-' + new Date().getTime(),
                      type: 'flow-rect',
                      name: 'x-'
                    }
                    graph.addChild(childData, nodeId)
                    graph.render()
                    graph.fitCenter() // 移到图中心
                    graph.fitView()
    
                    break
                  case 'addClassification':
                    console.log(target.innerText)
                    break
                  case 'del':
                    graph.removeChild(nodeId)
                    graph.render()
                    graph.fitCenter() // 移到图中心
                    graph.fitView()
                    // graph.fitView()
                    break
                  case 'proview':
                    console.log(target.innerText)
                    break
                  case 'edit':
                    console.log(target.innerText)
                    break
                  default:
                    break
                }
              }
            })

    4.树形图  矩形上线连接点的位置

    //自定义节点
     G6.registerNode(
              'flow-rect',
        {
            getAnchorPoints() {
                  //矩形上线连接点的位置
                  return [
                    [0.5, 0],
                    [0.5, 1]
                  ]
                }
         },
          'rect'//连接线
            G6.registerEdge('line-arrow', {
              options: {
                style: {
                  stroke: '#ccc'
                }
              },
              draw: function draw(cfg, group) {
                const startPoint = cfg.startPoint
                const endPoint = cfg.endPoint
    
                const stroke = (cfg.style && cfg.style.stroke) || this.options.style.stroke
                const startArrow = (cfg.style && cfg.style.startArrow) || undefined
                const endArrow = (cfg.style && cfg.style.endArrow) || undefined
                //连接线路径
                const keyShape = group.addShape('path', {
                  attrs: {
                    path: [
                      ['M', startPoint.x, startPoint.y],
                      ['L', startPoint.x, (startPoint.y + endPoint.y) / 2],
                      ['L', endPoint.x, (startPoint.y + endPoint.y) / 2],
                      ['L', endPoint.x, endPoint.y]
                    ],
                    stroke,
                    lineWidth: 1,
                    startArrow,
                    endArrow
                  },
                  className: 'edge-shape',
                  name: 'edge-shape'
                })
    
                return keyShape
              }
            })

    5. 点击切换选中

    
    
              setState(name, value, item) {
                  var group = item.getContainer()
                  // 获取外边框
                  var nodeRect = group.find(function(e) {
                    return e.get('name') === 'node-rect'
                  })
                  // 获取任务名称
                  var collapseTitleText = group.find(function(e) {
                    return e.get('name') === 'node-name'
                  })
                  // 获取折叠点
                  var collapseText = group.find(function(e) {
                    return e.get('name') === 'collapse-text'
                  })

               
                  // 设置状态
                  if (name === 'selected') {
                    if (value) {
                      nodeRect.attr({
                        stroke: '#1258ED',
                        lineWidth: 2
                      })
                      collapseTitleText.attr({
                        fill: '#1258ED'
                      })
                    } else {
                      nodeRect.attr({
                        stroke: '#999999',
                        lineWidth: 1
                      })
                      collapseTitleText.attr({
                        fill: '#333'
                      })
                    }
                  }
            }

    //
    点击节点文字 graph.on('node-name:click', e => { const {item} = e graph.setItemState(item, 'selected', !item.hasState('selected')) // 切换选中 })

    6.解决自定义节点动态更新调用graph.render(),坐标问题

    根据G6坐标系的 pointX/pointY  缩放平移不影响  pointX/pointY  坐标计算   ,

    通过记录最初创建时的 画布中心point坐标,计算拖拽后和最初创建的坐标差,在每次render后进行平移

    记录缩放比例,render之后进行还原

    注意:缩放比例和缩放中心的坐标,需要和拖拽后画布中心的坐标一致,否则会有位置差

    
    
    //this.initGraphCenterPoint 为创建时保存的画布中心坐标
       updateGraph() {
          this.graphCenterPoint = graph.getGraphCenterPoint()
          this.graphCenterZoom = graph.getZoom()
          let x = this.graphCenterPoint.x - this.initGraphCenterPoint.x,
            y = this.graphCenterPoint.y - this.initGraphCenterPoint.y
            graph.render()
            graph.fitCenter()
            graph.translate(x, y)
            graph.zoomTo(this.graphCenterZoom, this.graphCenterPoint)
        },

    7.双击节点编辑

       //监听双击点击 
    graph.on('node:dblclick', e => {
            const nodeItem = e.item // 获取被点击的节点元素对象
            that.editNode(e)
            console.log('双击', nodeItem._cfg)
          })
    
    
    //双击编辑
        editNode(evt) {
          let that = this
          const item = evt.item
          const model = item.get('model')
          const {x, y, width, height} = item.calculateBBox()
          const graph = evt.currentTarget
          const realPosition = evt.currentTarget.getClientByPoint(x, y)
          const el = document.createElement('div')
    
          el.style.fontSize = 16 + 'px'
          el.style.position = 'fixed'
          el.style.top = realPosition.y + 'px'
          el.style.left =
            realPosition.x + ((width - G6.Util.getTextSize(model.bqglLabel, 20)[0]) * graph.getZoom()) / 2 + 'px'
          el.style.transformOrigin = 'top left'
          el.style.transform = `scale(${evt.currentTarget.getZoom()})`
          const input = document.createElement('input')
          input.value = model.bqglLabel
          input.style.width = G6.Util.getTextSize(model.bqglLabel, 20)[0] + 'px'
          input.style.fontWeight = 'bold'
          input.style.height = height + 'px'
          input.className = 'dice-input'
          el.className = 'dice-input'
          el.appendChild(input)
          document.body.appendChild(el) 
          const destroyEl = () => {
            document.body.removeChild(el)
          }
          const clickEvt = event => {
            if (
              !(
                event.target &&
                event.target.classList.length &&
                event.target.className &&
                event.target.className.includes('dice-input')
              )
            ) {
              window.removeEventListener('mousedown', clickEvt)
              window.removeEventListener('scroll', clickEvt)
    
              graph.updateItem(item, {
                bqglLabel: input.value
              })
              //更新视图
              that.updateGraph()
    
              graph.layout()
              graph.off('wheelZoom', clickEvt)
              destroyEl()
            }
          }
          graph.on('wheelZoom', clickEvt)
          window.addEventListener('mousedown', clickEvt)
          window.addEventListener('scroll', clickEvt)
          input.addEventListener('keyup', event => {
            if (event.key === 'Enter') {
              clickEvt({
                target: {}
              })
            }
          })
        },

    8.dom节点插入

    SVG 与 DOM 图形在 V3.3.x 中不支持。 仅在 Graph 的 renderer 为 'svg' 时可以使用 DOM 自定义节点。

    new G6.TreeGraph({
      renderer: 'svg',
    })

     G6 的节点/边事件不支持 DOM 类型的图形。如果需要为 DOM 节点绑定事件,请使用原生 DOM 事件

    参考文档:使用-dom-自定义节点

    rectConfig 为基础公共变量配置对象

     rectConfig: {
            //配置项
             200,
            height: 40,
            lineWidth: 1,
            fontSize: 16,
            fill: '#fff', // 填充背景
            radius: 4,
            stroke: '#F7F7F7',
            opacity: 1
          }
    此处代码是循环插入
          cfg.list.forEach((item, i) => {
                      let agrments = `${i},"${cfg.id}","${item.bqglLabel}"`,
                        classList = item.selected ? `childNode selected` : `childNode`
                      group.addShape('dom', {
                        itemData: {
                          bqglUuid: cfg.bqglUuid,
                          bqglType: cfg.bqglType,
                          bqglLabel: cfg.bqglLabel
                        },
                        attrs: {
                          x: nodeOrigin.x + 10,
                          y: i * (rectConfig.height + 5) + nodeOrigin.y + 30,
                           rectConfig.width - 20,
                          height: rectConfig.height,
                          html: `
                          <div class='${classList}'
                            oncontextmenu='nodeChildern(event , ${agrments})'
                            onclick='clickNodeChildern(event , ${agrments})'
                            onmousemove='nodeChildernMοusemove(event, ${agrments})'
                            onmouseout='nodeChildernMοuseout(event, ${agrments})'
                            style='height:${rectConfig.height}px'
                          >
                            <span
                              ondblclick='dbclickNodeChildern(event , ${agrments})'
                            >${that.fittingString(item.bqglLabel, rectBBox.width - 10 * 2 - rectConfig.height, 16)}
                            </span>
                          </div>`
                        },
                        name: 'node-childern-rect'
                      })
                    })
    原生DOM事件函数,在 mounted 中声明 绑定在window上
    //标签右键触发的事件
          window.nodeChildern = (e, index, parentId) => {
            
          }
          //标签点击触发的事件
          window.clickNodeChildern = (e, index, parentId) => {
          
          }
          //标签双击触发的事件
          window.dbclickNodeChildern = (e, index, parentId) => {
         
          }
        //鼠标移入
          window.nodeChildernMοusemove = (e, index, parentId, bqglLabel) => {
           
          }
          //标签鼠标移出
          window.nodeChildernMοuseout = (e, index, parentId, bqglLabel) => {
            t.style.display = 'none'
          }
     

    9.节点偏移量修正

    宽度未自适应,造成重叠的bug

     

    在 getHeight 中改变下高度间距,触发了引擎  layout 重新渲染最终位置被修正
    new G6.TreeGraph({
         layout: {
                type: 'compactBox', //紧凑型树形菜单
                direction: 'TB', //垂直
                dropCap: false,
                getHeight: nodeItem => {
              //添加判断后就可以自适应了
                  if (nodeItem.collapsed) {
                    return rectConfig.height + 30
                  }
                  return rectConfig.height + 20
                },
                getWidth: () => {
                  return rectConfig.width + 40
                }
              },
    })    

    。。。

  • 相关阅读:
    使用ftp软件上传下载php文件时换行丢失bug
    #1045
    wamp虚拟主机的配置 .
    css3很酷的加载动画多款
    理解CSS3 transform中的Matrix(矩阵)
    好吧,CSS3 3D transform变换,不过如此!
    js流程控制语句
    js变量
    js函数
    Gym 100507I Traffic Jam in Flower Town (模拟)
  • 原文地址:https://www.cnblogs.com/wxyblog/p/16017585.html
Copyright © 2020-2023  润新知