2016-04-04 8 views
0

私はアプリケーションの棒グラフにd3を使用していますが、棒グラフが表すデータ値のテキストで各棒に注釈を付ける必要があります。データに特定のプロパティが存在する場合に条件付きでテキスト要素をレンダリングする

私はこのようにように、これまで取り組んできた:

layers = svg.selectAll('g.layer') 
    .data(stacked, function(d) { 
     return d.dataPointLegend; 
    }) 
    .enter() 
    .append('g') 
    .attr('class', function(d) { 
     return d.dataPointLegend; 
    }); 

layers.selectAll('rect') 
    .data(function(d) { 
     return d.dataPointValues; 
    }) 
    .enter() 
    .append('rect') 
    .attr('x', function(d) { 
     return x(d.pointKey); 
    }) 
    .attr('width', x.rangeBand()) 
    .attr('y', function(d) { 
     return y(d.y0 + d.pointValue); 
    }) 
    .attr('height', function(d) { 
     return height - margin.bottom - margin.top - y(d.pointValue) 
    }); 

layers.selectAll('text') 
    .data(function(d) { 
     return d.dataPointValues; 
    }) 
    .enter() 
    .append('text') 
    .text(function() { 
     return 'bla'; 
    }) 
    .attr('x', function(d) { 
     return x(d.pointKey) + x.rangeBand()/2; 
    }) 
    .attr('y', function(d) { 
     return y(d.y0 + d.pointValue) - 5; 
    }) 

私は実際には、特定のプロパティがデータ内に存在する場合、テキスト要素を追加したいと思います。

私は、文書内の選択方法がdatumであることを見て、これが私の必要なものかどうか疑問に思っています。私が探しているプロパティが存在しない場合、追加呼び出しを取り消す方法がわかりません。

おかげで[OK]を

試み2

だから私はそうのようなeach機能を使用して別の刺し、この時間があった:

layers.selectAll('text') 
    .data(function(d) { 
     return d.dataPointValues; 
    }) 
    .enter() 
    //This line needs to be my each function I think? 
    .append('text') 
    .each(function(d){ 
     if(d.pointLabel) { 
      d3.select(this) 
       .text(function(d) { 
        return d.pointLabel; 
       }) 
       .attr('x', function(d) { 
        return x(d.pointKey) + x.rangeBand()/2; 
       }) 
       .attr('y', function(d) { 
        return y(d.y0 + d.pointValue) - 5; 
       }) 
       .attr('class', 'data-value') 
     } 
    }); 
} 

私が今持っている問題は、私が取得することですpointLabelプロパティが存在するかどうかに関係なく追加されたテキスト要素。

append('text')をそれぞれにダウンロードする必要があるかどうかはわかりませんが、試してみると、d3が特定のコールを期待していないため、エラーが発生します。更新ノードを含むむしろlayers.enter()選択にテキストを追加するよりも....このバインディングD3のデータを使用する方法について

+1

質問に答えを加えるのではなく、あなた自身の質問に本当に答える必要があります。 – thatOneGuy

+0

私は実際に考えたとおりに解決しませんでした。(しかし、私はあなた自身の質問 – mindparse

答えて

1

方法、layers全体の選択に次の操作を行い、すなわち:

labels = layers.selectAll('text') 
    .data(function(d) { 
     // d is the datum of the parent, and for this example 
     // let's assume that the presence of `pointLabel` 
     // indicates whether the label should be displayed or not. 
     // You could work in more refined logic for it if needed: 
     return d.pointLabel ? [d] : []; 
    }) 

// The result of the above is that if a label is needed, a binding will 
// occur to a single element array containing `d`. Otherwise, it'll bind 
// to an empty array. After that binding, using enter, update and exit, 
// you get to add, update or even remove text (you might need removal if 
// you're updating an existing view whose existing label needs to go away) 

labels.enter() 
    .append("text") 

labels 
    .text(function(d) { d.pointLabel }) 
    .attr('x', function(d) { 
    return x(d.pointKey) + x.rangeBand()/2; 
    }) 
    .attr('y', ...) 

labels.exit() 
    .remove() 

ここではトリックはありませんが、これは非常に一般的なd3ユースケースではありません.1つの要素配列[d]にバインドするか、空白の1つを[]にバインドするかのどちらかです。つまり、enter()の選択を使って必要に応じてラベルを貼ります。そして、このアプローチの非データバインディングアプリケーションへの利点は、d.pointLabelが変更されたり、アプリケーションの状態が変更されたり、ラベルの有無(または存在の欠如、すなわち削除)が更新されるたびに、このコードを複数回呼び出すことができることですそれに応じて。

関連する問題