为什么我的圆节点在 d3 力定向图中无法正确绘制?

问题描述 投票:0回答:1

我不确定为什么我的圆形节点在这种情况下没有绘制。我的目标是根据节点数据 (d) 对为每个节点创建的元素进行微调控制。我并不总是想要圆圈。

看看这段代码生成的内容,我发现:

圆被添加到 svg 中,并具有半径和填充颜色。然而,它们没有被绘制。

但是,如果我这样做:

    const node = svg
      .append('g')
      .attr('stroke', '#fff')
      .attr('stroke-width', 1.5)
      .selectAll()
      .data(nodes)
      .join((enter) => enter.append('circle'))
      .attr('r', 16)
      .attr('fill', (d) => color(d.group))

我明白了:

svg 代码是相同的。我确实看到每个圆形元素都有一个

circle[Attributes Style]
。但是,我不确定为什么在第二种情况下会出现这种情况,而在第一种情况下却不会。

如何使用函数根据节点数据创建不同的节点元素?我的代码需要如何更改,以便在仍然使用传递给

enter.append
的函数的同时绘制圆圈,以便我可以返回任意元素?

    const width = 1000
    const height = 400

    const node_data = Array.from({ length: 5 }, () => ({
      group: Math.floor(Math.random() * 3),
    }))

    const edge_data = Array.from({ length: 10 }, () => ({
      source: Math.floor(Math.random() * 5),
      target: Math.floor(Math.random() * 5),
      value: Math.floor(Math.random() * 10) + 1,
    }))

    const links = edge_data.map((d) => ({ ...d }))
    const nodes = node_data.map((d, index) => ({ id: index, ...d }))
    
    const color = d3.scaleOrdinal(d3.schemeCategory10)

    const svg = d3.select('#chart')

    const simulation = d3
      .forceSimulation(nodes)
      .force(
        'link',
        d3
          .forceLink(links)
          .id((d) => d.id)
          .distance((d) => 100)
      )
      .force('charge', d3.forceManyBody())
      .force('center', d3.forceCenter(width / 2, height / 2))
      .on('tick', ticked)

    const link = svg
      .append('g')
      .attr('stroke', '#999')
      .attr('stroke-opacity', 0.6)
      .selectAll()
      .data(links)
      .join('line')
      .attr('stroke-width', (d) => Math.sqrt(d.value))

    const node = svg
      .append('g')
      .attr('stroke', '#fff')
      .attr('stroke-width', 1.5)
      .selectAll()
      .data(nodes)
      .join((enter) =>
        enter.append((d) => {
          return document.createElement('circle')
        })
      )
      .attr('r', 16)
      .attr('fill', (d) => color(d.group))      

    node.append('title').text((d) => `hello ${d.id}`)

    function ticked() {
      link
        .attr('x1', (d) => d.source.x)
        .attr('y1', (d) => d.source.y)
        .attr('x2', (d) => d.target.x)
        .attr('y2', (d) => d.target.y)

      node.attr('cx', (d) => d.x).attr('cy', (d) => d.y)
    }
    .graph {
      width: 1000px;
      height: 400px;
    }
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script>
<svg ref="chart" id="chart" class="graph"></svg>

javascript d3.js d3-force-directed
1个回答
0
投票

请更新代码

.join(enter => { const elementType = d => document.createElementNS('http://www.w3.org/2000/svg', 'circle'); return enter.append(elementType); })

    const width = 1000
    const height = 400

    const node_data = Array.from({ length: 5 }, () => ({
      group: Math.floor(Math.random() * 3),
    }))

    const edge_data = Array.from({ length: 10 }, () => ({
      source: Math.floor(Math.random() * 5),
      target: Math.floor(Math.random() * 5),
      value: Math.floor(Math.random() * 10) + 1,
    }))

    const links = edge_data.map((d) => ({ ...d }))
    const nodes = node_data.map((d, index) => ({ id: index, ...d }))
    
    const color = d3.scaleOrdinal(d3.schemeCategory10)

    const svg = d3.select('#chart')

    const simulation = d3
      .forceSimulation(nodes)
      .force(
        'link',
        d3
          .forceLink(links)
          .id((d) => d.id)
          .distance((d) => 100)
      )
      .force('charge', d3.forceManyBody())
      .force('center', d3.forceCenter(width / 2, height / 2))
      .on('tick', ticked)

    const link = svg
      .append('g')
      .attr('stroke', '#999')
      .attr('stroke-opacity', 0.6)
      .selectAll()
      .data(links)
      .join('line')
      .attr('stroke-width', (d) => Math.sqrt(d.value))

    const node = svg
      .append('g')
      .attr('stroke', '#fff')
      .attr('stroke-width', 1.5)
      .selectAll()
      .data(nodes)
       .join(enter => {
    const elementType = d => document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    return enter.append(elementType);
  })
      .attr('r', 16)
      .attr('fill', (d) => color(d.group))      

    node.append('title').text((d) => `hello ${d.id}`)

    function ticked() {
      link
        .attr('x1', (d) => d.source.x)
        .attr('y1', (d) => d.source.y)
        .attr('x2', (d) => d.target.x)
        .attr('y2', (d) => d.target.y)

      node.attr('cx', (d) => d.x).attr('cy', (d) => d.y)
    }
.graph {
      width: 1000px;
      height: 400px;
    }
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script>
<svg ref="chart" id="chart" class="graph"></svg>

© www.soinside.com 2019 - 2024. All rights reserved.