Jump to content
Search Community

kill vs clear

Gabriel 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

Could someone explain the difference between using kill() or clear() on a timeline? That is, besides kill() being able to kill individual tweens, lets assume we're using kill() on the entire timeline itself. The documentation is unclear (use kill to kill a tween; define kill?). If they're the same, then why use clear(), other than the timeline instance being preserved? And, I'm interested if either resets the positions of elements in a timeline to their beginning position, or what the best way to go about that is? Thanks!

Link to comment
Share on other sites

kill() literally kills the entire timeline, as if you'll never use it again. Dead. Caput. It gets removed from its parent timeline as well. clear(), on the other hand, simply empties all the children out of the timeline. So the timeline still exists and stays on its parent timeline. 

 

If you want to return all the child tweens/timelines to their starting points, you can simply seek(0) or totalTime(0) on that timeline which is the same thing as rewinding it completely. 

 

Does that "clear" things up? (pardon the pun) ;)

Link to comment
Share on other sites

Yeah it does. Nice pun, lol. Pretty much how I would expect it to work. I guess I was more interested in the aspect of resetting tweens to their starting point.

I haven't set up any definitive tests to isolate the problem, but I was having some problems prior with pausing a timeline who's tweens were in a container with "display:none" set. I thought I read somewhere that GSAP wouldn't animate non-displayed tweens, but Firebug showed them tweening away in the background. When I'd display the container, the animation would be running fine, from whatever point in the timeline it had reached. But whenever I'd pause the timeline and then tl.seek(0) or tl.play(0), the element positioning would become all screwy and wouldn't animate properly when it started playing again after displaying it.

So that's related because I was working on a way to destroy and rebuild the timeline each time I displayed the container, so positioning would be correct. Seek wasn't doing the job for me for resetting the original element positions, so I'm exploring solutions

 

I'm also getting three different animation results for FF/chrome/IE when it comes with dealing with display:none issues, for this animation and others. For some transitional animations, I'm grabbing coordinates for beginning/ending positions by toggling display:none/block back and forth, and animating things into place. It's only working right in FF, chrome and IE both are giving me issues. But I haven't even began to look into debugging those animations yet.

 

To explain what I mean by transitional animations: For example, the page footer is always displayed, and it's position is dictated by page elements above it, because it's in the flow. If I'd like to display a hidden element above it, it would be nice to animate the footer going to the new position first, and then animate the div from a height of zero, growing downward to meet the footer. To get the new footer position on any given page, I have to toggle the hidden element display on and off before animating. I'm actually working on much more complex transitional animations, but I'm only getting good results in FF so far, with IE amazingly doing better than Chrome. But unless this rings a bell for you, I'll have to get back to you later with more specifics, or a Codepen or something

Link to comment
Share on other sites

At the moment I'm trying to build a resizing tool for a banner animation.

 

The animation contains hundreds of elements, created with jQuery on the fly. So after a screen resize, it's very costly to remove all the elements and remake them again with new dimensions.

 

So the idea is: I changed my building function to not create new elements if they already exist, using ID's and a counter to check. But my building function still set's their dimensions and positioning by swapping the existing element into the same function in place of a newly created element. So, to resize:

 

resize(width,height,callback,tl)

 

Which will seek(0) the animation to reset everything, empty the timeline, resize the container, run the callback which rebuilds the animation, and then play it from it's prior playhead position. BUT: it's not working at all. If I pause it before rebuilding, and inspect the elements in Firebug, they are littered with transforms even after doing seek(0). So playing it runs a new animation on pre-transformed elements, and it's a big mess. I can't seem to reset the damn things.

 

And I'm assuming that it's because the FROM tweens are immediateRender:true, so after doing a seek(0), they are immediately in their "from" positions. I need immediateRender:true set, it's not an option to turn it off. So how can I put the elements back in place without destroying and rebuilding?

Link to comment
Share on other sites

I didn't realize you were asking to clear all inline styles - I thought you wanted them returned to their starting values from the tween. you can clear any of them or all of them using the clearProps special property, like:

TweenLite.set(element, {clearProps:"all"});

