如何从给定步长的 D3 SVG 贝塞尔曲线中获取点?

How to get points from a D3 SVG bezier curve with given step size?

所以我有一个 D3 SVG 贝塞尔曲线 like this

我想从 D3 路径中获取具有给定步骤的点的 X、Y 坐标,如下所示:

所以要得到一个等步的坐标对数组。如果可能,不要重新计算贝塞尔曲线。如何在 D3js 中做这样的事情?

借助 here 的二分函数,您可能需要这样的东西:

const
  svg = d3.select("svg"),
  width = 512,
  height = 200;
const data = [];
const curve = "curveBasis";

var walk = function() {
  for (let i = 0, v = 2; i < 50; ++i) {
    v += Math.random() - 0.5;
    v = Math.max(Math.min(v, 4), 0);
    data.push({step: i, value: v});
  }
}

walk();

walkX = d3.scaleLinear()
  .domain([0, 49])
  .range([10, width - 10]);

walkY = d3.scaleLinear()
  .domain([0, 4])
  .range([200 - 10, 10]);

const line = d3.line()
  .curve(d3[curve])
  .x(d => walkX(d.step))
  .y(d => walkY(d.value));

svg
  .append("path")
  .attr("id", "svgpath")
  .attr("d", line(data))
  .attr("fill", "none")
  .attr("stroke", "black");

var svgpath = document.getElementById("svgpath");

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
}

for (let i = 0; i < data.length; ++i) {
  console.log(findYatXbyBisection(walkX(i), svgpath, 0.01).toFixed(4));
}
<html>
<head>
<meta charset="utf-8" />
<title>SVG Line</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.1/d3.min.js" integrity="sha512-COTaPOlz12cG4fSfcBsxZsjauBAyldqp+8FQUM/dZHm+ts/jR4AFoJhCqxy8K10Jrf3pojfsbq7fAPTb1XaVkg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<svg id="chart" width="512" height="200">
</svg>

请注意,返回的 Y 值是 SVG 坐标,因此它们从页面顶部的 0 开始。检查 walkY 函数中使用的范围函数以刷新您必须如何反转 D3.js.

中典型折线图和条形图的值

当然,您可以将值推送到您的自定义数组并使用不同的间隔值,例如我使用的总线(路径)宽度的 1/n 而不是 1/50(对于 50 个数据点)。