如何更改d3 pathTween函数

时间:2017-01-26 02:24:59

标签: d3.js path tween

我尝试使用找到here的代码作为项目的起点。此代码使用D3在两个路径之间使用名为pathTween()的函数进行转换,如下所示:

function pathTween(d1, precision) {
  return function() {
    var path0 = this,
        path1 = path0.cloneNode(),
        n0 = path0.getTotalLength(),
        n1 = (path1.setAttribute("d", d1), path1).getTotalLength();

    // Uniform sampling of distance based on specified precision.
    var distances = [0], i = 0, dt = precision / Math.max(n0, n1);
    while ((i += dt) < 1) distances.push(i);
    distances.push(1);

    // Compute point-interpolators at each distance.
    var points = distances.map(function(t) {
      var p0 = path0.getPointAtLength(t * n0),
          p1 = path1.getPointAtLength(t * n1);
      return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]);
    });

    return function(t) {
      return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1;
    };
  };
}

让我感到困惑的是,在这个例子中,这段代码中的某些东西使转换成为一种轻松的移动,我希望将其更改为线性。我认为它必须是pathTween()中使用的一个函数中的D3默认值,除非我忽略了添加该缓动的pathTween()部分。

任何人都知道可能会有什么违约行为以及如何改变它?

由于

1 个答案:

答案 0 :(得分:3)

在D3 v3.x中transition

  

默认缓动功能是“立方体输出”。

cubic-in-out缓和......

  

...提供合适的slow-in slow-out动画。

因此,如果你想要线性缓动,你只需要明确地设置它:

path.transition()
    .duration(2000)
    .ease("linear")//set the ease here
    .attrTween("d", pathTween(d1, 4))
    .each("end", function() { d3.select(this).call(transition, d1, d0); });

以下是缓解的代码:http://blockbuilder.org/anonymous/d0f28de24658467d48053ef6e39e8413

S.O.中的相同代码片段:

var width = 960,
    height = 500;

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

var d0 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100",
    d1 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100c100,0 0,100 100,100";

svg.append("path")
    .attr("transform", "translate(180,150)scale(2,2)")
    .attr("d", d0)
    .call(transition, d0, d1);

function transition(path, d0, d1) {
  path.transition()
      .duration(2000)
      .ease("linear")
      .attrTween("d", pathTween(d1, 4))
      .each("end", function() { d3.select(this).call(transition, d1, d0); });
}

function pathTween(d1, precision) {
  return function() {
    var path0 = this,
        path1 = path0.cloneNode(),
        n0 = path0.getTotalLength(),
        n1 = (path1.setAttribute("d", d1), path1).getTotalLength();

    // Uniform sampling of distance based on specified precision.
    var distances = [0], i = 0, dt = precision / Math.max(n0, n1);
    while ((i += dt) < 1) distances.push(i);
    distances.push(1);

    // Compute point-interpolators at each distance.
    var points = distances.map(function(t) {
      var p0 = path0.getPointAtLength(t * n0),
          p1 = path1.getPointAtLength(t * n1);
      return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]);
    });

    return function(t) {
      return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1;
    };
  };
}
path {
  fill: none;
  stroke: #000;
  stroke-width: 1.5px;
}
<script src="//d3js.org/d3.v3.min.js"></script>

编辑:你在评论中说你正在使用D3 v4.x.在这种情况下,您会有一些变化:

path.transition()
    .duration(2000)
    .ease(d3.easeLinear)
    .attrTween("d", pathTween(d1, 4))
    .on("end", function() { d3.select(this).call(transition, d1, d0); });

它们是:d3.easeLinear而不是"linear".on而不是.each

以下是blockbuilder:http://blockbuilder.org/GerardoFurtado/90f1d1040bcfd3b4172f3965efab2b37