2016-02-14 2 views
2

Я хочу добавить метки к своей вертикальной гистограмме, отображающей текущее процентное значение, соответствующее текущей высоте бара. Поэтому мне нужно постоянно обновлять процентное значение, и мне также нужен переход, чтобы текстовый элемент перемещал insync с помощью гистограммы. Я попытался это:Как я могу динамически обновлять текстовые метки в d3?

var percentageLabels = svg.selectAll(".percentage-label") 
    .data(dataset); 

    percentageLabels.remove(); 

    percentageLabels 
    .enter() 
    .append("text") 
      .attr("class", "percentage-label") 
      .style("fill", "white") 
    .text(function(d) { 
     return d; 
    }) 
    .attr("y", function(d) { 
     return y(d); 
    }) 
    .attr("x", function(d, i) { 
     return i * (w/dataset.length) + 2.5/100 * w + w * 10/100; 
    }) 
    .transition().duration(1750).ease("linear") 
    .attr("y", function(d) { 
        return y(d); 
    }); 

Отъезд fiddle

ответ

2

Я бы сделать пару изменений здесь. Сначала оберните rect и text в g, так что вам потребуется только привязка данных. Затем вы можете перейти их вместе:

var uSel = svg.selectAll(".input") 
    .data(dataset); //<-- selection of gs 

uSel.exit().remove(); //<-- anybody leaving? remove g (both rect and text) 

var gs = uSel 
    .enter() 
    .append("g") 
    .attr("class", "input"); //<-- enter selection, append g 

gs.append("rect") 
    .attr("fill", "rgb(250, 128, 114)"); //<-- enter selection, rect to g 

gs.append("text") 
    .attr("class", "percentage-label") 
    .style("fill", "white") 
    .attr("x", function(d, i) { 
     return i * (w/dataset.length) + 2.5/100 * w + w * 10/100; 
    }); //<-- enter selection, text to g 

uSel.select("rect") 
    .attr("x", function(d, i) { 
     return i * (w/dataset.length) + 2.5/100 * w; 
    }) 
    .attr("width", w/dataset.length - barPadding) 
    .attr("height", y(0)) 
    .transition().duration(1750).ease("linear") 
    .attr("y", function(d) { 
     return y(d); 
    }) 
    .attr("height", function(d) { 
     return h - y(d); 
    }); //<-- update rects with transition 

uSel.select("text") 
      .transition().duration(1750).ease("linear") 
      .attr("y", function(d) { 
        return y(d); 
      }) 
    .text(function(d) { 
     return d + "%"; 
    }); //<-- update text with transition 

Обновлено fiddle.


редактирует

Для перехода текст, вы, вероятно, придется использовать custom tween function:

uSel.select("text") 
    .transition().duration(1750).ease("linear") 
    .attr("y", function(d) { 
     return y(d); //<-- move the text 
    }) 
    .tween("", function(d) { 
     var self = d3.select(this), 
      oldValue = y.invert(self.attr("y")), //<-- get the current value 
      i = d3.interpolateRound(oldValue, d); //<-- interpolate to new value   
     return function(t) { 
     self.text(i(t) + '%') <-- update the text on each iteration 
     }; 
    });  

Обновлено, обновлено fiddle.

+0

Спасибо! Отличное решение! Я гораздо ближе к тому, чего хочу достичь. –

+0

Но я хочу, чтобы метка отображала значение ее текущей высоты. Теперь он показывает значение, на которое он будет переходить. Я бы хотел, чтобы это было как счетчик. Подсчет всех номеров из одной точки перехода в другую. Сожалею. Я не высказал достаточно ясно –

+0

@AndreasDominguez, см. Обновленный ответ. – Mark

0

Из документов:

Метод transition.each можно использовать для цепи переходов и применять общую синхронизацию через множество переходов, , Например:

d3.transition() 
    .duration(750) 
    .ease("linear") 
    .each(function() { 
     d3.selectAll(".foo").transition() 
     .style("opacity", 0) 
     .remove(); 
    }) 
    .transition() 
    .each(function() { 
     d3.selectAll(".bar").transition() 
     .style("opacity", 0) 
     .remove(); 
    }); 
Смежные вопросы