如何访问与D3 SVG对象相关的DOM元素?

XML*_*XML 55 svg dom visualization data-visualization d3.js

我试图通过试验他们的一个基本气泡图来学习D3 .第一项任务:弄清楚如何拖动气泡并让它在被拖动时成为最顶层的物体.(问题是让D3的对象模型映射到DOM上,但我会到达那里......)

要拖动它,我们可以使用它们提供的代码简单地调用d3的拖动行为:

var drag = d3.behavior.drag()
    .on("dragstart", dragstart)
    .on("drag", dragmove)
    .on("dragend", dragend);
Run Code Online (Sandbox Code Playgroud)

效果很好.拖得好.现在,我们如何让它成为最顶级的项目?在这里搜索"svg z-index",很快就会发现改变索引的唯一方法是在DOM中进一步向下移动一个对象.好.它们并不容易,因为单个气泡没有ID,但是在控制台上乱搞,我们可以找到其中一个气泡对象:

$("text:contains('TimeScale')").parent()
Run Code Online (Sandbox Code Playgroud)

我们可以将它移动到包含svg元素的末尾:

.appendTo('svg')
Run Code Online (Sandbox Code Playgroud)

执行此操作后拖动它,它是最顶层的项目.到目前为止,如果你完全在DOM中工作那么好.

但是:我真正想做的是在拖动给定对象/气泡时自动发生这种情况.D3提供了一个模型dragstart()dragend()函数,它们允许我们在拖动过程中嵌入一个语句来完成我们想要的操作.D3提供的d3.select(this)语法允许我们访问您当前正在拖动的对象/气泡的d3对象表示.但是我如何干净地将那个大型数组转换为对我可以与之交互的DOM元素的引用 - 例如 - 将其移动到svg容器的末尾,或者在DOM中执行其他引用,例如表单提交?

Tom*_*unn 174

您还可以通过selection.node()方法获取由选择表示的DOM元素

var selection = d3.select(domElement);

// later via the selection you can retrieve the element with .node()
var elt = selection.node();
Run Code Online (Sandbox Code Playgroud)

  • 这是一种更好的答案. (20认同)
  • 顺便说一句.这也是d3.js作者Mike Bostok在他的文章[How Selections Work](http://bost.ocks.org/mike/selection/)中的推荐方式 (7认同)

Phr*_*ogz 31

SVG文档中的任何DOM元素都将具有ownerSVGElement引用其所在SVG文档的属性.

D3的选择只是嵌套数组,上面有额外的方法; 如果你有.select()一个DOM元素,你可以得到它[0][0],例如:

var foo = d3.select(someDOM);

// later, where you don't have someDOM but you do have foo
var someDom = foo[0][0];
var svgRoot = someDom.ownerSVGElement;
Run Code Online (Sandbox Code Playgroud)

但请注意,如果您正在使用d3.select(this)那么this已经 DOM元素; 你不需要将它包装在D3选择中只是为了打开它.

  • 这似乎不起作用,至少在d3 4.0中不再有用.即使我的选择中有一个元素,`mySel [0]`对我来说是'undefined`.`mySel._groups [0] [0]`返回DOM元素,但这看起来不应该被访问.来自[其他答案](http://stackoverflow.com/a/22024786/1430156)的`mySel.node()`解决方案看起来更简洁. (5认同)
  • 哦,哇 那是票.我一直试图使用`d3.select(this)`,而不仅仅是'this`.因此,我可以大大简化`document.getElementsByTagName("svg")[0] .appendChild(document.getElementById(d3.select(this).attr('id')));`只需`$("svg") .append($(本));`.谢谢! (3认同)

Eli*_*jah 11

如果要追加,可以为各个元素分配ID和类:

node.append("circle.bubble")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return fill(d.packageName); })
.attr("id", function(d, i) { return ("idlabel_" + i)})
.attr("class", "bubble")
;
Run Code Online (Sandbox Code Playgroud)

然后你可以用class选择selectAll("circle.bubble")或者按id选择并修改属性,如下所示:

var testCircle = svg.select("#idlabel_3")
.style("stroke-width", 8);
Run Code Online (Sandbox Code Playgroud)