使用d3js将子元素添加到力有向图中的特定节点

Adding child elements to specific nodes in a force-directed graph using d3js


使用d3js将子元素添加到力有向图中的特定节点 已获得1个解决方法 2020-08-18 18:07:56 javascript

我想根据节点类型向节点添加不同的子元素.因此,节点具有称为 type 的属性.所有节点都应由具有从属子元素的 g 元素组成.

我通过使用D3s filter 功能尝试了这个,但我被卡住了,因为我的代码没有每个节点只添加一次子元素,而是多次添加想要的子元素 (与我有节点相同的数量).所以我想我在选择上做错了什么.

我的图的节点和链接会随着时间的推移而变化,所以我所做的是首先存储选择,当一个节点被添加到 self.nodes 时,我调用绘制函数 (我会忽略链接代码).

self.domNodes = this.svg.append('g').attr('class', 'nodes').selectAll('.node')

function draw() {
    self.domNodes = self.domNodes.data(self.nodes, (node) => node.id)
    self.domNodes.exit().remove()

    // all nodes
    self.domNodes.enter()
      .append('g')
      .attr('class', (node) => `node ${node.type}`)
      .merge(self.domNodes)

    // contributions
    self.domNodes.filter((d) => d.type === 'contribution')
      .append('circle')
      .attr('r', 4)
      .attr('fill', 'blue')

    // persons
    self.domNodes.filter((d) => d.type === 'person')
      .append('other elements and attributes...')

    self.simulation.nodes(self.nodes)
    self.simulation.force('link').links(self.links)
    self.simulation.alpha(1).restart()
}

工作原理是,它确实区分 personcontribution ,并添加我想要的元素专门为这种类型,但它不添加只有一个每个 g 节点,但它添加了这些 (节点的数量我拥有) 到每个 g 的倍数节点.如果我继续调用draw函数,它将在我的g元素上附加越来越多的圆圈.

<svg>
    <g>
        <g class="nodes">
            <g class="node contribution" transform="translate(466, 442)">
                <circle r="4" fill="blue"></circle>
                <circle r="4" fill="blue"></circle>
                <circle r="4" fill="blue"></circle>
            </g>
            <g class="node contribution" transform="translate(466, 442)">
                <circle r="4" fill="blue"></circle>
                <circle r="4" fill="blue"></circle>
                <circle r="4" fill="blue"></circle>
            </g>
            <g class="node contribution" transform="translate(466, 442)">
                <circle r="4" fill="blue"></circle>
                <circle r="4" fill="blue"></circle>
                <circle r="4" fill="blue"></circle>
            </g>
            <g class="node person" transform="translate(400, 200)">
                <someotherthings></someotherthings>
                <someotherthings></someotherthings>
            </g>
            <g class="node person" transform="translate(400, 200)">
                <someotherthings></someotherthings>
                <someotherthings></someotherthings>
            </g>
        </g>
    </g>
</svg>

我在这里做错了什么?我只希望 circle 和其他元素每个节点只追加一次.

<svg>
    <g>
        <g class="nodes">
            <g class="node contribution" transform="translate(466, 442)">
                <circle r="4" fill="blue"></circle>
            </g>
            <g class="node contribution" transform="translate(466, 442)">
                <circle r="4" fill="blue"></circle>
            </g>
            <g class="node contribution" transform="translate(466, 442)">
                <circle r="4" fill="blue"></circle>
            </g>
            <g class="node person" transform="translate(400, 200)">
                <someotherthings></someotherthings>
            </g>
            <g class="node person" transform="translate(400, 200)">
                <someotherthings></someotherthings>
            </g>
        </g>
    </g>
</svg>

任何帮助都很感激.


使用d3js将子元素添加到力有向图中的特定节点 方法1

在再次阅读了d3 wiki上的selection.data之后,我终于可以正常工作了.

我事先合并了笔记,因此我的选择包括enter和update节点.我现在做的是首先创建enter节点,然后对它们进行选择和过滤器,然后合并它们.

function draw() {
    self.domNodes = self.domNodes.data(self.nodes, (node) => node.id)
    self.domNodes.exit().remove()

    // all nodes
    const enterNodes = self.domNodes.enter()
      .append('g')
      .attr('class', (node) => `node ${node.type}`)

    // contributions
    enterNodes.filter((d) => d.type === 'contribution')
      .append('circle')
      .attr('r', 4)
      .attr('fill', 'blue')

    // persons
    enterNodes.filter((d) => d.type === 'person')
      .append('other elements and attributes...')

    self.domNodes = self.domNodes.merge(enterNodes)

    self.simulation.nodes(self.nodes)
    self.simulation.force('link').links(self.links)
    self.simulation.alpha(1).restart()
}

.htaccess .net .net-core 2d 3d 3d-printing ab-initio abp abstract-syntax-tree actions-on-google actionscript-3 active-directory activemq activemq-artemis acumatica adobe-xd aframe ag-grid agora.io air airflow ajax akka alert alexa algorithm alignment allure amadeus amazon-cloudformation