Jump to content
Search Community

Dynamically update, same speed

mikel test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi @GreenSock,


I found this code snippet with the comment (here).

"It sounds like you're trying to make it travel at a certain constant velocity and dynamically update the destination value, right? "


var myElement = document.getElementById("yourID"); //the element to tween
function move(element, y, speed) { //"speed" is pixels per second
    if (!element._gsTransform) { //forces GSAP to parse the transforms...only necessary the first time.
        TweenLite.set(element, {y:"+=0"});
    return TweenLite.to(element, Math.abs(y - element._gsTransform.y) / speed, {y:y, ease:Linear.easeNone, onComplete:on_stop, onCompleteParams:[this.rNum]});
//now you can just call this method anytime and it'll adjust things on-the-fly
move(myElement, 1000, 200);


Unfortunately, it does not work the way I expect it: same speed ...


See the Pen jQrJYQ by mikeK (@mikeK) on CodePen

What's wrong with my code or my expectation?


Best regards




Link to comment
Share on other sites

All three add statements execute at the same time and they calculate the duration based on current position of the element, so 3rd statement goes to 50 pixels in 0.5 seconds but by the time that tween executes distance has changed. Though what you are expecting is that it should calculate duration after first two tweens complete.


If you want to construct timelines like that, maybe you can use addPause method and move your logic inside it.




See the Pen KrMOQd?editors=0010 by Sahil89 (@Sahil89) on CodePen


  • Like 2
Link to comment
Share on other sites

Problem: When you create any timeline, all the statements execute at the same time. So GSAP creates tween with target and duration, in your case duration is important but it gets calculated for all three tweens based on target element's current position. So when 3rd tween is created element is at position 0 and it goes distance of 50 pixels which is absolute value. But because it is a 'to' tween, the element goes from whatever the current position is to the target position and by the time 3rd tween plays, distance has changed but because it was created already, the duration for it was set to 0.5.


Solution: You need some way to calculate duration based on actual position, to get around that you need to use addPause method.

  1. When you call addPause during a timeline, it will pause timeline at given position parameter.
  2. I am passing the function that will get called when timeline pauses, parameters that we pass to move function and scope. I am passing current timeline as scope to keep things organized.
  3. Inside the move function, you do same calculations as before but this function gets called while timeline is playing.
  4. Because of that the tween gets created based on what is actual position of the element, so your calculation for duration is live and correct.
  5. Once your tween/timeline completes inside the addPause function, we can resume the main timeline by using onComplete callback.


If you know all target positions then another solution would be to calculate your duration based on target value of previous tween instead of getting current position of the element. Because I think original question was for scenario where target position would change based on user interaction.


See the Pen eQdOxL?editors=0010 by Sahil89 (@Sahil89) on CodePen


  • Like 2
Link to comment
Share on other sites

Hi @Sahil,


Your explanations are very helpful. But frankly, as js novice, it's not easy.

My goal:

  • To keep the moves / drives variable in relation to the window width.
  • These should then be integrated into a master timeline.
  • And finally, to use this concept:
// based on https://codepen.io/osublake/pen/3f8b76a324743b25b786026d5b711fff
var requestId = null;

window.addEventListener("resize", function() {
  if (!requestId) {
    requestId = requestAnimationFrame(resize);

function buildTimeline(progress = 0, reversed = false) {
  // the master timeline


function resize() {
  ww = window.innerWidth;
  vh = window.innerHeight;
  var progress = master.progress();
  var reversed = master.reversed();
  buildTimeline(progress, reversed);
  requestId = null;


My understanding of your help and plenty of trial and error has led me to this result:


See the Pen JeRJVK by mikeK (@mikeK) on CodePen


The first two steps work.
However, in the third step, I do not know how to 'include the move func' - updating the relative positions:


See the Pen GwjyNG by mikeK (@mikeK) on CodePen


Is this third step feasible?


Kind regards




Link to comment
Share on other sites

That's tricky mainly because you want to change the duration of the tweens but changing duration of tweens that are on active timeline create weird effect because you are stretching timeline's duration so it just stretches from same start position. You can't add these tweens to any timeline, only thing you can do is change timescale of whatever that timeline is but still going to be tricky situation if it is complex animation.


Here is a bit more simplified demo,

  1. now instead of animating element I am animating another object between 0 to 1.  Because animating actual element gets too tricky.
  2. And then using the onUpdate call to update position of element.
  3. When move function is called I am creating new tween and assigning it to currentTween variable.
  4. I am using another variable, currentVars. To record start and end position that I need to create new tween on resize.
  5. onResize if currentTween is actually active, then kill currentTween. Then call move function to create new tween.


See the Pen GwjGVZ?editors=0010 by Sahil89 (@Sahil89) on CodePen


See if this works for you, I am not sure if there is better way but if I come up with something then I will let you know.

  • Like 2
Link to comment
Share on other sites

Happy to help! Here is less complex solution using invalidate. Instead of using another object, I am animating element directly. On resize, activeTween gets invalidated to record new values. I have left some comments for key parts but this is far less complex and better for performance because we are not creating new set tween on every frame.


See the Pen KrNPem?editors=0010 by Sahil89 (@Sahil89) on CodePen


  • Like 3
Link to comment
Share on other sites

Hi @Sahil,


It's really fun to play with your 'toy'.


See the Pen LXbNov by mikeK (@mikeK) on CodePen


Since the master is not a 'normal' timeline, an overlap of tweens (before, behind) with the move timeline is not feasible (pause is pause!).

But I found a way to integrate action during the move. The learning curve is increasing.


Thanks a million - I'm busy ...


Best regards


@Carl: EGON is running fast now - according to the order from the director.



  • Like 3
Link to comment
Share on other sites


Since the master is not a 'normal' timeline, an overlap of tweens (before, behind) with the move timeline is not feasible (pause is pause!).


If you think about it, what you are trying to do is to create timeline for user interaction. Your character is free to move around so you can't put him in timeline. Instead you should treat it as interaction. When he reaches certain spot then trigger animation related to that position. Timeline is not best option for this.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...