2

我有一个包含计数和日期对象的对象数组。使用它们在时间尺度上创建选择的矩形。效果很好。但我想使用 jQuery UI 中的滑块来允许用户将结果缩小到整个范围的一部分,并更好地查看更精细的细节。但是我无法弄清楚如何从我的矩形选择中动态添加和删除数据点。这是代码。有问题的部分位于滑块滑动事件处理程序的最底部。我非常感谢有关如何正确管理数据的任何帮助。

  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 元素。这应该被取出。

接下来,(我很确定)您需要将矩形重新分配给新绑定。IE

    rects = rects.data(subdata);

接下来,您附加所有enter()'ing rects。但是您缺少一些设置(“y”、“填充”等属性)。但是您还需要更新集合中未添加或删除的所有子数据成员。所以它变成:

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