我正在尝试制作一个动画,显示来自十个不同点的数据。对图形进行编码,使得传感器(通过圆圈显示)根据一小时内获得的总体数据(总条目数和平均速度)改变其颜色和大小。
通过此条目(Transition not working d3)和此模拟Gapminder(https://bost.ocks.org/mike/nations/)的代码,我能够为图表设置动画。但是,由于代码的结构,退出和更新功能不起作用。第1小时数据中的第一个条目只有一个对象,因此只绘制一个圆。此圆圈随时间更新,但未绘制其他传感器(因此未更新)。
我正在考虑为每个传感器重新创建第一个空对象,以便在动画开始时绘制它们。但是,我想避免这种情况。
代码是这样的:
//FUNCTION TO GET THE DATA BY HOUR
function getDataByHour (hour) {
var allBridges = new Array();
var found;
for (b = 0; b < boatsByHour.length; b++){
bridges.forEach(function(br,i){
if (boatsByHour[b].sensorID== br.id){
xy = projection([br.longitude, br.latitude])}
});
if (boatsByHour[b].hour == hour){
found = true;
bridgeNumber = boatsByHour[b].sensorID;
allBridges.push({
"numberBoats": (boatsByHour[b].numberBoats),
"speed": (boatsByHour[b].speedAvg),
"bridge": boatsByHour[b].sensorID,
"longitude": xy[0],
"latitude": xy[1],
"hour": boatsByHour[b].hour
})
}
}
return allBridges;
}
//SENSORS
var sensor = plot.append("g")
.attr("class","bridges")
.selectAll(".sensors")
.data(getDataByHour(timeRange[0]))
.call(animateSensors)
.enter()
.append("circle")
.attr("class","sensors")
.attr("cx", function(d,i){return d.longitude})
.attr("cy", function(d,i){return d.latitude})
.on("mouseover",function(d){console.log(d)});
sensor.exit().remove();
plot
.transition()
.duration(300000)
.ease(d3.easeLinear)
.tween("hour", tweenHour)
//FUNCTION THAT UPDATES THE ANIMATION
function animateSensors (sensor){
sensor
.attr("r",function(d){return radiusScale(d.numberBoats)})
.style("fill",function(d){return colorScale(d.speed)});
}
function tweenHour(){
var hour = d3.interpolateNumber (timeRange[0],timeRange[1]);
return function(h){
displayHour(hour(h))}
}
function displayHour(hour) {
sensor.data(getDataByHour(Math.floor(hour))).call(animateSensors);
}
我尝试了不同的方法来包含enter()和exit()。如果我添加enter()并在'animateSensors'函数中附加圆圈,则绘制所有圆(传感器)。但是它们没有被更新,所以最后,即使exit()。remove()更新在其中,我也会在SVG中绘制数千个圆圈。
由于
答案 0 :(得分:0)
好的,现在可以了。我不得不调用数据的第一部分(其中只绘制了1个圆而不是总数10),而是必须调用包含所有圆的数据的数据(如最后一点):
var sensor = plot.append("g")
.attr("class","bridges")
.selectAll(".bridge")
.data(getDataByHour(timeRange[1])) // instead of getDataByHour(timeRange[0])
.enter()
.append("circle")
.attr("class",function(d){return "bridge " + d.bridge})
.attr("cx", function(d,i){return d.longitude})
.attr("cy", function(d,i){return d.latitude})
.on("mouseover",function(d){console.log(d)});
由于函数tweenHour
,动画正确启动function tweenHour(){
var hour = d3.interpolateNumber (timeRange[0],timeRange[1]);
return function(h){
displayHour(hour(h))}
}