D3.js - what is selection.call() returning?

China☆狼群 提交于 2019-12-25 08:42:15

问题


I'm currently working on a force simulation. Here's the fiddle if you need it. This particular section is giving me a bit of trouble - I'm trying it for links and not nodes, where the situation is similar, so we can see the difference of working and non-working:

function linkRender(selection) {
    selection
        .data(links)
        .enter().append("line")
        .attr("stroke-width",2)
        .attr("stroke","black")
}
let link = svg.selectAll("line").call(linkRender);

Here, call() is supposed to return the selection, that is, the link lines. However, when rendering links in selection.on(), if I use the link variable to work with, it doesn't render properly, much to my distress:

simulation.on("tick",byFrame);
function byFrame() {
    // This doesn't work!
    link
        .attr("x1", d => d.source.x )
        .attr("y1", d => d.source.y )
        .attr("x2", d => d.target.x )
        .attr("y2", d => d.target.y )

    // But this works!
    svg.selectAll("circle")
        .attr("cx",d => d.x )
        .attr("cy",d => d.y )
}

And if I assign the link variable to linkRender() the old way, that is,

let link = linkRender(svg.selectAll("line"))

as long as I set linkRender() to return the code inside (return selection.data(links).etc), the rendering works fine.

Finally, here's a comparison of link and svg.selectAll("line"):

So I'd love to know what is going on. Thanks in advance!


回答1:


Your statements are not equivalent and are, therefore, not comparable. The documentation on selection.call() tells us:

Invokes the specified function exactly once, passing in this selection along with any optional arguments. Returns this selection.

This is to be understood literally: returning this selection means exactly the selection the specified function is called with. Because there are no lines prior to that call your selection will be empty when invoking .call() on it. Although you may successfully use this empty selection within that function to bind data and append the lines, this will not alter the original selection.

Because

Selections are immutable.

the .call() method will nonetheless return the original, i.e. empty, selection, which will then be assigned to link. It is easy to see, that this differs from your other solution when selecting the newly added lines afterwards or when returning the enter selection from your modified function.

It is actually working for the nodes, because in byFrame() you do not access them via node but by doing a svg.selectAll("circle") instead.

I think for this application using

let link = linkRender(svg.selectAll("line"));

will be the way to go. As you have already mentioned, this will require linkRender() to return the selection properly.



来源:https://stackoverflow.com/questions/41721841/d3-js-what-is-selection-call-returning

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!