Antv G6 force分布式布局 icon“+“ “-“收缩自定义,关系图子节点

子节点收缩

javascript 复制代码
    const collapseIcon = (x, y, r) => {
       // 折叠
       return [
         ['M', x - r, y],
         ['a', r, r, 0, 1, 0, r * 2, 0],
         ['a', r, r, 0, 1, 0, -r * 2, 0],
         ['M', x - r + 4, y],
         ['L', x - r + 2 * r - 4, y]
       ]
     }
     const expandIcon = (x, y, r) => {
       // 拓展
       return [
         ['M', x - r, y],
         ['a', r, r, 0, 1, 0, r * 2, 0],
         ['a', r, r, 0, 1, 0, -r * 2, 0],
         ['M', x - r + 4, y],
         ['L', x - r + 2 * r - 4, y],
         ['M', x - r + r, y - r + 4],
         ['L', x, y + r - 4]
       ]
     }
draw(cfg, group) {
      const { noSubsetSty, collapsed } = cfg
      if (noSubsetSty) { // 需要折叠的节点标志,在数据中处理添加标记
        group.addShape('circle', {
          attrs: {
            x: size,
            y: 0,
            r: 13,
            fill: 'rgba(47, 84, 235, 0.15)',
            opacity: 0,
            zIndex: -2
          },
          name: 'collapse-icon-bg'
        })
        group.addShape('marker', {
          attrs: {
            x: size,
            y: 0,
            r: 7,
            symbol: collapsed ? collapseIcon : expandIcon,
            stroke: 'rgba(0,0,0,1)',
            fill: 'rgba(0,0,0,0)',
            lineWidth: 1,
            cursor: 'pointer'
          },
          name: 'collapse-icon'
        })
      }
    },
    afterDraw(cfg, group) {
      const icon = group.find(
        element => element.get('name') === 'collapse-icon'
      )
      if (icon) {
        const bg = group.find(
          element => element.get('name') === 'collapse-icon-bg'
        )
        icon.on('mouseenter', () => {
          bg.attr('opacity', 1)
        })
        icon.on('mouseleave', () => {
          bg.attr('opacity', 0)
        })
      }
    },
    setState(name, value, item) {
      const group = item.getContainer()
      if (group.get('children')) {
        if (name === 'collapsed') {
          const marker = item
            .get('group')
            .findAll(ele => ele.get('name') === 'collapse-icon')
          marker[0] &&
            marker[0].attr('symbol', value ? collapseIcon : expandIcon)
          if (item._cfg.model.depth === 0) {
            marker[1] &&
              marker[1].attr('symbol', value ? collapseIcon : expandIcon)
          }
        }
      }
    }
javascript 复制代码
 this.graph.on('node:click', e => {
        // 处理子节点展示问题 + -
        if (e.target.get('name') === 'collapse-icon') {
          const item = e.item
          const nodeId = item.get('id')
          const children = selectedWorks(nodeId, regroup.nodes, regroup.edges) // 查询相关子节点
          let newNodes = children.nodes
          if (newNodes.length) {
            if (e.item._cfg.model.collapsed) {
              for (let i = 0; i < newNodes.length; i++) {
                this.hiddenElements.push(newNodes[i].id)
                const item = this.graph.findById(newNodes[i].id)
                this.graph.hideItem(item, true)
                this.graph.paint()
              }
            } else {
              for (let i = 0; i < newNodes.length; i++) {
                this.hiddenElements.splice(
                  this.hiddenElements.indexOf(newNodes[i].id),
                  1
                )
                const item = this.graph.findById(newNodes[i].id)
                this.graph.showItem(item, true)
                this.graph.paint()
              }
            }
          }
          this.graph.layout({
            type: 'force',
            nodeSize: 50,
            preventOverlap: true,
            animate: false,
            linkDistance: d => {
              return 80
            },
            nodeStrength: -150,
            onTick: () => {
              this.graph.refreshPositions()
            },
            nodeSpacing: d => {
              return 80
            }
          })
          e.item._cfg.model.collapsed = !e.item._cfg.model.collapsed
          this.graph.setItemState(
            e.item,
            'collapsed',
            e.item._cfg.model.collapsed
          )
          this.graph.paint()
        }
      })

节点查找方法

javascript 复制代码
/**
 * 只有被指向的点并且没有指向的点  找最末端的点,并且被指向的方向只有一个
 * source ---->  target
 */
export function noSubsetHandle(nodeID, edges) {
  let idT = edges.map(i => i.target)
  let idS = edges.map(i => i.source)
  Array.prototype.countCertainElements = function(value) {
    return this.reduce((sum, element) => (element == value ? sum + 1 : sum), 0)
  }
  let index = idT.countCertainElements(nodeID)
  let results =
    idT.indexOf(nodeID + '') > -1 &&
    index === 1 &&
    idS.indexOf(nodeID + '') === -1
  return results
}
/**
 * @description 依据节点ID 查询 子集 和 相关 边
 * @param {*} nodeID
 * @param {*} nodes
 * @param {*} edges
 */
export function selectedWorks(nodeID, nodes, edges) {
  let edgesV = []
  let nodesV = []
  edges.map(e => {
    if (+e.source === +nodeID) {
      edgesV.push({ ...e })
    }
  })
  if (edgesV.length > 0) {
    nodes.map(e => {
      if (edgesV.findIndex(x => +x.target === +e.id) > -1) {
        if (noSubsetHandle(+e.id, edges)) {
          nodesV.push({ ...e })
        }
      }
    })
  }
  let edgesVv= []
  edgesV.length && edgesV.map(i => {
    if (nodesV.findIndex(x => +x.id === +i.target) > -1) {
      edgesVv.push({...i})
    }
  })
  let obj = {}
  obj.nodes = nodesV
  obj.edges = edgesVv
  return obj
}
相关推荐
hackeroink40 分钟前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者2 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-3 小时前
验证码机制
前端·后端
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
XH华4 小时前
初识C语言之二维数组(下)
c语言·算法
Data跳动4 小时前
Spark内存都消耗在哪里了?
大数据·分布式·spark
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_5 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
高山我梦口香糖5 小时前
[react]searchParams转普通对象
开发语言·前端·javascript