如何沿路径移动但仅在两个指定的路径点之间移动

时间:2017-05-02 07:56:55

标签: javascript d3.js svg path percentage

这个问题是关于d3版本3.x和路径移动。

想象一下,有一个路径和一个圆形元素,我希望圆圈在转换中遵循该路径,但只能达到一定的百分比。 我之前问过这个问题,并在Gerardo Furtado得到了一个很好的答案:My former question

尽管如此,这方面的一个问题仍然适用于我,而且由于我是初学者,到目前为止我找不到任何可行的解决方案:

我怎样才能追踪这条路径,比如说,从25%到50%的点,然后从50%的点到60%的点? < / p>

这些数字只是示例,任何百分比值都应该是可能的。

我需要避免路径移动始终从位置0开始,而是我想从圆已经到达的当前位置开始路径移动。

希望我能够清楚表达我的问题。

非常感谢您的任何见解和帮助。

1 个答案:

答案 0 :(得分:1)

嗯,我必须同意LeBeau,我也知道你也这样做了。自从我回答了你last question之后,我只需要对功能进行一些细微的修改。但是,请记住下一次的建议:在提出问题时,向我们展示一些您尝试过的代码,即使有效,因为它显示了努力。

回到问题。

对于这个解决方案,我将把所有东西都包装在一个名为move的函数中,该函数接受两个参数,即初始位置和最终位置(均为百分比):

function move(initialPosition, finalPosition) {

顾名思义,初始位置设置圆沿路径的初始位置。数学是这样的:

var start = path.node()
    .getPointAtLength(path.node().getTotalLength() * initialPosition);

然后,我稍微改变了我的上一个答案的功能,接受了初始和最终的职位:

function translateAlong(path) {
    var l = path.getTotalLength() * (finalPosition - initialPosition);
    return function() {
        return function(t) {
            var p = path.getPointAtLength(t * l + 
                (path.getTotalLength() * initialPosition));
            return "translate(" + p.x + "," + p.y + ")";
        };
    };
}

这是演示。点击按钮调用move 0.25(初始位置)和0.5(最终位置)作为参数:

var points = [
  [240, 100],
  [290, 200],
  [340, 50],
  [390, 150],
  [90, 150],
  [140, 50],
  [190, 200]
];

var svg = d3.select("body").append("svg")
  .attr("width", 500)
  .attr("height", 300);

var path = svg.append("path")
  .data([points])
  .attr("d", d3.svg.line()
    .tension(0) // Catmull–Rom
    .interpolate("cardinal-closed"));

var color = d3.scale.category10();

var dataPositions = [{
  initial: 0.25,
  final: 0.5
}, {
  initial: 0.5,
  final: 0.6
}];


svg.selectAll(".point")
  .data(points)
  .enter().append("circle")
  .attr("r", 4)
  .attr("transform", function(d) {
    return "translate(" + d + ")";
  });

d3.select("button").on("click", function() {
  move(0.25, 0.5);
});

function move(initialPosition, finalPosition) {

  var start = path.node().getPointAtLength(path.node().getTotalLength() * initialPosition);

  var circle = svg.append("circle")
    .attr("r", 13)
    .attr("fill", function(d, i) {
      return color(i)
    })
    .attr("transform", "translate(" + start.x + "," + start.y + ")");

  circle.transition()
    .duration(1000)
    .attrTween("transform", function() {
      return translateAlong(path.node())()
    });

  function translateAlong(path) {
    var l = path.getTotalLength() * (finalPosition - initialPosition);
    return function() {
      return function(t) {
        var p = path.getPointAtLength(t * l + 
            (path.getTotalLength() * initialPosition));
        return "translate(" + p.x + "," + p.y + ")";
      };
    };
  }

}
path {
  fill: none;
  stroke: #000;
  stroke-width: 3px;
}

circle {
  stroke: #fff;
  stroke-width: 3px;
}
<script src="//d3js.org/d3.v3.min.js"></script>
<button>Move</button>
<br>

PS:此答案中的功能不接受大于1的值。但如果您需要在路径中执行超过“一圈”的操作,则可以尝试更改它。