如何从 DOM 元素本身创建选择
How to create selection from DOM element itself
在 d3.js 中,如果我得到一个唯一标识 DOM 元素的 CSS 选择器,我可以创建一个仅包含该元素的选择,例如,使用
svg.selectAll("g.node#"+d.id)
假设我得到了 DOM 元素本身,例如,已经存在的特定 <g>
。将 DOM 元素直接传递给 selectAll
或 select
会产生错误,在 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
// ...
注意两点:
- 语句的根是全局
d3.
而不是选择 svg.
- 选择是使用
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 ...
在 d3.js 中,如果我得到一个唯一标识 DOM 元素的 CSS 选择器,我可以创建一个仅包含该元素的选择,例如,使用
svg.selectAll("g.node#"+d.id)
假设我得到了 DOM 元素本身,例如,已经存在的特定 <g>
。将 DOM 元素直接传递给 selectAll
或 select
会产生错误,在 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
// ...
注意两点:
- 语句的根是全局
d3.
而不是选择svg.
- 选择是使用
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 ...