Javascript 如何返回d3.js中路径的y坐标?

Javascript 如何返回d3.js中路径的y坐标?,javascript,svg,d3.js,Javascript,Svg,D3.js,我有一个图形,我希望表示图形的线在svg区域顶部悬停时在x坐标处显示一个圆。该圆应沿着表示曲线的直线的路径。问题是我不知道怎么做 下面的代码显示了我成功的程度,它确实在文档的右x坐标处添加了一个圆。现在,我用什么来代替问号呢 svg.on("mousemove", function() { d3.select("path.line") .style("stroke-width", "2.5px"); svg.append("svg:

我有一个图形,我希望表示图形的线在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");
    });

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);
});
var svg=d3.选择(“行”).追加(“svg”)
变量路径=
追加(“路径”)
.attr(“d”,“M0168L28,95.9999999999997L56192L84,71.9999999999997L12120L140192L16240L196168L224,48L252,24L280192L308120L336,24L364168L392,95.9999999999999997L448,95.9999999999999997L476192L504,71.9999999999999999999997L32120L56019288216168L6448L672,24L728120L756,24L927,417”)
.attr(“填充”、“无”)
.attr(“笔划”、“黑色”);
变量圆=
svg.append(“圆”)
.attr(“cx”,100)
.attr(“cy”,350)
.attr(“r”,3)
.attr(“填充”、“红色”);
var pathEl=path.node();
var pathLength=pathEl.getTotalLength();
var BBox=pathEl.getBBox();
变量比例=路径长度/BBox.width;
var offsetLeft=document.getElementById(“行”).offsetLeft;
var randomizeButton=d3.选择(“按钮”);
on(“mousemove”,function()){
var x=d3.event.pageX-offsetLeft;
变量开始=x,结束=路径长度,目标;
while(true){
目标=数学楼层((开始+结束)/2);
pos=路径getPointAtLength(目标);
如果((目标==结束| |目标==开始)&&pos.x!==x){
打破
}
如果(位置x>x)结束=目标;
否则,如果(位置x

您可以在这里看到一个演示:

我很确定这对任意时间线样式的路径形状不起作用,例如,在一个点上有一个非常尖锐的尖峰的线将不允许在路径长度和x位置之间进行线性插值。@nrabinowitz这非常简单,可以测试,是的,它不完全存在。是的,我认为在这种情况下,使用
.getPointAtLength()
获得准确点的唯一方法是沿直线搜索,直到找到一个
x
值接近
d3.event.pageX
的点。很好!我很想看到有人对这个问题进行二进制搜索,但这是非常可靠的。@Snowfish想象你有一条开始有宽曲线的直线
∩∩∩———,当您位于屏幕中间时,您将处于屏幕宽度的50%。然而,这条线可能是其长度的75%,但在计算所有候选位置之前,您无法确定这一点(例如,一条线的长度永远不会小于屏幕的宽度)。