Jump to content
Search Community

Get array of resulting values

swampthang 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

Wondering if there is a way to get an array of values for each frame of a tweened object. I'm familiar with the getTweensOf method for TimelineMax and TweenMax but that just returns the tween setup values. I need to be able to loop through the timeline without having to actually run it in the DOM. So, for example in the codepen, I'd like to be able to capture an array that contains the x value for each frame in the timeline without having to reposition the timeline in order to get the values. In other words, without having to use a DOM selector and extract the _gsTransform value after repositioning the timeline.

 

Is there a way to do that built in to GSAP?

See the Pen YQRrvj by swampthang (@swampthang) on CodePen

Link to comment
Share on other sites

Came up with a hybrid way of getting the values without having to run the timeline in real time. Was trying to avoid actually seeing the timeline run. I'm still having to process the timeline and snag the values but it happens so fast you don't notice it. Would still love a way to do this without having to run the timeline to get values from the dom.

 

See the Pen jwQGgq by swampthang (@swampthang) on CodePen

 

Link to comment
Share on other sites

Those values are completely dynamic, based on the timing in the browser. Think of it kinda like being "resolution-independent" - GSAP's ticker tries to run at 60fps (whenever possible) but the actual time between ticks varies (dependent on the browser, what else is going on in the main thread, etc.). So it isn't as if GSAP can just say "here's an array of all the values over the course of the entire tween at one time." 

 

But don't worry, I think I've got something that'll work for you...

function summarizeTweenValues(tween, fps) {
        fps = fps || 60;
        var modifiers = {}, //we're piggy-backing on the ModifiersPlugin functionality to make it simple to record values on each render
            results = {}, //stores the results in an array for each property of the tween, like results.x = [0, 100, ...]
            l = tween.duration() * fps,
            getModifier = function(a) {
                return function(value) {
                    a.push(value);
                    return a[0]; //always return the initial value so that the DOM doesn't change at all - we're only recording the changed value in the results array.
                };
            },
            vars = tween.vars.css || tween.vars,
            p, i;
        for (p in vars) {
            results[p] = [];
            modifiers[p] = getModifier(results[p]);
        }
        vars.modifiers = modifiers;
        vars.immediateRender = true;
        tween.invalidate();
        for (i = 0; i <= l; i++) {
            tween.seek(i / fps);
        }
    delete tween.vars.modifiers;
    tween.invalidate().seek(0);
    return results;
}
var tween = TweenLite.to("#box", 4, {x:500, ease:Power1.easeInOut});
var values = summarizeTweenValues(tween, 60);
console.log(values.x);

 

It's leveraging ModifiersPlugin an a unique way, for recording the values as we iterate through the tween at various times. It always sets it to the initial value, though, so in terms of the DOM there isn't any change during this time. In other words, if x starts at 0 and the tween tries setting x to 50, it'll only record that in the array but set x on the DOM element to 0. 

 

Does this help?  

 

See the Pen jwQZqj by GreenSock (@GreenSock) on CodePen

 

  • Like 1
Link to comment
Share on other sites

That's awesome, Jack! I've added it to my version, replacing what I had. Question for you - will the array of values line up with each frame? I'll be working with multiple timelines that have multiple tweens and objects and the nested timelines will have different start times and durations. I'm thinking for each tween, I should be able to get the tween's startTime relative to the master timeline and iterate through each value in the array and relate those frame numbers as offset the frame numbers of the master timeline for aligning time placement of the rendered tweens relative to the master timeline. Right?

 

See the Pen JJeLmz by swampthang (@swampthang) on CodePen

 

Link to comment
Share on other sites

I'm a bit concerned that you might be misunderstanding a fundamental timing concept in GSAP - that whole "resolution independence" thing and how tweens render their values. It's not like a video where there are X number of pre-rendered frames. Instead, it calculates the necessary value(s) on-the-fly. It's completely dynamic. This is a *good* thing in almost every case. 

 

Unless you specifically use the useFrames feature in GSAP and define all of your durations that way (which is extremely rare), there is no concept of "frames" at all. 

 

At 60fps, there's about 16.67ms between each "tick" in a perfect world. A "tick" updates the playhead and triggers the render. But what if the browser is doing 500 different things and takes 40ms between two ticks at one point? If you're using pre-calculated frame-based values, it's going to push EVERYTHING back and slow...things....down. If there's a big drag and the browser can only render every 70ms or something, can you see the problem? Durations won't be honored. Things slow down. Timing gets thrown off. 

 

GSAP doesn't do things that way - it dynamically adjusts and renders the values according to precisely where the playhead happens to land at that moment. Again, this is a very *good* thing. It makes things smoother and more predictable. 

 

The same goes for how timelines work. There are no "frames" where everything must align. It's not as if you're only "allowed" to place tweens at perfect 16.67ms increments on the timeline (in terms of their startTimes). Two tweens could be positioned 0.0000364 seconds apart - GSAP doesn't care. 

 

And keep in mind that plenty of screens don't run at 60hz - they may play at half that. My Mac actually has one screen running at 60fps and another at 30fps. If I drag the browser from one to the other, it literally alters how frequently the browser emits the requestAnimationFrame. GSAP handles it beautifully, but imagine if we enforced a strict "frames" concept - it'd mess everything up if all the child animations could suddenly only be at 33.33ms increments (frames). 

 

In GSAP, if the playhead happens to land at 0.000241 seconds into a tween, that's EXACTLY where the values will be rendered. "Resolution independence". 

 

Does that clarify things? 

 

What exactly is your goal with all these pre-calculated "frames-based" values? I'm a tad concerned that it might be heading down a path that won't be beneficial. 

 

 

  • Like 2
Link to comment
Share on other sites

Thanks for the clarification, Jack. To answer your question regarding what I'm trying to accomplish - creating a tool (using Electron) that will do a Ken Burns effect with images. One image is being animated at a time - width, height, x and y. To export these animations, I'm moving the playhead forward one frame at a time and saving a copy of the image so that it forms an image sequence (img001.jpg, img002.jpg, etc). I'll then create a video from the image sequence using FFMPEG. I can tell FFMPEG what the framerate is and it will create the video accordingly.

 

I've actually been doing that kind of thing for other animations as well and haven't had any trouble with it being pretty accurate but I was having to actually move the playhead forward and snag the data. I've been using canvas and image blob's rendered from the current frame to an image sequence but here I'm just saving the state of a single image. 

 

I'm not too worried about things being perfect. I just want to be able to snag the settings at the current frame to save a copy of the currently animating image. That's why, in the original codepen, I was advancing one frame at a time to get the data. Was just hoping to be able to get the data without having to actually step through the timeline.

 

Looks like that's gonna do it. Have been able to export the video included cropping and zooming. Used FFMPEG to create the images and then compile them into a video. Seems pretty smooth too. Thanks for the help, Jack!

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