【问题标题】:How to access the parentNode of a selection to raise an element?如何访问选择的 parentNode 以引发元素?
【发布时间】:2012-05-15 19:44:40
【问题描述】:

我创建了以下文档:

<g>
    <path class=​"line" name=​"gene_1" stroke=​"#aec7e8" d=​"M10.47...">​</path>​
    <path class=​"line" name=​"gene_2" stroke=​"#aec7e8" d=​"M10.47...">​</path>​
    <path class=​"line" name=​"gene_3" stroke=​"#aec7e8" d=​"M10.47...">​</path>​
    ...
</g>

当我将鼠标悬停在每条路径上时,我想将其最后附加到 svg:g 中,以便它出现在其他行的顶部,但我不知道如何正确选择 parentNode

function onmouseover(d, i){
  var current_gene_name = d3.select(this).attr("name"),
      current_gene_pcp = d3.select(".line[name=" + current_gene_name + "]");

  p1 = this.parentNode 

  p2 = current_gene_pcp[0].parentNode

  p3 = current_gene_pcp[0][0].parentNode

  //p.appendChild(this);
}

p1 有效,但我想确保this.line,所以我更喜欢使用current_gene_pcp,但p2 返回&lt;html&gt;&lt;/html&gt; 作为父级,即使p3返回正确的&lt;g&gt;&lt;/g&gt;。最后一个版本似乎是一个等待发生的错误。有没有更好的办法?

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    D3 选择只是一个包裹在所选元素周围的双数组。正如您在p3 中发现的那样,您可以根据需要取消引用数组以找到您的第一个节点。但是,确实存在更好的方法:

    来自selection.node() 的文档:

    返回当前选择中的第一个非null 元素。如果选择为空,则返回null

    在你的情况下:

    var dad = current_gene_pcp.node().parentNode;
    

    但是,如果您不需要 DOM 句柄以外的行,您不妨直接获取:

    // Search document-wide...
    var dad = document.querySelector(".line[name=" + current_gene_name + "]");
    
    // ...or only as a child of the current DOM element
    var dad = this.querySelector(".line[name=" + current_gene_name + "]");
    

    【讨论】:

      【解决方案2】:

      这是将鼠标悬停元素移到前面的快速方法:

      selection.on("mouseover", function() { this.parentNode.appendChild(this); });
      

      另见 d3-js 组中的 related thread

      【讨论】:

      • 此行为不稳定。当我在 Chrome 中结合:hover 样式尝试此操作时,样式已正确应用。当我在 Firefox (v20) 中尝试此操作时,根本不会应用这些样式。当我删除此 mouseover 代码时,样式会正确应用到 Firefox 中。我猜这是由于元素的 mouseover` 在重新附加为其 DOM 的最后一个子元素之前尝试将其自身移除。
      【解决方案3】:

      有两种方法可以访问它。
      像这样使用third variablesomeNode.attr("someAttrib", function(d, i, j) { console.log(d, i, j); });j 包含您提供给父​​节点的数据。
      或使用d3.select(this.parentNode).data()[0].id;

      一个例子:

      <!DOCTYPE html>
      <meta charset="utf-8">
      <body>
      <script src="http://d3js.org/d3.v3.min.js"></script>
      <div id="area", width="1000px" height="1000px"></div>
      <script>
      var GAP = 10, NODE_RADIUS = 14;
      
        var nodes = [
          {id: 1, prop: [{id: 1, something: 1}], abc: 1},
          {id: 2, prop: [{id: 1, something: 1}, {id: 2, something: 1}, {id: 3, something: 1}], abc: 2},
          {id: 3, prop: [{id: 1, something: 1}, {id: 2, something: 1}], abc: 3},
          {id: 4, prop: [{id: 1, something: 1}], abc: 4},
          {id: 5, prop: [{id: 1, something: 1}], abc: 5},
          {id: 6, prop: [], abc: 6}
        ];
      
      var nodeLayer = d3.select("#area").selectAll(".node").data(nodes, function(d) {return d.id; });
      var iNodes = nodeLayer.enter().append("svg").attr("class", "node");
          //append the black circle
          iNodes.append("circle")
                      .style("fill", "black")
                      .attr("r", NODE_RADIUS)
                      .attr("cx", function(d) {return 10 + d.id * 10;})
                      .attr("cy", 100);
      
          iNodes.append("g").selectAll(".prop").data(function(d) {return d.prop;}).enter()
                  .append("text")
                      .text(function(d,i,j){console.log("parent id="+j); return d3.select(this.parentNode).data()[0].id;})
                      .attr("dx", 50)
                      .attr("dy", 50)
                      .style("font-size", "8px")
                      .style("fill", d3.rgb(180,0,0))
                      .style("text-anchor", "middle");
      
      </script>
      </body>
      

      【讨论】:

        【解决方案4】:

        出于某种原因,我不得不上 2 倍级别:console.log("&gt;&gt;"+my_chart.node().parentNode.parentNode.id+"&lt;&lt;")

        【讨论】:

          【解决方案5】:

          我做过的一种方法是:

          bars.on('mouseover', d => {
          let parentNode = d3.select(this.parentNode);
          let tooltip = parentNode.append('rect)
          
          

          this关键字,可以访问当前节点,然后触摸它的parentNode。

          【讨论】:

            【解决方案6】:

            随着 D3 v4 的发布,这已成为一种 XY-problem。不再需要到达parentNode 以将元素重新插入为其父级的最后一个子级。因为从 D3 上的那个版本开始提供 selection.raise() 方法:

            选择提高()

            按顺序将每个选定元素重新插入为其父元素的最后一个子元素。相当于:

            selection.each(function() {
              this.parentNode.appendChild(this);
            });
            

            使用 D3 v6 将事件作为第一个参数传递给事件侦听器(请参阅changelog),您的代码可以像这样简单:

            function onmouseover(event) {
              d3.select(event.target).raise();
            }
            

            看看下面的演示:

            d3.select("g")
              .on("mouseover", event => d3.select(event.target).raise())
            <script src="https://d3js.org/d3.v6.js"></script>
            
            <svg width="400" height="400">
              <g>
                <rect x="100" y="50" width="100" height="100" fill="red"></rect>
                <rect x="150" y="50" width="100" height="100" fill="blue"></rect>
              </g>
            </svg>

            【讨论】:

              猜你喜欢
              • 2017-05-11
              • 1970-01-01
              • 2013-12-12
              • 2023-04-02
              • 2017-08-02
              • 1970-01-01
              • 2020-02-18
              • 1970-01-01
              • 2020-02-12
              相关资源
              最近更新 更多