保持元素顺序(selection.order)与d3中的退出转换

时间:2014-06-25 21:30:51

标签: javascript d3.js

我会用小提琴切断追逐:http://jsfiddle.net/K6Yrw/ [点击第二个按钮快速查看效果]


我正在使用selection.order因为我需要我的DOM元素以与数据元素相同的顺序存在。

我想向我的.exit()选项添加转换。但是,当与.order()结合使用时,该过程会中断。要删除的项目放在DOM元素列表的开头。

我的猜测:也许是因为order试图获取数据数组中元素的索引 - 当然它不再存在,因此得到-1作为索引,这意味着它应该被排序到DOM元素列表的开头。

如果我不使用order,则退出转换工作正常:但是如果我在数据数组中部分插入某些内容,当然新的DOM元素只会附加到结尾。

非常感谢任何提示或帮助!

2 个答案:

答案 0 :(得分:2)

我相信我有一个解决方案。问题是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 && next !== node.nextSibling && (!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/

答案 1 :(得分:0)

也许您只能在插入项目时尝试运行selection.order,而不是在删除项目时。

因此,为了纠正这个小提琴,你会在方法doD3()中添加一个参数,该方法包含是否运行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);
});