我有一个使用.transition()进行动画处理的矩形,它需要5秒钟(.duration(5000))。我想知道是否有任何方法可以在这5秒内指定一个百分比,所以动画是从该百分比开始执行的。
例如,对于5秒的持续时间,如果我指定50%的值,我希望动画从对应于2.5秒(5%的50%)的值开始。那可能吗?
这是我的代码:

d3.select("#visualization").append('svg');
var vis = d3.select("svg").attr("width", 800).attr("height", 614).style("border", "1px solid red");

var rectangle = vis.append("rect").attr("width", 100).attr("height", 70).attr("x", 0).attr("y", 50);

rectangle
  .transition()
  .duration(5000)
  .attr("x", 250)
  .attr("width", 100)
  .attr("height", 100)
  .attr("opacity", 0.5)
  .attr("fill", "red");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="visualization"></div>

最佳答案

对于线性缓动,只需更改持续时间并传递自己的ease函数即可,该函数很简单:

const percentage = 0.5;//here, a value between 0 and 1

selection.transition()
    .duration(5000 * (1 - percentage))
    .ease(t => percentage + t * (1 - percentage))
    //etc...
如果您还有另一种放松,则将修改后的t值传递给它。例如,使用d3.easeCubic:
.ease(t => d3.easeCubic(percentage + t * (1 - percentage)))
这里的逻辑很简单:正如API解释的那样,“对于过渡处于事件状态的每个帧,它使用介于0到1之间的缓和t值调用补间。因此,我们的函数仅使过渡从percentage的缓和值开始,并且t值(从0到1)用于指示必须添加的剩余量(1 - percentage)的分数。当t = 1时,整个表达式percentage + t * (1 - percentage)等于1。
这是演示。首先,您的常规过渡:

const vis = d3.select("body").append('svg').attr("width", 800).attr("height", 614).style("border", "1px solid red");

var rectangle = vis.append("rect").attr("width", 100).attr("height", 70).attr("x", 0).attr("y", 50);

rectangle
  .transition()
  .duration(5000)
  .attr("x", 250)
  .attr("width", 100)
  .attr("height", 100)
  .style("opacity", 0.5)
  .attr("fill", "red");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

现在使用percentage = 0.5,所有内容(位置,不透明度等)都从原始转换的50%开始:

const vis = d3.select("body").append('svg').attr("width", 800).attr("height", 614).style("border", "1px solid red");

var rectangle = vis.append("rect").attr("width", 100).attr("height", 70).attr("x", 0).attr("y", 50);

const percentage = 0.5;

rectangle
  .transition()
  .duration(5000 * (1 - percentage))
  .ease(t => d3.easeCubic(percentage + t * (1 - percentage)))
  .attr("x", 250)
  .attr("width", 100)
  .attr("height", 100)
  .style("opacity", 0.5)
  .attr("fill", "red");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

最后,使用percentage = 0.8。因为这是三次放松,所以不透明度/运动即将结束:

const vis = d3.select("body").append('svg').attr("width", 800).attr("height", 614).style("border", "1px solid red");

var rectangle = vis.append("rect").attr("width", 100).attr("height", 70).attr("x", 0).attr("y", 50);

const percentage = 0.8;

rectangle
  .transition()
  .duration(5000 * (1 - percentage))
  .ease(t => d3.easeCubic(percentage + t * (1 - percentage)))
  .attr("x", 250)
  .attr("width", 100)
  .attr("height", 100)
  .style("opacity", 0.5)
  .attr("fill", "red");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>


PS:不相关,请使用style代替attr设置样式。您会看到,在您的特定情况下,它会产生巨大的变化。

10-07 23:20