在D3图表中更新DOM元素后,如何执行追加?

时间:2015-06-27 23:34:13

标签: javascript jquery d3.js

我有一个甘特图,我用D3构建了一个相关的过滤器,用户可以选择最短的时间,最长的时间等。所以当过滤器改变时,xAxis会修改并且一些元素随时间移动。< / p>

A还绘制了一些连接过滤器所选元素的线条。

当在滤镜中进行选择时,我删除线条(通过移除),更改矩形的颜色,并将轴更改为新的时间刻度。但是,当我去绘制新线条时,在更新之前,引用将从旧矩形中拉出。

以下是显示问题的JSFiddle: https://jsfiddle.net/3afumu4d/12/

要查看问题:点击过滤器图标,然后选择&#34;最短时间&#34;,箭头将重绘但位置错误。它是在过渡之前将它们绘制在矩形的位置。

这是我的更新方法。

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));;

}

drawArrows方法是通过甘特图向新突出显示的路径添加箭头的方法。但它没有获得新的价值。

有没有办法在DOM元素更新后触发drawArrows方法?

1 个答案:

答案 0 :(得分:0)

我在另一个Stack Overflow问题中找到了答案。

基本上我需要等待所有“rect”转换完成,因此更新了rect x,y,width值。

我使用了此处的endAll方法:d3.js transition end event