最後にenter()と書いたときにのみグラフが更新される

2020-08-02 javascript d3.js data-visualization

私は使用してデータを切り替えようとしました d3.intervalとデータを棒グラフとしてsvgにレンダリングします。

以下のように。

間隔 -

d3.interval(function(){update(data);
                       flag =! flag;
                      },1000)  

レンダリング -

function update(input){
    
    var value = flag ? 'revenue':'profit'


    x.domain(input.map(function(d){return d.month}));
    y.domain([0,d3.max(input, function(d){return d[value]})])

    var xAxisCall = d3.axisBottom(x);
    var yAxisCall = d3.axisLeft(y).tickFormat(function(d){return '$'+d})
    
    xAxisGroup.call(xAxisCall.tickSizeOuter(0))
    yAxisGroup.call(yAxisCall.tickSizeOuter(0))

    var rects = svg.selectAll('rect').data(data)

    rects.exit().remove()


    
    rects.enter().append('rect').attr('y', (d)=>{return height-y.range([0,height])(d[value])})
                 .attr('x', (d)=>{ return 50+x(d.month)})
                 .attr('height',(d)=>{return y(d[value])})
                 .attr('width',x.bandwidth())
                 .attr('fill','grey')
                 
    }

しかしながら、 長方形に入力されたデータに応じてグラフを切り替えることはありません。 以下のように、長方形のレンダリングの最後に.append()を配置したときにのみ機能しました。

rects.attr('y', (d)=>{return height-y.range([0,height])(d[value])})
             .attr('x', (d)=>{ return 50+x(d.month)})
             .attr('height',(d)=>{return y(d[value])})
             .attr('width',x.bandwidth())
             .attr('fill','grey')
             .enter().append('rect')

最後にエンターとアペンドを追加する必要があるのはなぜですか? これが得られない理由は 最初に.enter()。append( 'rect')を置いても、 rectのプロパティは再定義および更新できます。

ただし、事前にenter()引数を指定すると、長方形のプロパティは更新されませんでした。

以下のように「console.log」を追加してテストしました。

rects.enter().append('rect').attr('fill',function(){return flag? "rgba(100,0,0,0.2)":'rgba(0,100,0,0.2)'}).attr('y', (d)=>{return height-y.range([0,height])(d[value])})
             .attr('x', (d)=>{ return 50+x(d.month)})
             .attr('height',(d)=>{console.log(d[value])
                                  ;return y(d[value])})
             .attr('width',x.bandwidth())

それは何も記録しません、私が最後にエンターを入れたときだけ記録します。

なぜすべての引数が実行されないのですか?

Answers

最初のケースでは、 入力の選択がありますが、更新の選択を変更するものはありません。 2番目のケースでは、入力の選択に対して何もしないで更新の選択を変更します。

更新を書き込んで、選択内容を明確かつ個別に入力してください。これは通常、コードの重複につながります...これらの重複が気に入らない場合は、 merge()使用merge()ください:

var rects = svg.selectAll('rect').data(data)

rects.exit().remove()

rects = rects.enter()
  .append('rect')
  .attr('fill', 'grey')
  .merge(rects)
  .attr('y', (d) => {
    return height - y.range([0, height])(d[value])
  })
  .attr('x', (d) => {
    return 50 + x(d.month)
  })
  .attr('height', (d) => {
    return y(d[value])
  })
  .attr('width', x.bandwidth())

D3は要素に直接作用しないデータ結合を使用しますが、それらの変換を記述します。あなたがするとき:

var rects = svg.selectAll('rect').data(data)

すべての長方形を選択するのではなく、「更新」選択の長方形のみを選択します。 D3の作者による詳細な説明を次に示します。

今日では、 selection.join()ベースのコードをより明確にするselection.join selection.join()メソッドを使用することをお勧めします。

svg.selectAll('rect')
  .data(data)
  .join(
    enter => enter.append('rect')
      .attr('fill', 'grey'),
    update => update
      .attr('x', (d) => 50 + x(d.month))
      .attr('y', (d) => height-y.range([0,height])(d[value]))
      .attr('width', x.bandwidth())
      .attr('height', (d) => y(d[value])),
    exit => exit.remove()
   )

Related