//or to only clear transform and opacity:
TweenLite.set(element, {clearProps:"transform,opacity"}); 

I'm very interested to see an example of what you described with all the transforms being messed up after you seek(0). I can't imagine how or why that would happen. Any chance you could post a very simple codepen or jsfiddle that demonstrates the issue? Seeking back to 0 should always revert the values to their starting places (at least the starting place of those particular tweens/timelines). 

  • Like 2
Link to comment
Share on other sites

Yeah, that's a handy feature. It's ideal for setting inline values to their prior values. I never noticed it since it's buried in the CSSPlugin documentation. Thanks, I'll have use for it later. Although for my banner animation, attr('style','') will work, and is about 10% faster after testing, but that's a special case scenario with potentially thousands of elements.

 

Although, It would be handy to be able to use clearProps on a timeline and have it reset all it's animation targets for convenience. Personally, I think it's logical to add it as a flag for .kill(). When you want to destroy an animation after you're done with it, it makes sense that you may want to throw out the baby with the bath water and return everything to the pre-animation state, to kill any changes that were made as well.

 

Yeah, when I get back to that part I'll have to see if I can reproduce it in a Codepen. I have to focus on one thing at a time for now, so I'll get back to you on that. Thanks

Link to comment
Share on other sites

OK, here's one of the kinds of problems I'm having. I can't figure out where to begin testing, because I'm not sure what's causing the problem.

 

I trimmed out most of the fat out of this codepen, the non-related stuff. It creates the animation which works fine, but then when it clears it and rebuilds it using the same function it did the first time, suddenly it doesn't want to work. I set a timer to change the size after 5 seconds, to show before and after. After resizing, you can notice right away that it's no longer tweening the rotation:

 

See the Pen FdhGg by seraphzz (@seraphzz) on CodePen

 

I've been scratching my head at this for hours. Everything works as far as I can tell. I'm going to redo some of the stuff, like using an object rather than a switch, but despite some cosmetics everything seems to work fine, even on my much larger animation. Just, not after rebuilding though, and I don't see why.

Link to comment
Share on other sites

What kills me is that I have a much larger animation and much more robust version of the tool in that codepen. With text, images, tons of layers, complex animations, and the tools to manipulate them easily... After the resize, just about the whole animation seems to look fine, except the layer rotation no longer works, but everything else looks fine! I hope someone can spot a problem...

Link to comment
Share on other sites

