在D3中,如何让从SVG线插入线数据?(In d3, how to get the interpol

2019-06-17 11:13发布

我显示与D3的线图与大致下面的代码(给定尺度函数xy和浮子阵列data ):

 var line = d3.svg.line()
         .interpolate("basis")
         .x(function (d, i) { return x(i); })
         .y(function (d) { return y(d); });
 d3.select('.line').attr('d', line(data));

现在我想知道线的垂直高度在给定的水平像素位置 。 该data阵列具有较小的数据点比像素和显示的行进行内插 ,所以它不是直接的在距离给定的像素来推导线的高度data数组。

任何提示?

Answer 1:

编辑19月- 2012年间的意见 与许多感谢nrabinowitz!

你需要做一些搜索返回的数据的getPointAtLength 。 (见https://developer.mozilla.org/en-US/docs/DOM/SVGPathElement 。)

// Line
var line = d3.svg.line()
     .interpolate("basis")
     .x(function (d) { return i; })
     .y(function(d, i) { return 100*Math.sin(i) + 100; });

// Append the path to the DOM
d3.select("svg#chart") //or whatever your SVG container is
     .append("svg:path")
     .attr("d", line([0,10,20,30,40,50,60,70,80,90,100]))
     .attr("id", "myline");

// Get the coordinates
function findYatX(x, linePath) {
     function getXY(len) {
          var point = linePath.getPointAtLength(len);
          return [point.x, point.y];
     }
     var curlen = 0;
     while (getXY(curlen)[0] < x) { curlen += 0.01; }
     return getXY(curlen);
}

console.log(findYatX(5, document.getElementById("myline")));

对我来说,这将返回[5.000403881072998,140.6229248046875。

此搜索功能, findYatX ,是远远有效的(在运行O(n)的时间),但说明了这一点。



Answer 2:

该解决方案是不是接受的答案更有效。 它的执行时间是对数(同时接受的答案具有线性复杂度)。

var findYatXbyBisection = function(x, path, error){
  var length_end = path.getTotalLength()
    , length_start = 0
    , point = path.getPointAtLength((length_end + length_start) / 2) // get the middle point
    , bisection_iterations_max = 50
    , bisection_iterations = 0

  error = error || 0.01

  while (x < point.x - error || x > point.x + error) {
    // get the middle point
    point = path.getPointAtLength((length_end + length_start) / 2)

    if (x < point.x) {
      length_end = (length_start + length_end)/2
    } else {
      length_start = (length_start + length_end)/2
    }

    // Increase iteration
    if(bisection_iterations_max < ++ bisection_iterations)
      break;
  }
  return point.y
}


Answer 3:

我曾尝试推行findYatXbisection(如通过很好建议本布),我无法得到它的AS就是工作。

而不是修改长度length_end和length_start的函数的,我只下降了50%的长度(如果x <point.x)或增加50%(如果x> point.x),但总是相对于开始的零长度。 我也纳入revXscale / revYscale由我d3.scale功能设置为像素转换成X / Y值。

function findYatX(x,path,error){
    var length = apath.getTotalLength()
        , point = path.getPointAtLength(length)
        , bisection_iterations_max=50
        , bisection_iterations = 0
    error = error || 0.1
    while (x < revXscale(point.x) -error || x> revXscale(point.x + error) {
        point = path.getPointAtlength(length)
        if (x < revXscale(point.x)) {
             length = length/2
        } else {
             length = 3/2*length
        }
        if (bisection_iterations_max < ++ bisection_iterations) {
              break;
        }
    }
return revYscale(point.y)
}


文章来源: In d3, how to get the interpolated line data from a SVG line?