Jump to content
Search Community

Bezier curves with time value for each coordinate

chris24k 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 all,

 

I just started to learn GSAP and I really love it! There is something I need to do, which might be a bit too specific to be of anybody elses interest, but still I'd like to get some help on this one (there are several issues I'm dealing with).

 

The requirement is to have a timeline of fixed length, say 8 seconds. It needs to be controlled by a slider. During execution, some items will appear, move around and dissappear at specific times. None of these is to be expected to be visible at the beginning or the end of the timeline, although the timeline has to last a bit longer than the last tween, i.e. all items have reached their destinations after 6 seconds, but the timelines length has to be 8. In my current workaround I just append an empty Tween with a duration of 2 secs which doesn't change any values.

See the Pen wJmkK by anon (@anon) on CodePen

.

 

Now to my question. These animations need to be smoothed with bezier curves, but as far as I know one can only specifiy an array of values and a duration. How can I make sure, that the animated object will be at point x at time t, when the point distribution over time is not equidistant?

 

Looking forward to your answers :)

 

Thanks,

Chris

 

 

Other issues (not related to the main question):

  • Is there a better way to extend the timeline's duration (without affecting its timescale), other than the method I described (adding an empty tween)?
  • Can I set all Tweens in a Timeline to the same easeType at once?
  • I noticed, that my pen doesn't work on its first run. If you press restart or use the slider Everything works as expected. What did I do wrong?
Link to comment
Share on other sites

Hi and welcome to the GreenSock forums,

Looks like you are doing quite well, although insertMultiple() is an old and deprecated method from the v11 Flash days. We have new ways of accomplishing the same results but which MUCH less code. I'll get to that later.

 

Bezier Point Time

At this time the API does not have a way to expose at what point in time a tween reaches any of the points you provided in your array of points. From your description of the problem, I can see how this could be useful, but from what I know it would be a non-trivial endeavor. Someone else might be able to weigh in with more details or a solution... but I'm at a loss at the moment.

 

Is there a better way to extend the timeline's duration (without affecting its timescale), other than the method I described (adding an empty tween)?

 

 

What you are doing is fine. I see that you have a tween with a duration of 2 seconds at the end. Another approach is to add a 0-duration tween 2 seconds past the end of the timeline like so

 

var tl = new TimelineLite()


tl.to("#redBox", 1, {x:550})
  .to("#blueBox", 1, {x:550})
  
//add a dummy set 10 seconds past the end of the timeline
tl.set({},{}, "+=10")


alert(tl.duration()) //12

 

http://codepen.io/GreenSock/pen/lkyoh

 

TimelineLite's set() method (which creates a 0-duration tween) makes it pretty light on syntax

 

Can I set all Tweens in a Timeline to the same easeType at once?

 

 

No, there is not a default ease per timeline, BUT globally you can use 

TweenLite.defaultEase = Linear.easeNone
I noticed, that my pen doesn't work on its first run. If you press restart or use the slider Everything works as expected. What did I do wrong?

 

 

On further inspection your timeline was running, its just that your boxes both had visibility:hidden on them.

 

The reason for this is because you were creating 2 tweens with 0-second durations which technically completed as soon as they were created. The later tween which set visibility to hidden, literally overwrote (killed) the first tween so on first run visibility was hidden.

 

To avoid this just give each of your 0-second duration tweens a very very very short duration:

 

tl.insertMultiple([
  TweenLite.to("#redBox", 0.001, {x:100,y:100, ease:Linear.easeNone, visibility:"visible"}),
  TweenLite.to("#redBox", 1, {x:400,y:200, ease:Linear.easeNone}),
  TweenLite.to("#redBox", 1, {x:300,y:300, ease:Linear.easeNone}),
  TweenLite.to("#redBox", 1, {x:200,y:200, ease:Linear.easeNone}),
  TweenLite.to("#redBox", 1, {x:500,y:100, ease:Linear.easeNone}),
  TweenLite.to("#redBox", 0.001, {ease:Linear.easeNone, visibility:"hidden"}),
  TweenLite.to("#redBox", 2, { })
], 2, "sequence");

 

---

 

Back to my earlier comment about insertMultiple. Please make sure you are using the most recent js docs: http://api.greensock.com/js/

 

Click on TimelineLite and read up on the add() method, it can do whatever insertMultiple() and appendMultiplie() used to do and more. 

 

Also be sure to read up on TimelineLite's new methods like to(), from(), and staggerTo() as they allow you to do things very differently than we used to do in v11 Flash with append() and insert().

 

This video here should give you a good idea of how concise the new syntax is: http://www.greensock.com/sequence-video/

  • Like 2
Link to comment
Share on other sites

Thank you Carl for clearing things up. Really apprechiate your answers.

 

