2015-06-27 3 views
0

У меня есть диаграмма Ганта, которую я построил с D3, у которой есть связанный фильтр, где пользователь может выбрать самое короткое время, самое длинное время и т. Д. Поэтому, когда фильтр меняет изменения xAxis, а некоторые элементы меняются со временем.Как выполнить добавление после обновления элементов DOM в диаграмме D3?

A также нарисовали несколько линий, соединяющих элементы, выбранные фильтром.

Когда в фильтре сделан выбор, я удаляю строки (через удаление), меняю цвет прямоугольников и меняю ось на новую шкалу времени. Однако, когда я собираюсь рисовать новые строки, ссылки вытягиваются из старых прямоугольников до обновления.

Вот JSFiddle показывая вопрос:https://jsfiddle.net/3afumu4d/12/

Чтобы увидеть проблему: щелкните значок фильтра, а затем выберите «кратчайшее время», стрелки будут перерисовывать, но в неправильном месте. Он рисует их в месте расположения прямоугольников перед переходом.

Вот мой метод обновления.

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 - это то, что добавляет стрелки к вновь выделенному пути через диаграмму Ганта. Но он не получает новых ценностей.

Есть ли способ запустить метод drawArrows после обновления элементов DOM?

+0

я не уверен, что ваш вопрос - не могли бы вы поставить что-то на jsfiddle или аналогичный, который демонстрирует проблему, пожалуйста? –

+0

Я сделал jsfiddle моего графика ... извините за сложность, но это то, с чем я работаю. Фактический javascript начинается с 1167. Чтобы увидеть проблему, нажмите фильтр и выберите «Самое короткое время». Стрелки, которые рисуются, находятся в позиции прямоугольников до переходов. Извините, я новичок в D3. https://jsfiddle.net/3afumu4d/12/ – Setix

+0

Попытка ввести функции непосредственно в приложение 1000 строк + без тестирования его в изоляции сначала почти так же сумасшедшая, как ожидать, что кто-то замерзнет и исправит это для вас. Разве вы не думаете, что было бы разумнее изолировать функцию, которую вы пытаетесь реализовать, и заставить ее работать, прежде чем интегрировать ее? –

ответ

0

Я нашел ответ в другом вопросе переполнения стека.

По существу мне нужно было дождаться завершения всех «прямых» переходов, поэтому значения rect x, y, width были обновлены.

Я использовал метод подход endAll найти здесь: d3.js transition end event

Смежные вопросы