如何从 DOM 元素本身创建选择

How to create selection from DOM element itself

在 d3.js 中,如果我得到一个唯一标识 DOM 元素的 CSS 选择器,我可以创建一个仅包含该元素的选择,例如,使用

svg.selectAll("g.node#"+d.id)

假设我得到了 DOM 元素本身,例如,已经存在的特定 <g>。将 DOM 元素直接传递给 selectAllselect 会产生错误,在 Firefox 中报告为 "SyntaxError: An invalid or illegal string was specified",或在 Chrome 中报告为 "Uncaught SyntaxError: Failed to execute 'querySelectorAll' on 'Element': '[object SVGGElement]' is not a valid selector"。

如何根据对 DOM 元素本身的引用创建选区?应该没有必要让 D3 使用 CSS 选择器去搜索元素。

目前,我已经有了工作代码,可以通过构造一个独特的 CSS 选择器来获得适当的选择,但这似乎是不必要的工作,因为我已经有了对 [=59= 的引用] 我想附加东西的元素。

编辑:

感谢@meetamit 和@LarsKotthoff:好吧,如果它只适用于 DOM 元素上的 selectAll,那么我的代码有些地方我不明白(不足为奇)。我试图避免将大量代码转储到我的 SO 问题中,但我不知道还能做什么。这是一个 fiddle. It doesn't run in jsfiddle, and I don't know why, but it runs just fine without jsfiddle in Firefox, Chrome and Safari. (Here's a fiddle,它只包含我在 HTML window 中的整个文件。)

我的代码应该为强制布局中的每个节点添加一个小包布局。可能有一种纯粹惯用的方法来做到这一点,但我只是通过在力布局中的节点上调用 each,从一个单独的函数中添加包布局,才成功地让它工作:

var svgnodes = svg.selectAll("g.node")
    .data(data.nodes, function (d) {return d.id;})
    .enter()
    .append("g")
    .attr("class", "node")
    .attr("id", function (d) {return d.id;})
    .call(layout.drag())
    .on("click", click);

svgnodes.each(function (d, i) {addPersonCircles(d, svg, this);});

这是 addPersonCircles 的部分定义:

function addPersonCircles (d, svg, personG) {
    // makes a data new structure for use by pack layout:
    function makeroot (id) {return {"name":name, "children":[{"name":"a"}, {"name":"p"}]};}

      // data structure containing three elements, one for each element generated by makeroot()
    var pack = d3.layout.pack()
        .size([personRadius, personRadius])
        .value(function (d) {return 1;})
        .nodes(makeroot(d.id));

    // KLUDGE. Isn't there a way to select using the dom element personG that was passed in?
    svg.selectAll("g.node#"+d.id)    // find particular existing g node in person net
        .selectAll("circle.person")  // create new circles within g node
        .data(pack)
        .enter()
        .append("circle")
        ...
}

当我添加 console.log(personG) 时,即显示 each() 中的 this 内容时,显示的内容如下所示:

<g class="node" id="sandra" transform="translate(263.59494561798255,242.1803122208288)">...</g>

我有时对 this 指的是什么感到困惑,但这里它似乎指的是 DOM 节点,而不是别的。但是,当我将 svg.selectAll("g.node#"+d.id) 替换为 svg.selectAll(personG) 时,我收到了上面报告的错误消息。结果如下所示。感谢您的帮助。

您可以使用 d3.select() 将 DOM 节点变成 D3 选择。您不能 使用selection.selectAll() 将DOM 节点变成D3 选择。您想要的代码是

d3.select(personG) 
    .selectAll("circle.person")  // create new circles within g node
    // ...

注意两点:

  1. 语句的根是全局 d3. 而不是选择 svg.
  2. 选择是使用 select() 而不是 selectAll()

Meetamit 完全正确。

您可以使用 d3.select():

将单个 DOM 节点转换为 D3 选择

If the selector is not a string, instead selects the specified node; this is useful if you already have a reference to a node, such as this within an event listener or a global such as document.body

此外,您可以使用 d3.selectAll():

将 DOM 节点数组转换为 d3 选择

If the selector is not a string, instead selects the specified array of nodes; this is useful if you already have a reference to nodes, such as this.childNodes ...