Its unfortunate, that this can't be done directly with bezier curves. I think I will try to preprocess the animation curve to get a set of points I can use for bezier. I'll let you know how it goes.

Link to comment
Share on other sites

Very nice.

 

Just want to let show you that you can reduce your GSAP code by a fair amount by chaining TimelineLite/Max to() and set() functions.

//I noticed that you were often using add()
timeline.add(TweenLite.to(target, duration, {vars}));

//when this would do the same thing:
timeline.to(target, duration, {vars});

When adding lots of tweens, it can really save a lot of work for your fingers;)

 

Also, instead of using a very small duration() for a to() tween, TimelineLite's set() works great.

timeline.add(TweenLite.to(target, 0.001, {vars}));
//same as
timeline.set(target, {vars});

I know I recommended the 0.001 duration thing previously, but that was because you were using insertMultiple at the time. The new set() method of TimelineLite creates a tween with a 0-second duration. 

 

I edited your pen with the new convenience methods and it looks like it is performing the same way:

 

var tlMain = new TimelineLite({onUpdate:updateSlider});
tlMain.add(tlRed, keyFramesRed[0].t)
  .set("#redBox", curvePointsRed[0], keyFramesRed[0].t - 0.001)
  .set("#redBox", {visibility:"visible"}, keyFramesRed[0].t)
  .set("#redBox", {visibility:"hidden"}, keyFramesRed[keyFramesRed.length-1].t)


  .add(tlBlue, keyFramesBlue[0].t)
  .set("#blueBox", curvePointsBlue[0], keyFramesRed[0].t - 0.001)
  .set("#blueBox", {visibility:"visible"}, keyFramesBlue[0].t)
  .set("#blueBox", {visibility:"hidden"}, keyFramesBlue[keyFramesBlue.length-1].t);

See it here: http://codepen.io/GreenSock/pen/jiuKd?editors=001

 

I know earlier I recommended add(), but that was really just to show how to replace he functionality of insertMultiple(). to(), from(), staggerFrom() and other new methods of Timeline can save you a ton of time.

 

Again, great job on all those Bezier calculations!

Link to comment
Share on other sites

This is a little off topic, but I just found something interesting. Thought I share, although it could be nothing, since I'm very new to javascript and haven't gotten around much yet...

 

Check this code:

var tlMain = new TimelineLite({onUpdate:updateSlider});
tlMain.add(tlRed, keyFramesRed[0].t)
  .set("#redBox", curvePointsRed[0], keyFramesRed[0].t - 0.001);

curvePointsRed[0] is { x: 100, y: 100 }, so these can be used as vars for the tween. That code works in the pen, but not in my environment. I looked into the sources

p.set = function(target, vars, position) {
    position = this._parseTimeOrLabel(position, 0, true);
    if (vars.immediateRender == null) {
        vars.immediateRender = (position === this._time && !this._paused);
    }
    return this.add( new TweenLite(target, 0, vars), position);
};

and it complans that vars.immediateRender is undefined, thus creating an error.

If I call the set method like this

var tlMain = new TimelineLite({onUpdate:updateSlider});
tlMain.add(tlRed, keyFramesRed[0].t)
  .set("#redBox", {x:curvePointsRed[0].x, y:curvePointsRed[0].y}, keyFramesRed[0].t - 0.001);

everything works.

 

I like being lazy, so using curvePointsRed[0] directly would be my first choice. Would it make sense for you to check for 'undefined' instead of 'null' inside of the set method? I guess the problem is on my side anyway, since it does work flawlessly in the pen. Maybe it's the fault of the closure compiler which i'm using, who knows...

 

 

Link to comment
Share on other sites

Yea it seems mighty odd that the same code is working in CodePen but not locally.

 

If curvePointsRed[0] truly is === { x: 100, y: 100 }, then it's also === { x: curvePointsRed[0].x, y: curvePointsRed[0].y }, so that change really should have no effect...

 

Have you checked what your compiler has done to the set method? And is there something wrong with the TweenMax.min.js file provided (or the CDN) to not just use that?

Link to comment
Share on other sites

I am using TweenLite.min.js and TimelineLite.min.js from cdn, but it doesn't make any difference, whether I use them or TweenMax.min.js or have them all locally in place. The compiled code doesn't look wrong (tried with WHITESPACE_ONLY and ADVANCED).

 

If I use keyFramesRed[0] instead of curvePointsRed[0] it works, so I guess it's because

keyFramesRed[0] = {x:100,y:100,t:2} // values assigned

and

curvePointsRed[0] = {
        x:bezier(all_those_params), // methods assigned
        y:bezier(all_those_params)
      }

Its either that, or something in my local setup, since the set function is the same in both versions.

 

But since the workaround works I'm not going to investigate any further for now as there is a deadline comming up soon. :?

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...