I think I see the problem. You set up your timeline with a from() rotation tween, so your element will go from -720 to whatever it currently is at the time you set up that tween (zero initially, of course). Works great the first time, but then when you seek(0), it of course rewinds that tween to its beginning value which is -720 in your case (remember, it's a from() tween). In other words, rewinding your timeline correctly sets rotation to -720. 

 

Then, when you run your code again, you're doing the same thing - setting up a from() tween in your timeline that goes from -720 to whatever it currently is, and this time it's already at -720 because that's what it was correctly set to when you did the seek(0) on your timeline. 

 

See the issue? GSAP is doing exactly what it's supposed to. So you've got 3 options:

  1. Use a fromTo() tween so that you can define the starting and ending values
  2. Or use a set() to force rotation back to 0 when you rewind the timeline or just before you do your from() tween.
  3. Or delete the _gsTransform property of the element when you clear its style so that no transformations are remembered. Like "delete element._gsTransform" (or manually reset its rotation property to 0)

Does that clear things up for you? 

Link to comment
Share on other sites

Not really. I thought clear() is supposed to empty the whole timeline, and either using clearProps or clearing the style attributes would remove any changes to the elements. Where is _gsTransform even stored? The timeline or tween instance? And doing this for potentially thousands of elements in a loop seems inefficient. So I'm stuck trying to completely revert the timeline to an empty state without destroying it so it can be reused, and removing any changes to any elements. This seems like such a simple thing, I'm perplexed why this seems so complicated

Link to comment
Share on other sites

Sorry about any confusion/frustration. Let me try to explain...

 

CSS3 transforms are unfortunately all crammed into a single property - "transform" (or a vendor-prefixed flavor thereof), but one of the big benefits of GSAP is that it allows those to be animated independently, with completely different timings/eases/whatever (try doing that with regular CSS3 animations - it's impossible). The only way to do that is to store the data distinctly, so we simply attach a property to the element itself, named _gsTransform and tuck the values in there. That way they can be accessed by any tween anytime in order to render things correctly and maintain harmony.

 

The other reason this is necessary is because there are bugs in several browsers that cause the calculated css values to be improperly reported, so it's important that we maintain state using our own object like this. The css can't be trusted to persist. The transforms are the ONLY things we need to do this for. 

 

So that's why it doesn't help if you clear out the element's "style" inline values using your jQuery attr("style","") call. That doesn't delete the _gsTransform object that GSAP attached. 

 

And again, the GSAP stuff is doing exactly what you were asking it to in terms of rewinding the timeline to the beginning - it's just that you wrote your code such that the beginning of the animation would have the object at rotation:-720. 

 

When you clear() a timeline, that doesn't mean that all the tweens suddenly revert everything (that could be catastrophic). It just means it removes them from the timeline so that the playhead no longer causes them to render. Think of it like a cassette player - when you eject the cassette it doesn't rewind it too or cause the cassette itself to erase its music. 

 

clearProp:"all" literally just clears all the values in the element's inline css styles. That was working perfectly too, just like jQuery's attr("style",""). The only thing that didn't wipe out (and it shouldn't) is the _gsTransform object with its values. Again, those must be handled distinctly in order to work around browser bugs and to allow each type of transform (rotation, scale, skew, x, y, etc.) to be handled distinctly in your animations. 

 

You shouldn't have to loop through all your elements and do some strange time-consuming voodoo magic on them - you can simply replace your from() tween with a fromTo() or add a single TweenLite.set() line just beforehand. I provided 3 solutions above for you that hopefully won't be very costly at all. Did none of those options work well for you? 

Link to comment
Share on other sites

Thank you for that in depth explanation. I had no idea that gsap was attaching information to my elements that wasn't visible to me in firebug.

 

Since this data is attached to the dom elements themselves, is it correct that it persists when the timeline is killed? I mean, it's used internally for tracking properties in gsap and isn't actually used by the browser (the browser uses "transform"), so I guess it's confused why the information would stay attached after it's no longer needed. It seems if you kill all tweens on an object and time passes by, then gsap would have to recreate this tracking data based on the object's new position, because it can't be assumed that it's css and transforms haven't changed. Wouldn't manually changing an element's rotation, inline or by changing it's class style, therefore screw up gsap's ability to animate it?

 

It sounds like deleting this object is my best option, because I'm trying to create a wrapper for recreating the timeline whenever the browser is resized, and I don't want the user to have to have to use a series of fromTo's or set's to account for the plugin's behavior. They should only need focus on creating a simple a-z timeline, and let the plugin handle the resizing functionality automagicaly. Even performing set on each element beforehand is not an option, as all elements won't pass through the constructor, and there's no point between element creation and timeline insertion for the plugin to hook into.

 

It's still odd to me though. I understand why you say this object is created and it's purpose, but this isn't the only instance I'm needing to revert an element to be animated again later from a different location. The website is fluid/responsive, with many animated transitions, and browser resizing should not break any of these animations. So in my mind, what I'm doing seems common place stuff for a website like this. Releasing an element from memory seems an easier step than relying on fromTo's for fluid inline elements. Is there any plans to add a function to automate this? You could say, a "forget" function? I'm surprised I haven't seen this documented either, unless I missed something

Link to comment
Share on other sites

I think this is perhaps a difference in thinking from an animation platform born in flash to animating a website. In flash I would expect gsap to maintain constant control, but with dom elements there are so many things happening between animations, and gsap can't be there every step of the way

Link to comment
Share on other sites

You should have no problem seeing the data in debugging tools - I can see the _gsTransform stuff in Chrome Dev Tools and I assume Firebug is the same. 

 

I understand your frustration with the seemingly persistent data, but let me explain the factors that I had to consider:

  1. Speed. This is absolutely imperative in any good animation platform because animations are so demanding. Reparsing the matrix data on each update would be very costly. 
  2. Flexibility. Since various tweens could be controlling various parts of an element's transforms (like one rotation tween and a different scale tween and a 3rd positional one), it was imperative that there be a centralized place to read/store that data, hence the _gsTransform object attached directly to the element. That's much better than each tween creating its own and then trying to talk to each other about which things are being edited. 
  3. Compatibility. In certain scenarios, browsers don't correctly report an element's transform data at all, so if I followed your advice to always re-parse the css data every time a new tween starts, you'd get funky behavior in a few situations (not common, but enough to be annoying). For example, if you rotate to 120 degrees and then later you want to rotate to 90 degrees, the browser might report the matrix as being 0 degrees, so you'd suddenly see the element jump from 120 to 0 degrees and then animate to 90. Again, that has nothing to do with bugs in GSAP - it's a browser bug. One of the reasons people like using GSAP so much is that it works around a lot of those nasty browser bugs for them, so it "just works". 

    The other thing to note about re-parsing the computed style matrix data that the browser spits back is that it cannot accurately report rotations that are beyond 360 degrees. So imagine if you rotate to 720 and then you want to rotate to 700. You'd expect it to just rotate 20 degrees backward, right? But no, if we parse the raw matrix data from the browser, it's literally impossible to interpret that it was rotated 720 degrees, thus it would be interpreted as 0 degrees to start, and instead of rotating 20 degrees backwards, it would rotate 700 degrees forwards. 

So if I implement your suggestion, it would slow things down and be less flexible and have compatibility issues, plus after rotating beyond 360 degrees (or -360 degrees) it would lose state and animate in a way that folks probably wouldn't expect. 

 

Based on your responses, I'm still concerned that you didn't understand my explanation regarding why things stay rotated after you rewind and kill() the timeline (and why that's definitely the correct behavior). It has nothing to do with GSAP's roots in Flash. It's doing exactly what you're telling it to do - you created a tween that has the element rotated 720 degrees at the VERY BEGINNING of the timeline. So rewinding it correctly puts it back at that rotation.

 

You seem to be under the impression that the solutions I offered would somehow cause performance issues or be a massive headache to implement, but I don't understand why. It's literally changing maybe one line of code (unless I'm totally misunderstanding you which is entirely possible). 

 

If you're looking for one line of code to clear everything including transforms, here it is:

TweenLite.set([all_your_elements], {clearProps:"all", x:0, y:0, scale:0, rotation:0});

If you're doing 3D transforms, you can add those in there too. And if you are going to be applying transforms via css instead of GSAP, and then you want to force GSAP to re-parse them after you've already tweened them with GSAP (unlikely), you can delete the _gsTransforms property of the element, but again that's extremely uncommon that anyone would need or want to do that. 

Link to comment
Share on other sites

Thanks for all the explanations. I kind of feel bad that I'm taking up so much of your time that you could spend on more productive ventures.

 

I agree with you completely in terms of performance, and I'm fully understanding you. And I agree gsap performs as desired for common use cases. I wouldn't want to change this default behavior, especially as you've explained it. I do believe a future "clear/forget element" function would be a good addition, and would also add that this is kind of what I'd expect clearProps to do. But I understand that's a cssPlugin feature, so it affects the scope of that plugin, but would expect a tweenlite counterpart. Someone recognized the need for it, so it's a matter of consistency. But personally I don't even need it, as you've given me plenty of information to create it myself, thanks.

 

I know my needs might not seem common, but I assure you they're practical. I'm not sure if you understood what I'm doing. For a casual javascript user who wants to make a banner animation using CSS transforms, gsap makes it a breeze with entry level skills. But doing a fullscreen animation on a responsive width website becomes a maze of calculations on top of calculations to give a consistent look. This is the problem I'm solving. You just wrap your a-z animation in a function using a simple API for creating any dom element using relative sizing and placement, and the plugin automatically handles resizing it so it's identical at any size, with the added benefit of cool out of the box animations included. Recreating the timeline is simple and fast, but recreating the dom elements on each resize would be horribly slow, therefore I have to recycle and reset those elements. Hence, this is a very practical use case.

 

Thanks for all the help, I got what I need to finish it :)

  • Like 1
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...