【问题标题】:How do I return y coordinate of a path in d3.js?如何在 d3.js 中返回路径的 y 坐标?
【发布时间】:2012-09-14 20:32:55
【问题描述】:

我有一个图表,当悬停在 svg 区域的顶部时,我希望表示该图表的线在 x 坐标处显示一个圆圈。这个圆圈应该沿着代表曲线的线的路径。问题是我不知道该怎么做。

下面的代码显示了我的成功程度,它确实在文档的右侧 x 坐标处添加了一个圆圈。现在,我用什么代替问号?

    svg.on("mousemove", function() {
        d3.select("path.line")
          .style("stroke-width", "2.5px");

         svg.append("svg:circle")
            .attr("cx", Math.floor(event.offsetX-m[1]))
            .attr("cy", ?)
            .attr("r", "10")
            .attr("fill", "red");
    });

【问题讨论】:

    标签: javascript svg d3.js


    【解决方案1】:

    SVG 提供了一个名为 .getPointAtLength() 的本机函数,它返回一个路径的 x 和 y 值,无论您通过它的任何长度。

    您需要遍历该行的长度,直到找到相应的 y 位置。以下是您在 D3 中的操作方式:

    var svg = d3.select("#line").append("svg")
    var path = 
        svg.append("path")
          .attr("d", "M0,168L28,95.99999999999997L56,192L84,71.99999999999997L112,120L140,192L168,240L196,168L224,48L252,24L280,192L308,120L336,24L364,168L392,95.99999999999997L420,168L448,95.99999999999997L476,192L504,71.99999999999997L532,120L560,192L588,216L616,168L644,48L672,24L700,192L728,120L756,24L784,192L812,71.99999999999997")
          .attr("fill", "none")
          .attr("stroke", "black");
    
    var circle = 
        svg.append("circle")
          .attr("cx", 100)
          .attr("cy", 350)
          .attr("r", 3)
          .attr("fill", "red");
    
    var pathEl = path.node();
    var pathLength = pathEl.getTotalLength();
    var BBox = pathEl.getBBox();
    var scale = pathLength/BBox.width;
    var offsetLeft = document.getElementById("line").offsetLeft;
    var randomizeButton = d3.select("button");
    
    svg.on("mousemove", function() {
      var x = d3.event.pageX - offsetLeft; 
      var beginning = x, end = pathLength, target;
      while (true) {
        target = Math.floor((beginning + end) / 2);
        pos = pathEl.getPointAtLength(target);
        if ((target === end || target === beginning) && pos.x !== x) {
            break;
        }
        if (pos.x > x)      end = target;
        else if (pos.x < x) beginning = target;
        else                break; //position found
      }
      circle
        .attr("opacity", 1)
        .attr("cx", x)
        .attr("cy", pos.y);
    });
    

    您可以在此处查看演示:http://bl.ocks.org/3824661

    【讨论】:

    • 我很确定这不适用于任意时间线样式的路径形状,例如一条在某一点处具有非常尖锐尖峰的线将不允许在路径长度和 x 位置之间进行线性插值。
    • @nrabinowitz 这很简单,可以测试jsfiddle.net/FPfFJ,是的,它还不够。
    • 是的,我认为在这种情况下使用.getPointAtLength() 获得准确点的唯一方法是沿线搜索,直到找到x 值接近d3.event.pageX 的点.
    • 不错!我很想看到有人为这个问题实现二进制搜索,但这非常可靠。
    • @Snowfish 假设您有一条以宽曲线开头的线∩∩∩———,当您位于屏幕中间时,您将处于屏幕宽度的 50% 处。然而,这条线可能是它长度的 75%,但在计算所有候选位置之前,您无法确定(例如,一条线的长度永远不会小于屏幕的宽度)。
    猜你喜欢
    • 1970-01-01
    • 2017-11-26
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 2018-10-16
    • 1970-01-01
    • 2014-05-03
    相关资源
    最近更新 更多