使用Javascript D3库,如何在选择矩形时替换数据?
我有一个包含count和date对象的对象数组。使用它们在时间刻度上创建矩形的选择。效果很好。但是我想使用jQueryUI中的滑块,允许用户将结果缩小到整个范围的一部分,并更好地查看更精细的细节。但我还没有弄清楚如何从我的rect选择中动态添加和删除数据点。这是代码。所讨论的部分位于滑块事件处理程序的最底部。如果您能为我提供有关如何正确管理数据的帮助,我将不胜感激使用Javascript D3库,如何在选择矩形时替换数据?,javascript,svg,d3.js,Javascript,Svg,D3.js,我有一个包含count和date对象的对象数组。使用它们在时间刻度上创建矩形的选择。效果很好。但是我想使用jQueryUI中的滑块,允许用户将结果缩小到整个范围的一部分,并更好地查看更精细的细节。但我还没有弄清楚如何从我的rect选择中动态添加和删除数据点。这是代码。所讨论的部分位于滑块事件处理程序的最底部。如果您能为我提供有关如何正确管理数据的帮助,我将不胜感激 var data=env.client.data; var selected=env.client.selected;
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);
}
});
据我所知,你走的是对的 您获得了子数据,然后将其应用于RECT
rects.data(subdata)
.remove();// this is wrong!!
我不知道为什么要调用remove,但这实际上是删除子数据中的所有DOM元素。这个应该拿出来
接下来,我非常确定您需要将rect重新分配给新绑定。即
rects = rects.data(subdata);
在下一步中,附加所有回车矩形。但是您缺少一些设置“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()
}
并在初始时间和应用新子数据时调用此函数。Hello。谢谢那确实有效。但我找到了一个更好的方法。对于我的特定用途,我实际上不需要添加或删除任何数据。取而代之的是,我可以重新缩放x轴,这会让东西从侧面脱落,但也可以使用剪辑路径。工作快得多。但再次感谢你。你的回答有助于我更好地理解发生了什么。是的,剪裁而不是重新绑定数据更有意义。