#javascript #d3.js
#javascript #d3.js
Вопрос:
Я перейду к делу со скрипкой: http://jsfiddle.net/K6Yrw / [нажмите вторую кнопку, чтобы быстро увидеть эффект]
Я использую selection.order
, потому что мне нужно, чтобы мои элементы DOM существовали в том же порядке, что и элементы данных.
Я хочу добавить переход к моему .exit()
выбору. Однако при объединении с .order()
процесс прерывается. Удаляемый элемент помещается в начало списка элементов DOM.
Мое предположение: возможно, потому order
, что пытается получить индекс элемента в массиве данных — конечно, он больше не существует, и поэтому получает -1
как индекс, что означает, что он должен быть отсортирован до начала списка элементов DOM.
Если я не использую order
, переход выхода работает просто отлично: но если я вставляю что-то частично через массив данных, конечно, новый элемент DOM просто добавляется в конец.
Любые советы или помощь с благодарностью!
Комментарии:
1. Не уверен, правильно ли я понял вопрос. Я получаю один и тот же заказ с и без
selection.order()
. Элементы DOM будут добавлены в том же порядке, что и элементы данных по умолчанию, вам не нужно ничего делать дополнительно, чтобы получить это.2. Lars — они всегда добавляются, никогда не вставляются. Вставка элемента с индексом 3 в данные приведет к тому, что он будет добавлен в конец списка элементов DOM.
order()
это работает, но в случаеexit()
выбора он всегда упорядочивает элементы, относящиеся к удаленным данным, в самом начале списка DOM.3. Все еще не совсем понимаю, к чему вы здесь стремитесь. Возможно, у вас есть более сложный пример, в котором это имеет значение?
4. Скрипка должна показать это — простой список элементов DOM, я хочу, чтобы они сохраняли порядок, который имеют их базовые данные. Я хочу анимировать удаление элемента из этого списка. В то же время вставленный элемент должен появиться в том месте, где он был вставлен. Если это имеет смысл?
5. Ах, теперь я понимаю, что вы имеете в виду — я пропустил бит вставки. В основном вы видите это, потому что используете переход. Что вам нужно сделать, так это упорядочить после завершения перехода удаления. Это относительно просто при использовании
.each("end", ...)
обработчика. Загвоздка в том, что вам также нужно запускать это, когда выбор выхода пуст, что требует отдельной проверки. jsfiddle.net/K6Yrw/47
Ответ №1:
Я считаю, что у меня есть решение. Проблема в том, что d3 в конечном итоге сортирует не только элементы в вашем выборе. Извлеченные элементы больше не являются частью вашего выбора, и d3 непреднамеренно перемещает их. Я изменил существующую функцию порядка d3 так, чтобы она принимала ключевую функцию и пропускала все, чего нет в текущем выборе. Таким образом, удаленные элементы просто остаются на месте. Моей версии нужен ключ, чтобы проверить, находится ли элемент в текущем выборе. Не уверен, есть ли лучший способ справиться с этим или нет.
function strictOrder(fnKey){
fnKey = fnKey || function(d){return d;};
return function(){
for (var j = -1, m = this.length; j < m; ) {
for (var group = this[j], i = group.length - 1, next = group[i], node,seen = new d3.set(); --i >= 0; ) {
node = group[i];
if (!node) continue;
if (next amp;amp; next !== node.nextSibling amp;amp; (!node.nextSibling || seen.has(fnKey(node.nextSibling.__data__)))){
next.parentNode.insertBefore(node, next);
}
seen.add(fnKey(node.__data__));
next = node;
}
}
return this;
};
}
посмотрите на свою раздвоенную скрипку здесь: http://jsfiddle.net/co8nqopy/1 /
Ответ №2:
Может быть, вы можете попробовать просто запустить selection.order только при вставке элементов, а не при удалении элементов.
Итак, чтобы исправить ошибку, вы должны добавить аргумент в метод doD3(), который содержит true / false относительно того, запускать selection.order или нет. Поэтому передавайте true при вставке элементов, чтобы сохранить порядок, и false при удалении элементов.
См. Скрипку: http://jsfiddle.net/K6Yrw/31 /
var items = ['apple', 'banana', 'orange', 'aardvark'];
function doD3(order) {
var selection = d3.select('div.c')
.selectAll('p')
.data(items, function(d) { return d; });
selection
.enter()
.append('p')
.text(function(d) { return d; })
.style('opacity', 0)
.transition()
.style('opacity', 1);
selection
.exit()
.transition()
.style('opacity', 0)
.remove();
if(order) {
// remove this to see alternative behaviour
selection
.order();
}
}
doD3(true);
$('#b1').click(function() {
items.splice(1, 0, ['kiwi']);
doD3(true);
});
$('#b2').click(function() {
items.splice(2, 1);
doD3(false);
});
Комментарии:
1. Интересно, но, конечно, это означает, что я не могу обновить удалить или вставить удалить одновременно. И я не могу удалить, затем вставить или обновить во время выполнения перехода удаления.?