【问题标题】:Specify startpoint to interpolate a circle on an arc when clicked on by the user指定起点以在用户单击时在圆弧上插入一个圆
【发布时间】:2016-11-25 13:53:26
【问题描述】:

如何提供弧线的起点以沿弧线的路径移动圆。我有一张世界地图,上面显示了几条弧线。我希望在用户使用.on('click') 事件选择的圆弧上插入圆的运动。我想知道如何识别相关弧的起点。

具体来说,我无法理解在圆的.attr("transform", "translate(" + startPoint + ")") 属性中提供哪些参数以使圆从圆弧的起始位置开始。

目前,它通过了整个路径,我收到以下错误

d3.v3.min.js:1 错误:属性转换:预期数字,“translate(M1051.5549785289…”。

尽管令人惊讶的是,圆形标记出现在屏幕上,并沿已绘制的第一条弧线插入。但是,我希望将此插值更改为用户单击的弧。换句话说,每次用户点击不同的弧线时,我如何向圆形标记提供一个新的 startPoint 并对其进行后续插值。

var path3 = arcGroup.selectAll(".arc"),
    startPoint = pathStartPoint(path3)

var marker = arcGroup.append("circle")
marker.attr("r", 7)
  .attr("transform", "translate(" + startPoint + ")")

transition();

function pathStartPoint(path) {
  var d = path.attr("d")
  console.log(path)
  dsplitted = d.split(" ");
  return dsplitted[0].split(",");
}

function transition() { 
  marker.transition()
    .duration(7500)
    .attrTween("transform", translateAlong(path3.node()))
    .each("end", transition);// infinite loop
}

function translateAlong(path) {
  var l = path.getTotalLength();
  return function(i) {
    return function(t) {
      var p = path.getPointAtLength(t * l);
      return "translate(" + p.x + "," + p.y + ")";//Move marker
    }
  }
}

【问题讨论】:

  • 我不完全确定您的特定脚本(或 D3,就此而言)如何工作。但是,是否有可能(或者您已经)在屏幕上有一个标记列表及其坐标?在我看来,您应该能够在传递这些坐标时重新调用您的 arc 函数?还是我在这里遗漏了什么?
  • 感谢您的回复刘易斯。现在绘制弧线的方式是使用 LineString,其中我指定了三个坐标,根据这些坐标绘制弧线。这些坐标从 csv 文件中读取并存储在称为链接的数组中。我进一步使用 links.push 后跟 .enter() 来绘制弧线
  • @sjaikumar 无需明确将其设置为起点。一旦过渡开始运行,它将调用translateAlong() 的最里面的插值函数,起始值为t = 0,这将隐式计算起点。
  • 感谢@altocumulus 也解释了这背后的理论。我现在能够实现它。非常感谢:)

标签: javascript d3.js interpolation


【解决方案1】:

正如@altocumulus 在他们的评论中所说,getPointAtLength 不需要起点。它将从 0 到路径长度的距离作为参数,其中 0 是起点。这是一个简单的示例,单击下面的任意路径:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <script>
    var w = 400,
      h = 400;

    var svg = d3.select('body')
      .append('svg')
      .attr('width', w)
      .attr('height', h);

    var data = []
    for (var i = 0; i < 5; i++) {
      data.push({
        x0: Math.random() * w,
        y0: Math.random() * h,
        x1: Math.random() * w,
        y1: Math.random() * h
      });
    }

    var marker = svg.append("circle")
      .attr("r", 20)
      .style("fill", "steelblue")
      .style("opacity", 0);

    svg.selectAll("path")
      .data(data)
      .enter()
      .append("path")
      .attr("d", function(d) {
        var dx = d.x1 - d.x0,
          dy = d.y1 - d.y0,
          dr = Math.sqrt(dx * dx + dy * dy);
        return "M" + d.x0 + "," + d.y0 + "A" + dr + "," + dr +
          " 0 0,1 " + d.x1 + "," + d.y1;
      })
      .style("stroke", function(d, i) {
        return d3.schemeCategory10[i];
      })
      .style("stroke-width", "10px")
      .style("fill", "none")
      .on("click", function(d){
          marker
            .style("opacity", 1)
            .transition()
            .duration(1000)
            .attrTween("transform", translateAlong(this))
            .on("end", function(d) {
              marker.style("opacity", 0);
            });
      });

    function translateAlong(path) {
      var l = path.getTotalLength();
      return function(i) {
        return function(t) {
          var p = path.getPointAtLength(t * l);
          return "translate(" + p.x + "," + p.y + ")"; //Move marker
        }
      }
    }
  </script>
</body>

</html>

【讨论】:

  • 这就像一个魅力。感谢您也解释了它背后的理论,并感谢您花时间通过一个例子来解释它。我感激不尽:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-30
  • 1970-01-01
  • 2021-04-09
  • 2011-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多