2

countオブジェクトとdateオブジェクトを持つオブジェクトの配列があります。それらを使用して、時間スケールで長方形の選択を作成します。よく働く。しかし、jQuery UIのスライダーを使用して、ユーザーが結果を全範囲の一部に絞り込み、より細かい詳細をよりよく表示できるようにしたいと思います。しかし、rect選択からデータポイントを動的に追加および削除する方法を理解できませんでした。これがコードです。問題の部分は、スライダースライドイベントハンドラーの一番下にあります。データを適切に管理する方法について、助けていただければ幸いです。

  var data=env.client.data;
  var selected=env.client.selected;

  var max=_.max(data,function(element){
    return(element.count);
  }).count;

    var height=250;
    var width=960;

    var padding={
      bottom:25,
      left:30,
      right:10,
      top:10
    };

    var barwidth=(width-(padding.left+padding.right))/data.length;

    var chart=d3.select('#chart')
                .html('')
                .append('svg')
                .attr('height',height)
                .attr('width',width);

    var scale={};

    scale.x=d3.time
              .scale
              .utc()
              .domain([d3.first(data).date,d3.last(data).date])
              .range([padding.left,width-padding.right]);

    scale.yy=d3.scale
               .linear()
               .domain([0,max||1])
               .range([height-padding.bottom,padding.top]);

    scale.yh=d3.scale
               .linear()
               .domain([0,max||1])
               .range([0,height-(padding.bottom+padding.top)]);

    var axis={};

    axis.x=d3.svg
             .axis()
             .scale(scale.x)
             .orient('bottom');

    axis.y=d3.svg
             .axis()
             .scale(scale.yy)
             .orient('left')
             .ticks(12);

    if(max<12) axis.y.ticks(max);

    var xa=chart.append('g')
                .attr('class','xAxis')
                .attr('transform','translate(0,'+(height-padding.bottom)+')')
                .call(axis.x);

    var ya=chart.append('g')
                .attr('class','yAxis')
                .attr('transform','translate('+(padding.left)+',0)')
                .call(axis.y);

    var rects=chart.selectAll('rect')
                   .data(data)
                   .enter()
                   .append('rect')
                   .attr('x',function(d){
                     return(scale.x(d.date));
                   })
                   .attr('y',function(d){
                     return(scale.yy(d.count));
                   })
                   .attr('height',function(d){
                     return(scale.yh(d.count));
                   })
                   .attr('fill',function(d){
                     return(d3.hsl(120-(120*(d.count/50)),1,0.1));
                   })
                   .attr('width',barwidth)
                   .attr('title',function(d){
                     return(d.tooltip);
                   })
                   .on('mouseover',function(d){
                     d3.select(this)
                       .attr('fill',d3.hsl(120-(120*(d.count/50)),1,0.5));
                   })
                   .on('mouseout',function(d){
                     d3.select(this)
                       .attr('fill',d3.hsl(120-(120*(d.count/50)),1,0.1));
                   })
                   .on('click',function(d){
                     var selected=moment(d.date.getTime()).utc();
                     env.client.range.selected=selected;
                     $('#client-datetime').val(selected.format('YYYY MMM DD, HH:mm'));
                     _.publish('client date changed');
                   });

    var be=d3.first(data).date.getTime();
    var ee=d3.last(data).date.getTime();

    $('#slider').slider({
      range:true,
      min:be,
      max:ee,
      values:[be,ee],
      slide:function(event,ui){
        var bd=new Date(ui.values[0]);
        var ed=new Date(ui.values[1]);
        var subdata=_.filter(data,function(element){
          return((element.date>=bd)&&(element.date<=ed));
        });
        var barwidth=(width-(padding.left+padding.right))/subdata.length;
        scale.x.domain([bd,ed]);
        xa.call(axis.x);
        rects.data(subdata)
             .remove();
        rects.enter()
             .append('rect')
             .attr('x',function(d){
               return(scale.x(d.date))
             })
             .attr('width',barwidth);
      }
    });
4

1 に答える 1

2

私の知る限り、あなたは正しい方向に進んでいます。

取得しsubdata、それをrectsに適用しました

    rects.data(subdata)
         .remove();// this is wrong!!

なぜ呼び出しているのかわかりませんremove()が、基本的にはサブデータにあるすべてのDOM要素が削除されます。これを取り出す必要があります。

次に、(私はかなり確信しています)rectsを新しいバインディングに再割り当てする必要があります。つまり

    rects = rects.data(subdata);

次に、すべてのenter()'ingrectsを追加します。ただし、一部の設定('y'、'fill'などの属性)が欠落しています。ただし、セットに追加またはセットから削除されなかったすべてのサブデータメンバーも更新する必要があります。したがって、次のようになります。

    rects.enter()
         .append('rect')
         .attr('y',function(d) {
           return(scale.yy(d.count));
         })
         .attr('height',function(d){
           return(scale.yh(d.count));
         })
         .attr('fill',function(d){
           return(d3.hsl(120-(120*(d.count/50)),1,0.1));
         });

    rects// This happens for all updated AND entering rects
         .attr('x',function(d){
           return(scale.x(d.date))
         })
         .attr('width',barwidth);

最後に、サブデータに含まれなくなったものを削除する必要があります。

    rects.exit().remove();

このロジックは、initスクリプトの上位にあるものとよく似ています(initバージョンはenter()'ingセットでのみ動作することを除いて)。したがって、すべてを関数に移動する必要があります。

updateChart(newData) {
    rects = rects.data(subdata);
    rects.enter()
    // etc....

    rects.remove()
}

この関数は、初期化時および新しいサブデータが適用されているときに呼び出します。

于 2012-11-01T18:23:54.667 に答える