Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Overlapping nodes after collapse issue - Indent tree layout does not recalculate node spacing correctly after collapse/expand operation #6751

Open
2 of 10 tasks
TifaXu131 opened this issue Feb 6, 2025 · 2 comments
Labels
bug 🐛 Something isn't working

Comments

@TifaXu131
Copy link

Describe the bug / 问题描述

在使用 G6 紧凑树(indent)布局时,当执行节点折叠操作后,部分节点出现重叠现象,有时候会前后电脑

重现步骤:
点击折叠

G6 版本:5.0.42

Image

<template>
  <div id="container"></div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue'
import { Rect as GRect, Text as GText } from '@antv/g'
import { Graph, GraphEvent, register, treeToGraphData, Badge, CommonEvent, ExtensionCategory } from '@antv/g6'
import { getTaskRelationTree } from '@/service/apis/task'

// 自定义节点:只保留 label 和折叠按钮逻辑
class TreeNode extends GRect {
  // 获取 label 样式
  getLabelStyle(attributes) {
    const [width, height] = this.getSize(attributes)
    return {
      name: 'label',
      x: -width / 2 + 8,
      y: -height / 2 + 50,
      text: this.data?.label,
      fontSize: 12,
      fill: '#000',
      cursor: 'pointer'
    }
  }
  // 绘制 label
  drawLabelShape(attributes, container) {
    const labelStyle = this.getLabelStyle(attributes)
    const label = this.upsert('label', GText, labelStyle, container)
    if (label && !Reflect.has(label, '__bind__')) {
      Reflect.set(label, '__bind__', true)
      label.addEventListener(CommonEvent.CLICK, () => {
        // 点击 label 可执行跳转或其他操作
      })
    }
  }
  // 获取折叠按钮样式
  getCollapseStyle(attributes) {
    if (this.childrenData.length === 0) return false
    const { collapsed } = attributes
    const [width] = this.getSize(attributes)
    return {
      fill: '#D2D6DA',
      fontSize: 16,
      text: collapsed ? '+' : '-',
      x: width / 2,
      y: 0,
      cursor: 'pointer'
    }
  }
  // 绘制折叠按钮
  drawCollapseShape(attributes, container) {
    const collapseStyle = this.getCollapseStyle(attributes)
    const btn = this.upsert('collapse', Badge, collapseStyle, container)
    if (btn && !Reflect.has(btn, '__bind__')) {
      Reflect.set(btn, '__bind__', true)
      btn.addEventListener(CommonEvent.CLICK, () => {
        try {
          const { collapsed } = this.attributes
          const graph = this.context.graph
          if (collapsed) graph.expandElement(this.id)
          else graph.collapseElement(this.id)
        } catch (error) {
          console.error(error)
        }
      })
    }
  }
  // 重写 render,仅绘制 label 和折叠按钮
  render(attributes = this.parsedAttributes, container) {
    super.render(attributes, container)
    this.drawCollapseShape(attributes, container)
    this.drawLabelShape(attributes, container)
  }
}
register(ExtensionCategory.NODE, 'tree-node', TreeNode)

let graph
let mindMapData = []

const getData = async () => {
  // 此处替换为实际任务编码
  const data = await getTaskRelationTree('some-task-code')
  mindMapData = data
}

onMounted(async () => {
  await getData()

  graph = new Graph({
    container: 'container',
    data: treeToGraphData(mindMapData, {
      getNodeData: (datum) => {
        const nodeData = {
          ...datum,
          id: datum.nodeId,
          label: datum.name,
          style: { collapsed: false }
        }
        if (datum.children && datum.children.length) {
          nodeData.children = datum.children.map(child => child.nodeId)
        }
        return nodeData
      },
      getId: (d) => d.nodeId,
      getEdgeData: (source, target) => ({
        id: `${source.nodeId}-${target.nodeId}`,
        source: source.nodeId,
        target: target.nodeId
      })
    }),
    node: {
      type: 'tree-node',
      style: {
        size: [260, 80],
        radius: 4
      }
    },
    edge: {
      type: 'cubic-horizontal',
      style: {
        stroke: '#D2D6DA',
        lineWidth: 1,
        controlPoints: true
      }
    },
    layout: {
      type: 'indented',
      direction: 'LR',
      dropCap: false,
      indent: 340,
      controlPoints: true,
      getHeight: () => 60,
      nodesep: 40,
      ranksep: 120,
      preLayout: false
    },
    behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element']
  })

  graph.render()
  graph.once(GraphEvent.AFTER_RENDER, () => {
    graph.fitCenter()
  })
})

onUnmounted(() => {
  if (graph) graph.destroy()
  mindMapData = null
  graph = null
})
</script>

<style scoped>
#container {
  position: relative;
  height: 100%;
}
</style>

Reproduction link / 复现链接

No response

Steps to Reproduce the Bug or Issue / 重现步骤

点击折叠

G6 Version / G6 版本

Please select / 请选择

OS / 操作系统

  • macOS
  • Windows
  • Linux
  • Others / 其他

Browser / 浏览器

  • Chrome
  • Edge
  • Firefox
  • Safari (Limited support / 有限支持)
  • IE (Nonsupport / 不支持)
  • Others / 其他
@TifaXu131 TifaXu131 added the waiting for maintainer Triage or intervention needed from a maintainer. label Feb 6, 2025
@github-actions github-actions bot changed the title [Bug]: 节点折叠后重叠问题 — 缩进树布局在折叠/展开操作后节点间距未正确重新计算 [Bug]: Overlapping nodes after collapse issue - Indent tree layout does not recalculate node spacing correctly after collapse/expand operation Feb 6, 2025
@TifaXu131
Copy link
Author

TifaXu131 commented Feb 6, 2025

可以复现的代码链接 点第二个元素折叠 就会出现元素重叠 https://stackblitz.com/edit/react-2lkvgqmu?file=index.js

@TifaXu131
Copy link
Author

bug现象录屏
https://github.com/user-attachments/assets/0ab58edd-1908-4131-b61d-b00bf487e574

@zhongyunWan zhongyunWan added bug 🐛 Something isn't working and removed waiting for maintainer Triage or intervention needed from a maintainer. labels Mar 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants