[英]How do I perform append after DOM elements updatein a D3 chart?
I have a Gantt chart that I built with D3 that has an associated filter where a user can select the shortest time, longest time, etc. So when the filter changes the xAxis modifies and some of the elements shift with time. 我有一个用D3构建的甘特图,该图具有关联的过滤器,用户可以在其中选择最短时间,最长时间等。因此,当过滤器更改时,xAxis会修改,并且某些元素会随时间移动。
A have also drawn some lines connecting the elements selected by the filter. A还绘制了一些连接过滤器所选元素的线。
When a selection is made in the filter, I remove the lines (via remove), change the color of the rectangles, and change the axis to the new timescale. 当在过滤器中进行选择时,我删除了这些线(通过删除),更改了矩形的颜色,并将轴更改为新的时间刻度。 However when i go to draw new lines, the references are being pulled from the old rectangles, prior to updating.
但是,当我去画新线时,在更新之前,参考是从旧矩形中拉出来的。
Here is the JSFiddle showing the issue: https://jsfiddle.net/3afumu4d/12/ 这是显示问题的JSFiddle: https ://jsfiddle.net/3afumu4d/12/
To see issue: click the filter icon, then select "Shortest Time", the arrows will redraw but in the wrong location. 要查看问题,请执行以下操作:单击过滤器图标,然后选择“最短时间”,箭头将重绘,但位置错误。 It is drawing them in the location of rectangles prior to transition.
它在过渡之前将它们绘制在矩形的位置。
Here is my update method. 这是我的更新方法。
function updateData(){
//remove the lines
d3.select("#barsGroup").selectAll('line').remove();
//remove the arrows
d3.select("#barsGroup").selectAll('polyline').remove();
//based on selection, calculate start and end times
var checked = $('input[type=radio][name=timeline]:checked').attr('id');
taskArray.forEach(function(entry){
//if it is selected calculate its new start time.
if(illuminate(entry,checked)){
var newVal = root.startYear + getDelay(entry, checked);
entry.startTime = newVal.toString();
entry.endTime = (newVal + entry.time).toString();
}
});
var minX = d3.min(taskArray, function(d) {return dateFormat.parse(d.startTime);});
var maxX = d3.max(taskArray, function(d) {return dateFormat.parse(d.endTime);});
timeScale = d3.time.scale().domain([minX,maxX]).range([0,w-150]);
//update the boxes
var chart = d3.select("#innercontainer").transition();
//get all the rectangles, update all the rectangles
var updateBoxes = d3.select("#barsGroup").selectAll('rect')
.data(taskArray)
.transition()
.attr("x", function(d){return timeScale(dateFormat.parse(d.startTime)) + sidePadding;})
.attr("y", function(d, i){return i*gap + topPadding;})
.attr("width", function(d){return (timeScale(dateFormat.parse(d.endTime))-timeScale(dateFormat.parse(d.startTime)))})
.attr("fill", function(d){
for (var i = 0; i < categories.length; i++){
if (d.component == categories[i]){
//if true matches selection in filter
var checked = $('input[type=radio][name=timeline]:checked').attr('id');
if(illuminate(d,checked)){
return d3.rgb(colorScale(i));
}else{
return d3.rgb(colorScale(i)).darker(5);
}
//else show darker
}
}
})
.attr("opacity", function(d){
for (var i = 0; i < categories.length; i++){
if (d.component == categories[i]){
//if true matches selection in filter
var checked = $('input[type=radio][name=timeline]:checked').attr('id');
if(illuminate(d,checked)){
return 1.0;
}else{
return 0.4;
}
//else show darker
}
}
});
//Update the text boxes
var textlist = d3.select("#barsGroup").selectAll('text')
.data(taskArray)
.transition()
.attr("x", function(d){
return (timeScale(dateFormat.parse(d.endTime))-timeScale(dateFormat.parse(d.startTime)))/2 + timeScale(dateFormat.parse(d.startTime)) + sidePadding;
})
.attr("y", function(d, i){
return i*gap + 8+ topPadding;
})
.attr("fill", function(d){
for (var i = 0; i < categories.length; i++){
if (d.component == categories[i]){
//if true matches selection in filter
var checked = $('input[type=radio][name=timeline]:checked').attr('id');
if(illuminate(d,checked)){
return "#fff";
}else{
return "#3f3f3f";
}
}
}
}
);
//update grid lines
//scale the axis
xAxis = d3.svg.axis()
.scale(timeScale)
.orient('bottom')
.ticks(d3.time.year, 5) //TODO: change to years (skip every ten?)
.tickSize(-h+topPadding+20, 0, 0)
.tickFormat(d3.time.format('%Y'))
d3.select(".grid")
.transition()
.duration(750)
.call(xAxis)
.selectAll("text")
.style("text-anchor", "middle")
.attr("fill", "#fff")
.attr("stroke", "none")
.attr("font-size", 10)
.attr("dy", "1em")
.each("end",drawArrows(taskArray,checked));;
}
The drawArrows method is what adds arrows to the newly highlighted path through the Gantt Chart. drawArrows方法是通过甘特图向新突出显示的路径添加箭头的方法。 But its not getting new values.
但是它并没有获得新的价值。
Is there any way I can fire the drawArrows method after the DOM elements have updated? 在DOM元素更新后,有什么方法可以触发drawArrows方法?
I found the answer in another Stack Overflow question. 我在另一个堆栈溢出问题中找到了答案。
Essentially I needed to wait for all "rect" transitions to complete, so the rect x,y, width values were updated. 本质上,我需要等待所有“矩形”转换完成,因此更新了矩形x,y,width值。
I used the endAll method approach found here: d3.js transition end event 我使用了在这里找到的endAll方法: d3.js过渡结束事件
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.