Подтвердить что ты не робот

D3: Как обновить диаграмму новыми данными?

Я создал диаграмму dut dut. Вот мой код:

var width = 480;
var height = 480;
var radius = Math.min(width, height) / 2;
var doughnutWidth = 30;

var color = d3.scale.category10();

var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 70);

var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d[1]; });

var dataset = settings.dataset;
console.log(dataset);

var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) { 
  return color(d.data[0]);
})

У меня есть простая форма на моей веб-странице, которая отображает выпадающее меню с несколькими параметрами. Каждый раз, когда пользователь меняет значение в форме, новый набор данных отправляется на мой script (settings.dataset), и пончик перерисовывается на странице.

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

введите описание изображения здесь

Мой вопрос: как очистить старые значения? Я прочитал .exit() и .remove(), но я не могу обойти эти методы.

4b9b3361

Ответ 1

Создайте одну функцию, которая (re) рисует пирог, когда он создается, и когда он обновляется.

Новые данные должны быть добавлены в pie с использованием enter(), а старые данные должны быть удалены с помощью exit().remove()

Это так просто:

  path.enter().append("path")
            .attr("fill", function(d, i) { return color(i); })
            .attr("d", arc)
            .each(function(d) {this._current = d;} );

  path.transition()
            .attrTween("d", arcTween);

  path.exit().remove()

Полный рабочий код → JSFIDDLE

Ответ 2

Для реализации эффекта "перерисовки" вы хотите выполнить два шага:

Во-первых, я предполагаю, что вы хотите, чтобы svg-холст рисовался только один раз, когда страница загружается впервые, а затем обновляет диаграмму в svg вместо удаления и перерисовки svg:

 var svg = d3.select("body")
              .selectAll("svg")
              .data([settings.dataset]);  
 // put data in an array with only one element

 // this ensures there is only one consistent svg on the page when data is updated(when the script gets executed) 
 svg.enter().append("svg")  

Во-вторых, понимая enter(), exit(), есть много отличных уроков об этом. В вашем случае я бы предложил нарисовать пончик примерно так:

var path = svg.selectAll(".donut")  
           .data(settings.data)

// bind data to elements, now you have elements belong to one of those 
// three 'states', enter, exit, or update

// for `enter` selection, append elements
path.enter().append("path").attr("d", arc).attr("fill", "teal")

// for `update` selection, which means they are already binded with data
path.transition().attrTween("d", someFunction) // apply transition here if you want some animation for data change

// for `exit` selection, they shouldn't be on the svg canvas since there is no corresponding data, you can then remove them
 path.exit().remove()

Ответ 3

//remove and create svg
d3.select("svg").remove(); 
var svg = d3.select("body").append("svg").attr("width","960").attr("height", "600"),
inner = svg.append("g");