2017-12-07 20 views
6

ノードの種類に応じて異なる子要素を自分のノードに追加したいと思います。したがって、ノードにはtypeという属性があります。すべてのノードは、子要素が従属する要素gで構成されていなければなりません。d3jsを使用して強制的なグラフの特定のノードに子要素を追加する

私はD3s filter機能を使用してこれを試しましたが、私のコードはノードごとに1回しか子要素を追加しませんが、必要な子要素を複数回(ノードがあるのと同じ量)追加します。だから私は選択と何か間違っていると思う。

私のグラフのノードとリンクは時間とともに変化するので、最初に選択を保存し、ノードがself.nodesに追加されると、私は描画関数を呼び出します(リンクコードは除外します)。

何に動作することが personcontributionを区別し、私はこのタイプのために特別にしたい要素を追加しないこと、である
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() 
} 

が、それはgノードごとに1つだけを追加しませんが、それは(それらの複数を追加します私が持っているノードの数)をすべてのgノードに追加します。描画関数を呼び出すと、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と他の要素が1ノードにつき1回しか追加されないようにしたい。

<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> 

何か助けていただければ幸いです。

+0

あなたの特定の問題にされない直接の回答がありますが、見てきました(/ Q/39278704)? – altocumulus

+0

質問を投稿してください。それがうまくいかなければ、フィドラー/プランカーに複製された問題へのリンクで私を助けてください。 –

+0

'draw()'を初めて呼び出すときに、複数の子ノードが表示されるのですか?またはノードを複数回呼び出す必要がありますか? –

答えて

2

d3 wikiでselection.dataをもう一度読み終えたら、ついにそれが機能しました。

私のメモはあらかじめマージされていますので、私の選択には入力ノードと更新ノードが含まれていました。私が今行ったことは、最初に入力ノードを作成してから選択とフィルタを行い、後でそれらをマージすることでした。 [「データに基づいて、異なるタイプのSVG要素を作成する方法は?」* *]

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() 
} 
関連する問題