【问题标题】:d3.js duplicate code for enter selection and update selectiond3.js 用于输入选择和更新选择的重复代码
【发布时间】:2014-07-01 06:50:24
【问题描述】:

我正在使用 d3.js 开发一些图表。我只是在编写一些函数来在屏幕上绘制一些线条。但是我发现自己编写了重复的代码来设置属性以输入选择和更新选择。更糟糕的是,这是不可避免的。

检查下面的代码。最初,我认为这很酷。每次输入的数据有变化,我只要调用这个函数,图表就会随之更新:如果有更多的数据进来,就会增加新的线条,如果只有数据改变,就会重新绘制现有的线条。

function drawLines(data){

    svg.selectAll('line')
        .data(data)
        .enter()
        .append('line')
        .attr({
            x1: function(d){
                return d.x1;
            },
            y1: function(d){
                return d.y1;
            },
            x2: function(d){
                return d.x2;
            },
            y2: function(d){
                return d.y2
            }
        })
        .style({
            stroke: 'black',
            'stroke-width': 4
        });;
}

但我发现它不起作用。 append 方法不会同时返回 update + enter 选择。我仍在处理输入选择。所以我必须编写如下代码:

function drawLines(data){

    var updateSelection = svg.selectAll('line')
                            .data(data);

    var enterSelection = updateSelection
                            .enter()
                            .append('line');

    enterSelection
        .attr({
            x1: function(d){
                return d.x1;
            },
            y1: function(d){
                return d.y1;
            },
            x2: function(d){
                return d.x2;
            },
            y2: function(d){
                return d.y2
            }
        })
        .style({
            stroke: 'black',
            'stroke-width': 4
        });

    updateSelection
        .attr({
            x1: function(d){
                return d.x1;
            },
            y1: function(d){
                return d.y1;
            },
            x2: function(d){
                return d.x2;
            },
            y2: function(d){
                return d.y2
            }
        })
        .style({
            stroke: 'black',
            'stroke-width': 4
        });
}

如您所见,我正在编写重复的 attr,样式代码只是为了对输入选择和更新选择执行相同的操作。但是 d3.js 文档的 enter 方法部分说:

当您追加时,输入选择合并到更新选择中 或插入。这种方法减少了输入和输入之间的代码重复 更新。而不是将运算符应用于输入和更新 单独选择,您现在可以将它们应用于更新选择 进入节点后。在您想要运行的极少数情况下 运算符仅在更新节点上,您可以在更新时运行它们 在进入新节点之前进行选择。

现在我对“输入选择合并到更新选择”和“减少输入和更新之间的代码重复”的含义感到困惑。难道我做错了什么?据我了解,enter和update之间的重复代码是不可避免的!

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    文档的意思是,一旦您附加元素,它们将成为更新选择的一部分。也就是说,您在更新选择中设置的任何属性也将在您之前从输入选择中附加的元素上设置。所以你只需要以下代码:

    var updateSelection = svg.selectAll('line')
                            .data(data);
    
    updateSelection.enter().append('line');
    
    updateSelection
        .attr({
            x1: function(d){
                return d.x1;
            },
            y1: function(d){
                return d.y1;
            },
            x2: function(d){
                return d.x2;
            },
            y2: function(d){
                return d.y2
            }
        })
        .style({
            stroke: 'black',
            'stroke-width': 4
        });
    

    注意这里代码的顺序很重要——你需要在设置更新选择的属性之前附加输入选择的元素。

    【讨论】:

    • 你刚刚彻底改变了我对 d3.js 的理解。我终于可以摆脱那些我觉得对我毫无意义的重复了。非常感谢!
    • 对于 d3.v4,查看 Interactive General Update Patternmerge 函数。
    • 我必须执行以下操作才能使其正常工作(d3 3 甚至):``` var enterSelection = updateSelection.enter().append('line'); updateSelection.merge(enterSelection).attr(...) ```
    【解决方案2】:

    您可以删除 .style 进行更新,但您需要保留 x1、y1、x2、x2

    这样做的原因是d3基于一个简单的原理:

    • 更新[数据集中存在的记录]
    • 输入[进入数据集的记录]
    • exit [离开数据集的记录]

    在更新中,可以转换与以前具有相同“键”的值。所以假设你有一个这样的数据集:

    [ { name: 'A', value: 2 } ]
    

    后来改成了:

    [ { name: 'A', value: 3 } ]
    

    您需要以某种方式将现有名称“A”从 2 更新为 3。

    这就是为什么您需要 x1、x2、y1、y2 来更新。

    希望这会有所帮助。

    【讨论】:

    • 嗨链接,我的困惑是为什么需要在更新选择和输入选择时编写两次相同的代码。无论是代码的属性还是样式部分。正如您从 d3 文档中看到的那样。这是说能够避免输入和更新选择之间的代码重复。我只是不知道怎么做。
    • 这在技术上是重复代码,但大多数时候在输入时,我会将 x1 设置为 0,在其上放置一个转换并延迟 1 秒,然后将 x1 设置为它的实际值。这样,您可以看到数据在进入时飞入数据集。您不希望在更新时这样做,因此您只需将 x1 设置为新值,数据就会从旧值增长到新值。最后,您可以让数据在退出时飞出数据集。过渡是 d3 的很大一部分,如果使用得当,它会非常强大。使用转换时不会重复代码。
    猜你喜欢
    • 1970-01-01
    • 2021-01-14
    • 2012-10-19
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 2016-12-26
    • 2023-03-24
    • 2016-07-23
    相关资源
    最近更新 更多