Сохранение порядка элементов (selection.order) с переходами выхода в d3

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