Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If a transition lasts n seconds is it possible to start it at a specified percentage of that time?

I have a rectangle that is animated using .transition() and it takes 5 seconds (.duration(5000)). I want to know if there is any way to specify a percentage under those 5 seconds, so the animation is executed from that percentage on.

For example, with a duration of 5 seconds, if I specify a value of 50%, I would like the animation to start from the values corresponding to 2.5 seconds (50% of 5). Is that possible?

This is my code:

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>
like image 210
yavg Avatar asked Sep 23 '20 13:09

yavg


Video Answer


1 Answers

For a linear easing, just change the duration and pass your own ease function, which can be as simple as:

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

selection.transition()
    .duration(5000 * (1 - percentage))
    .ease(t => percentage + t * (1 - percentage))
    //etc...

If you have another easing, pass the modified t value to it. For instance, using d3.easeCubic:

.ease(t => d3.easeCubic(percentage + t * (1 - percentage)))

The logic here is simple: as the API explains, "for each frame that a transition is active, it invokes its tweens with an eased t-value ranging from 0 to 1". Therefore, our function just makes the transition starting at the eased value of percentage and the t value, going from 0 to 1, is used to indicate the fraction of the amount remaining (1 - percentage) that must be added. When t = 1 the whole expression percentage + t * (1 - percentage) equals 1.

Here are the demos. First, your regular transition:

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>

Now using percentage = 0.5, everything (positions, opacity etc...) starts at 50% of your original transition:

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>

Finally, with percentage = 0.8. Because this is a cubic easing, the opacity/movement are almost ending:

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: not related, use style instead of attr for setting styles. You'll see that, in your specific case, it makes a huge difference.

like image 183
Gerardo Furtado Avatar answered Oct 30 '22 23:10

Gerardo Furtado