Ответ 1
Мощно (но раздражающе) D3.js иногда заставляет вас повторять себя для простых визуализаций. Если вы сообщите ему, что хотите создать элемент с атрибутами, полученными из данных определенным образом, а затем вы хотите перевести эти атрибуты на новые данные, вы должны снова рассказать о том, как получить значения (в случае, если вы захотите делать что-то другое, например, различную визуальную компоновку). Как говорит @Andrew, вы должны сказать, что делать, когда он переходит.
Вы можете обойти эту "проблему", следуя этой схеме:
var foo = d3.select('foo');
function redraw(someArray){
var items = foo.selectAll('bar').data(someArray);
items.enter().append('bar');
items.exit().remove();
items
.attr('foo',function(d){ return d });
}
В 2.0, когда вы append()
новые элементы в enter()
, они автоматически добавляются к исходному привязке с привязкой к данным, поэтому вызовы на attr()
и то, что позже будут применяться к ним. Это позволяет использовать один и тот же код для установки начальных значений и обновления значений.
Поскольку вы не хотите повторно создавать оболочку SVG для каждого обновления, вы должны создать это за пределами функции redraw
.
Если вы хотите выполнить переходы:
function redraw(someArray){
var items = foo.selectAll('bar').data(someArray);
items.enter().append('bar')
.attr('opacity',0)
.attr('foo',initialPreAnimationValue);
items.exit().transition().duration(500)
.attr('opacity',0)
.remove();
items.transition.duration(500)
.attr('opacity',1)
.attr('foo',function(d){ return d });
}
Обратите внимание, что указанное выше связывает объекты с данными по индексу. Если вы хотите, чтобы промежуточная точка данных удаляла эту точку данных перед ее удалением (вместо удаления последнего элемента и преобразования каждого другого элемента, чтобы он выглядел как этот), вы должны указать уникальное (неиндексное) строковое значение для связывания каждый элемент:
var data = [
{id:1, c:'red', x:150},
{id:3, c:'#3cf', x:127},
{id:2, c:'green', x:240},
{id:4, c:'red', x:340}
];
myItems.data(data,function(d){ return d.id; });
Вы можете увидеть пример этого и сыграть с ним в прямом эфире на моей игровой площадке D3.js.
Во-первых, посмотрите, что произойдет, когда вы закомментируете одну из строк данных, а затем верните ее снова. Затем удалите параметр ƒ('id')
из вызова data()
в строке 4 и снова попробуйте комментировать и в строках данных.
Изменить. В качестве альтернативы, прокомментированный прославленным mbostock, вы можете использовать selection.call()
вместе с функцией многократного использования в качестве способа DRY для вашего кода:
var foo = d3.select('foo');
function redraw(someArray){
var items = foo.selectAll('bar').data(someArray);
items.enter().append('bar').call(setEmAll);
items.exit().remove();
items.call(setEmAll);
}
function setEmAll(myItems){
myItems
.attr('foo',function(d){ return d*2 })
.attr('bar',function(d){ return Math.sqrt(d)+17 });
}
Как показано выше, .call()
вызывает функцию и проходит по выбору в качестве аргумента, так что вы можете выполнить ту же настройку в своем выборе в нескольких местах.