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
}
相关推荐
AndrewHZ1 小时前
【图像处理基石】什么是油画感?
图像处理·人工智能·算法·图像压缩·视频处理·超分辨率·去噪算法
.格子衫.1 小时前
015枚举之滑动窗口——算法备赛
数据结构·算法
qq_386322692 小时前
华为网路设备学习-21 IGP路由专题-路由过滤(filter-policy)
前端·网络·学习
J先生x2 小时前
【IP101】图像处理进阶:从直方图均衡化到伽马变换,全面掌握图像增强技术
图像处理·人工智能·学习·算法·计算机视觉
山猪打不过家猪3 小时前
(五)毛子整洁架构(分布式日志/Redis缓存/OutBox Pattern)
分布式·缓存
爱coding的橙子4 小时前
每日算法刷题 Day3 5.11:leetcode数组2道题,用时1h(有点慢)
算法·leetcode
蓝婷儿7 小时前
前端面试每日三题 - Day 32
前端·面试·职场和发展
jstart千语7 小时前
【Redis】分布式锁的实现
数据库·redis·分布式
星空寻流年8 小时前
CSS3(BFC)
前端·microsoft·css3
九月TTS8 小时前
开源分享:TTS-Web-Vue系列:Vue3实现固定顶部与吸顶模式组件
前端·vue.js·开源