Search the Community
Showing results for 'overwrite'.
-
Welcome to the forums, @Kahlub! In GSAP 3, overwriting is false by default. You were creating conflicting tweens in this case - in the mouseenter you started a 3-second long animation but let's say the user moves their mouse off of it 1 second later, you're creating another 0.5 second animation of the SAME property of the SAME object, which of course works (both tweens are setting that property, but since the mouseleave was created later, it runs last, thus its values are what's seen while it's running), and then when that animation finishes the OTHER one is STILL RUNNING. So suddenly you see the jump. That's not a bug in GSAP - it's just a logic issue with your code. But don't worry, it's easy to fix. You have several options: 1) Just set overwrite: true on your tweens. That means that when the tween is created, it finds all other tweens of the same target and immediately kills them. No more conflicts! 2) You could manually accomplish that with gsap.killTweensOf(yourTarget) but I find it simpler to just set overwrite:true. 3) You could set the default overwrite mode to "auto" or true, like: gsap.defaults({overwrite:"auto"}); That will tell GSAP to automatically check the first time each tween renders and find any animations of the same property of the same target and kill just those pieces of the other tween(s). 4) You could create a single tween that you simply play()/reverse() in the mouseenter/mouseleave events. That's even more efficient (but GSAP is so fast it's not as if there's a performance problem with the way you're currently doing it - I just tend to be a performance nut). If you want the mouseenter animation to be longer, you can simply set the timeScale accordingly, sorta like: const animation = gsap.fromTo(...); //create your tween once, set paused:true animateIconEnter = () => animation.timeScale(1).play(); animateIconLeave = () => animation.timeScale(6).reverse(); Just an idea. Lots of flexibility Happy tweening!
-
Use auto. gsap.defaults({ overwrite: "auto" })
-
You can overwrite particular properties by passing them into overwrite instead of true. https://jsfiddle.net/492oqsth/ Side notes: You don't need to pass units into y. Pixels is the default. You should include the duration inside the vars parameter, not as the second parameter
-
Thank you so much for the hint, but I'm not going to be able to use this option, because I also animate X and Y in addition to Scale when I move the mouse. In any case, thank you. I used your decision in another part of the code, it helped me a lot. I have a question. Is there any way you can use it for the whole function "overwrite:true" and for a certain part "overwrite:false". I'm asking because I stopped working on this piece of code: https://jsfiddle.net/2b9fgxL0/ . Opacity doesn't work for some reason... If overwrite is removed, everything will be fine.
-
`overwrite: "auto"` didn't do the trick, unfortunately. I made 2 code sandboxes illustrating the issue. without issue https://codesandbox.io/s/gsap-v2-no-jump-bug-umw6x?fontsize=14 with issue https://codesandbox.io/s/gsap-v3-jump-bug-in-vue-3272l?fontsize=14 Interesting: when you remove `clearProps` from the v3 sandbox, the issue doesn't occur. So apparently I do not understand what clearProps is supposed to do or we really have gsap bug here. Nevertheless: even if the v3 sandbox illustrates the intended behavior, I'd argue this should be changed to the way it worked in v2. Thrilled to read if you disagree with that and why you made this change.
-
Hard to say without being able to test it. Try changing the default overwrite, and see it that helps. gsap.defaults({ overwrite: "auto" });
-
why is that? I really like the "old syntax"; I'm used to it, it's faster to type, easier to see at a glance what the duration is, etc. I will need to look into the `overwrite` solution; right now here in Germany shoulllld be sleeping time having to set where things are at the beginning of the timline would be really bothersome and be kind of a downgrade for me personally–
-
It's hard to say without the ability to see it for ourselves. Guessing somewhat blindly, it could be because the overwrite property has a different default in GSAP3. In GSAP 2 it was "auto" by default but in GSAP 3 it's false. You can test it by putting gsap.defaults({overwrite:"auto"}); to the top of your script. Side note, it's good to put the duration inside of the vars parameter.
-
Updated from v2 to v3. Now animations aren't smooth.
bradjdouglas replied to bradjdouglas's topic in GSAP
Zach, thanks for the quick reply! I updated the overwrite value to 'auto' like you said and it helped a bit, but there were still some funky things going on. I then realized - based on your 'if I don't scroll too quickly' comment - that I didn't have a way to stop the animation from going again and again. I added 'isAnimating' to my state and set it before running the masterTL and resetting after. That seemed to do the trick! Appreciate the help! -
Updated from v2 to v3. Now animations aren't smooth.
ZachSaucier replied to bradjdouglas's topic in GSAP
Hey Brad, cool site! Welcome to the forums. Your animations look pretty smooth to me (given I don't scroll too fast too many times right in a row - I think that's more of a logical error. Is that what you're referencing?). Is it a particular browser that's giving you trouble? or a part of the site's animation that it happens with? That's a bit of code to look through even though most of it is unrelated. Guessing somewhat blindly, I'd guess that it's because the overwrite property has a different default in GSAP3. In GSAP 2 it was "auto" by default but in GSAP 3 it's false. You can test it by putting gsap.defaults({overwrite:"auto"}); to the top of your script. P.S. Small note: "out" is the default ease, so you can just say "expo" instead of "expo.out" if you want to. -
overwrite is set to false in v3. You can set it to true or "auto". It was set to "auto" in v2. gsap.defaults({ overwrite: true }) $('.kareta-b').mouseenter(function(event){ gsap.to($('.kareta-b .pimg'), 1, { x:"-27%", y:"-18%", width:"331%", }); }); $('.kareta-b').mouseleave(function(){ gsap.to($('.kareta-b .pimg'), 0.7, { x:"-27%", y:"23%", width:"185%", }); });
-
The only way I can think of that would cause behavior like that is if your rollout/rollover tweens have different durations, such that one finishes before the previous one does. If you want overwrite:"auto" (the old default), you can simply set that as the default like this: gsap.defaults({overwrite:"auto"}); Technically yes, but if you load GSAP first and you're loading the files into a browser, the plugins will attempt to auto-register but it's still a good habit to get into (registering them) because when you're working in build tools/bundlers, tree shaking can bite you if you have zero references in your code to the plugins.
-
TweenMax.to('body', 0.4, { color:recklessFG, backgroundColor:recklessBG,overwrite: true }); I've found that since I updated, I've had to use overwrite:true as things that were in order were going out of order? I have a lot of rollovers that all impact a few divs... e.g. rolling over a piece of text changes the background etc. and hides text, and the rollovers can happen very quickly.
-
Forgot to mention, that yes, I'm using the window to make it global. This pattern makes sure it doesn't overwrite window.mySvg if it already exists. window.mySvg = window.mySvg || {};
-
Hello I did two codepens, the first one trying to use the track you gave me but I have to miss something. I tried to be more specific about how the site works. I got a result on the second codepen but the animations when they are on screen, have an infinite animation (up to off screen) I tried to pause the offscreen sections but without any result I looked at overwrite and clearProps but I don't know how to implement them properly https://codepen.io/CedGrvl/pen/LYYdePj?editors=1010 https://codepen.io/CedGrvl/pen/QWWmmqJ Thx Again
-
Quick links Half the file size of the old TweenMax! Simplified API Backward compatibility Timeline defaults that get inherited by child tweens Advanced staggers everywhere MotionPathPlugin (replaces BezierPlugin) New random(...) capabilities Get property values, with unit conversion capabilities New "effects" extensibility Keyframes Relative ">" and "<" position prefix Animate to a width/height of "auto" New "repeatRefresh" feature New SnapPlugin (included in the core) Access/control the global timeline translateX, translateY, rotate, rotateX, and rotateY aliases You can define units for x/y transforms Built as modern ES6 modules with exports 15 Utility methods Other improvements and changes How do I get it? What was REMOVED? Other notes Roughly Half the file size of the old TweenMax! No kidding! It retains virtually all of the old functionality while adding 50+ features (as you'll see below). Simplified API No more "Lite/Max" flavors. TweenMax, TweenLite, TimelineLite, and TimelineMax have all been consolidated into a single "gsap" object. So simple! For example: //simple tween like the old TweenMax.to(...) gsap.to(".class", {duration:2, x:100}); //create a timeline and add a tween var tl = gsap.timeline(); tl.to(".class", {duration:2, x:100}); Internally, there's one "Tween" class (replaces TweenLite/TweenMax) and one "Timeline" class (replaces TimelineLite/TimelineMax), and both have all of the features like repeat, yoyo, etc. When you call one of the gsap methods like .to(), .from(), etc., it returns an instance of the appropriate class with easily chainable methods. Duration is now defined in the vars object (the old syntax still works). This offers several benefits: Improved readability It fits much better with keyframes It allows default durations to be inherited (more on that below) You can use function-based values //OLD - duration was 2nd parameter TweenMax.to(".class", 1, {x:100}); //NEW - duration is now a property of the vars object gsap.to(".class", {duration:1, x:100}); Shortened string-based eases - less typing, more readable, and zero import hassles. Here's the new convention for all of the standard eases: //OLD ==> NEW Elastic.easeOut ==> "elastic.out" //or just "elastic" because ".out" is the default flavor Elastic.easeIn ==> "elastic.in" Elastic.easeInOut ==> "elastic.inOut" Elastic.easeOut.config(1, 0.5) ==> "elastic.out(1, 0.5)" //or just "elastic(1, 0.5)" //and the other configurable eases are much easier!: SteppedEase.config(5) ==> "steps(5)" SlowMo.ease.config(0.5, 0.8) ==> "slow(0.5, 0.8)" RoughEase.ease.config({points:40}) ==> "rough(40)" ExpoScaleEase.config(0.5, 3) ==> "expoScale(0.5, 3)" Backward compatibility The new GSAP even adjusts itself to accommodate the old syntax! There's technically no more TweenMax, TweenLite, TimelineLite, or TimelineMax, but they're all aliased so that the vast majority of legacy code still works, untouched! You don't have to rewrite all your code to use GSAP 3, but we'd recommend shifting to the new, more concise syntax for all your new projects. Timeline defaults that get inherited by child tweens You don't have to keep setting the same ease over and over again...or duration...or whatever. Just set defaults on the parent timeline: gsap.timeline({defaults:{ease:"back", duration:2}}) .to(".class-1", {x:100}) //inherits the ease and duration from the parent timeline! .to(".class-2", {y:200}) //this one too Any defaults you set this way will get pushed into every child tween - it's not limited to a certain subset of properties. Advanced staggers everywhere There's no need for the old staggerTo()/staggerFrom()/staggerFromTo() methods because you can add staggers to regular tweens: gsap.to(".class", { x:"+=100", duration:1, stagger: 0.5 //simple stagger of 0.5 seconds }); //or get advanced: gsap.to(".class", { x:"+=100", duration:1, stagger: { amount:2, from:"center", grid:"auto", onComplete: myFunction //define callbacks inside the stagger to make them apply to each sub-tween } }); Don't worry - the stagger methods are still there to support legacy code. MotionPathPlugin (replaces BezierPlugin) Turn any SVG <path> into a motion path! There's even a MotionPathHelper utility that lets you EDIT your own path interactively in the browser (club members only)! Watch the video: The basic playground from the video is at: https://codepen.io/GreenSock/pen/LwzMKL Features: autoRotate along the path. Offset by any amount. Animate from any spot along the path to any other spot using "start" and "end" progress values like start:0.3, end:0.8 to animate from 30% along the path to 80%. you can even loop around (like end:1.5) or go backwards! Align the target with any other element, like make a <div> line up perfectly with an SVG <path> or another element, and start animating along the motion path from there. Feed in an array of values to have it build a motion path that goes through them. It doesn't even have to be "x" and "y" values - it can be almost any property of the target. You can even control the "curviness" of that path that gets plotted. There are some utility methods attached to MotionPathPlugin like stringToRawPath(), rawPathToString(), getRawPath(), sliceRawPath(), transformRawPath(), and pointsToSegment(). MotionPathPlugin is in the public files, and the MotionPathHelper utility is a bonus plugin that comes with "Shockingly Green" memberships and up. New random(...) capabilities Define random values in a string as a range (like "random(-100, 100)") or an array (like "random([red, blue, green])") and GSAP will swap in an appropriate random value for each target! This makes advanced randomized effects crazy simple. You can even have the random number rounded to the closest increment of any number! For example: gsap.to(".class", { x:"random(-100, 100, 5)" //chooses a random number between -100 and 100 for each target, rounding to the closest 5! }); Or pass in an array-like set of values and GSAP will randomly select one of those: //randomly selects one of the values (0, 100, 200, or 500) x:"random([0, 100, 200, 500])" There's also a gsap.utils.random() function that you can use directly if you prefer. We'll cover the utility methods later. Get property values (with unit conversion capabilities!) gsap.getProperty("#myElement", "backgroundColor"); gsap.getProperty("#myElement", "x"); //works with GSAP transform properties too. This would return something like "100px" Pass a unit as the 3rd parameter and GSAP will return the value converted for you! gsap.getProperty("#element", "width", "em"); //returns the width in em units! (for CSS values only) If you omit the unit parameter, it will return a NUMBER (at least for simple values where parseFloat() returns a number). For example, a "top" or "left" or "x" property that's technically "20px" would be returned as 20 (no unit suffix) because it's so common to need to deal with numbers in animation. In practical use, it would be annoying to get values like "20px" back from getProperty() and have to manually wrap it in parseFloat(). But again, if you want the unit included, just pass in that unit like gsap.getProperty("#element", "x", "px"); New "effects" extensibility You can author a function that does custom animation and then make it into a named effect that can be called anytime with new targets and configurations. So, for example, think of writing an “explode” effect yourself (a function that accepts targets and a configuration object and spits back an animation/timeline). You define it once, and call it anytime, like: gsap.effects.explode(".class", {speed:25}); GSAP wizards can build crazy-cool effects that folks can simply copy/paste into their project once and then trigger effects easily directly through GSAP. Here's a super-simple "fade" effect to show the concept: // register the effect with GSAP: gsap.registerEffect({ name: "fade", defaults: {duration:2}, //defaults get applied to the "config" object passed to the effect below effect: (targets, config) => { return gsap.to(targets, {duration: config.duration, opacity:0}); } }); // now we can use it like this: gsap.effects.fade(".box"); GSAP is providing 3 key services here: It parses the “targets” into an array. So if selector text is passed in, it becomes an array of elements passed to the effect function. It applies defaults to the vars object for you. No need to add a bunch of if statements or do the defaults yourself. It provides a centralized way of registering/accessing these “effects”. You can think of it almost like jQuery plugins, but for GSAP-based animation effects. Keyframes If you have one set of targets that should animate to various states, instead of creating a whole new tween for each one (re-defining the same targets each time), you can pass an array of keyframes (vars objects) and they'll be perfectly sequenced. Use a "delay" value to create gaps/overlaps!: gsap.to(".class", {keyframes: [ //<-- an array of keyframes! {x:100, duration:1}, {y:200, duration:1, delay:0.5}, //create a 0.5 second gap {rotation:360, duration:2, delay:-0.25} //overlap by 0.25 seconds ]}); These keyframes are basically like individual tweens, so you can even use callbacks like onStart, onComplete, etc. Relative ">" and "<" position prefix When building out a timeline sequence, it's VERY common to want to place the next animation relative to the previous tween's start or end. Since the default behavior is to put things at the end of the timeline, it's usually easy to get that effect, but what if you want the next tween to start at the same time as (or like 0.2 seconds after) the previously-inserted one? What do you do? I bet you either slap a label in there and keep referencing that label. Or maybe you memorize time stamps. Or if you're like me, sometimes you even look at the duration and do the math ("the duration of the previous one is 1 second, and I want it to start 0.2 seconds after that one starts, so I'll do "-=0.8" and pray that I don't need to mess with the timings very much and remember to edit in 2 places"). In GSAP 3 there's a better way. There are now these prefixes for the position parameter in timelines: "<" references the most recently-added animation's START time ">" references the most recently-added animation's END time And you could optionally offset things with numbers too. Examples: var tl = gsap.timeline(); tl.to(...) .to(..., "") //starts immediately after the previous tween's end time (sequenced) .to(..., ">-0.5") //overlaps with the previous tween by 0.5 seconds (because the number is negative) Think of them like pointers - "<" points to the start, ">" points to the end (of the most recently-added animation). Why do we even need ">"? Imagine a scenario like this: tl.to(... {duration:10}) .to(... {duration:2}, "-=10") //starts way earlier .to(...) // See the issue? Since it's tacked onto the end of the timeline, that's actually at the end of that first 10-second tween, NOT the 2nd tween. It's the correct behavior, but when you're animating it's often very handy to be able to insert things relative to the most recently-added one. Animate to a width/height of "auto" This sounds simple, but it can be very handy when you're expanding something to whatever size would naturally fit its contents. New "repeatRefresh" feature Setting repeatRefresh:true causes a repeating tween to invalidate() and re-record its starting/ending values internally on each iteration. This is only useful when you use dynamic values (relative, random, or function-based). For example... gsap.to(".class", { duration: 1, repeat: 5, repeatRefresh: true, //<- forces things to refresh each repeat iteration x: "random(-100,100)",//now x will go to a different random value on each repeat y: "+=50" //and y will keep moving 50px further down on each repeat }); Note: duration and delay do NOT refresh on each iteration. New SnapPlugin (included in the core) Think of this as a replacement for RoundPropsPlugin (still in the core for backward compatibility) but with a more intuitive name and more features. It basically adds a modifier to any property that implements one of the following snapping behaviors to every value DURING the tween (live, not just to the end value): //snap to an increment: gsap.to(".class", { x: 1000, snap: { x: 20 //x snaps to the closest increment of 20 (0, 20, 40, 60, etc.) } }); //snap to the closest value in an array: gsap.to(".class", { x: 1000, snap: { x: [0, 50, 150, 500] //x snaps to the closest value in this array } }); //snap to a value in an array, but only when it's within a certain distance/radius of one of those values: gsap.to(".class", { x:1000, snap: { x: {values:[0, 50, 150, 500], radius: 20} //x snaps to the closest value in the array but only when it's within 20 pixels of it. } }); You can define as many snap properties as you want. Access/control the global timeline gsap.globalTimeline.timeScale(0.1); //slow everything down gsap.globalTimeline.pause(); //stop everything, though you might want to use gsap.exportRoot() instead so that you can exclude delayedCalls() translateX, translateY, rotate, rotateX, and rotateY aliases To better match the names that most developers are used to in CSS, "translateX", "translateY", "rotate", "rotateX", and "rotateY" are mapped to x, y, rotation, rotationX, and rotationY. So, for example, you can do this: gsap.to(".class", { translateX: 100, // same as x:100 translateY: 100, // same as y:100 rotate: 360 // same as rotation:360 }); And yes, directional rotation values work for DOM elements: rotation:"270_short" //animates in the shortest direction! rotation:"270_cw" //animates clockwise rotation:"270_ccw" //animates counter-clockwise You can define units for x/y transforms gsap.to(".class", { x:"50vw", //units! (default is px) y:"5em" }); GSAP 3 no longer leverages matrix() and matrix3d() for CSS transforms which is why it can accommodate units like this. Built as modern ES6 modules with exports Nuff said. And of course there are browser-friendly, minified ES5 files provided as well. Utility methods GSAP exposes some very useful utility methods. Many of them can even return functions so that they can be plugged directly into tweens and leverage GSAP's function-based capabilities meaning they'll get called once for each target (rather than just using the same end value for them all). The included functions are checkPrefix(), clamp(), distribute(), getUnit(), interpolate(), mapRange(), normalize(), pipe(), random(), snap(), splitColor(), toArray(), unitize(), wrap(), and wrapYoyo(). Below is a demo that covers several of the utility methods. Check out the utility methods docs for more info. And here's one that demonstrates how to build your own custom plugin (in this case, it's an unofficial BlurPlugin): Other improvements and changes gsap.getById() - When you assign an id to an animation, you can find that instance by id. The core engine will find colors inside complex strings and animate them properly (no plugins necessary). And of course it'll find all the numbers inside complex strings and animate those as well. function-based values receive a 3rd parameter - the entire array of targets from the tween. This can be useful for advanced effects. gsap.to(".class", { x: function(index, target, targets) { return index * 50; } }); timeScale() can go negative! In GSAP 3 the timeScale controls the direction of playback, so setting it to a negative number makes the animation play backwards. That means it is intuitively linked with the reversed() method. If, for example, timeScale is 0.5 and then you call reverse() it will be set to -0.5. In GSAP 2 and earlier, the "reversed" state of the animation was completely independent from timeScale (which wasn't allowed to be negative). So in GSAP 3, you could even animate timeScale from positive to negative and back again! New iteration() method that lets you get/set the iteration number of a repeating animation. overwrite is false by default, and all other overwrite modes have been eliminated except: "auto" - looks for other active tweens and only kills duplicate/conflicting properties true - immediately overwrites all tweens of the same target(s) regardless of whether or not there are duplicate/conflicting properties. Why make this change? Overwriting caused confusion for some folks and could be tricky to troubleshoot, so it seemed prudent to have users opt-in. Of course you can change the default mode with gsap.defaults({overwrite:"auto"}); (in GSAP 2.x and earlier, "auto" was the default) nextLabel(), previousLabel(), and currentLabel() methods in Timelines (previously getLabelAfter(), getLabelBefore(), and currentLabel()) New read-only Tween.targets() method that returns an array of the targets (previously the API didn't provide a way to access the targets of a tween instance). gsap.updateRoot(time) lets game developers update the root timeline manually. Listening for tick events has been streamlined: //OLD: TweenMax.ticker.addEventListener("tick", yourFunction); TweenMax.ticker.removeEventListener("tick", yourFunction); //NEW: gsap.ticker.add(yourFunction); gsap.ticker.remove(yourFunction); The callback also gets passed some valuable information as parameters: time, deltaTime, and frame (in that order) ModifiersPlugin is baked into the core, as is SnapPlugin, RoundPropsPlugin, EndArrayPlugin and AttrPlugin. And yes, it's still about half the size that TweenMax 2.x was. ease:"linear" is a shortcut for the old ease:Linear.easeNone (which still works). ease:"none" also works. In advanced staggers, grid:[columns, rows] is flip-flopped to grid:[rows, columns] to follow convention with 2D arrays. The default autoKill behavior in ScrollToPlugin is now false. That way, it helps developers be more aware and opt-in to that behavior rather than being surprised by it. TextPlugin, ScrambleTextPlugin, and SplitText all handle even complex Emojis now. onOverwrite was removed in favor of a new onInterrupt callback that fires if/when the tween is killed before it completes. This could happen because its kill() method is called or due to overwriting. Defaults have been consolidated to 2 methods. So instead of TweenLite.defaultEase, TweenLite.defaultOverwrite, TweenLite.defaultStringFilter, etc., there is now gsap.defaults({ease:"power2.in", duration:1}) //for tween-related default (stuff you'd pass in via vars objects) gsap.config({autoSleep:120, force3D:"auto"}); //for other, more general settings. What was REMOVED? BezierPlugin - replaced with MotionPathPlugin (not in the core). RoughEase, SlowMo, and ExpoScaleEase are in an external EasePack file - they just seemed so rarely used that it wasn't worth the kb cost for everyone. cycle (formerly only in the stagger methods) has been replaced by gsap.utils.wrap() which is more flexible. skewType. It’s all just “normal” CSS-style skewing (not “compensated”) “useFrames” className tweens. No more Timeline.gotoAndPlay() - use Timeline.play() instead. CSSPlugin.cascadeTo() “{self}” reference in params. Seemed like a waste and almost nobody uses it, especially since by default callbacks are scoped to the tween/timeline instance anyway. “scope” values at all (except callbackScope). So no onCompleteScope, onUpdateScope, onStartScope, etc. There's no TweenMax.updateTo() or TweenMax.killChildTweensOf() methods. No more TweenLite.selector or TweenMax.selector (it's pointless with document.querySelectorAll() that's in browsers now). No Timeline.addCallback() method (it overlaps in functionality with Timeline.call(), or you can even use add() to add a simple callback with no parameters). MorphSVG's pathDataToRawBezier() method - use rawPathToString() instead. There's no more Ease class - everything is either string-based or plain functions (which can be passed to gsap.registerEase()). Draggable's "scroll" | "scrollTop" | "scrollLeft" types (added back in 3.0.2 due to popular request). The ticker's useRAF() method (modern browsers throttle even setTimeout() calls when the window is inactive/hidden anyway, so there's not much value to toggling it off). TweenLite.defaultEase, TweenLite.defaultOverwrite, TweenLite.defaultStringFilter, etc. There is now gsap.defaults() and gsap.config() where you can change properties like: gsap.defaults({ease:"power2.in", duration:1}) //for tween-related default (stuff you'd pass in via vars objects) gsap.config({autoSleep:120, force3D:"auto"}); //for other, more general settings. TweenMax.pauseAll(), TweenMax.resumeAll(), and TweenMax.globalTimeScale() are gone in favor of directly accessing methods on the globalTimeline: gsap.globalTimeline.pause(); gsap.globalTimeline.resume(); gsap.globalTimeline.timeScale(0.5); Other notes To avoid tree shaking issues and avoid fancy instantiation tricks, users should register any plugins that aren't in the core before using them, like: //list as many as you want. It doesn't hurt to register the same one multiple times. No need to include ones that are in the GSAP core like CSSPlugin, AttrPlugin, ModifiersPlugin, SnapPlugin, EndArrayPlugin, and RoundPropsPlugin. gsap.registerPlugin(MotionPathPlugin, TextPlugin); You can directly access the "labels" object of Timeline instances to get the key/value pairs. Module imports no longer create globals. In other words, if you imported TweenMax as a module in v2, it would end up creating globals for TweenMax, TweenLite, all the eases, etc. That's generally frowned upon for module development which is why we made the change in v3. This helps avoid any conflicts down the road too. Globals are only created in the ES5/UMD files (the ones typically loaded directly into the browser). ThrowPropsPlugin has been renamed InertiaPlugin and has some new features. lagSmoothing() is applied directly on the ticker, like: gsap.ticker.lagSmoothing(false); FAQ How did you cut the file size so much? Removed BezierPlugin, RoughEase, SlowMo (ease), and ExpoScaleEase from the core, but all of those eases (RoughEase, SlowMo, and ExpoScaleEase) are in a separate EasePack file that's only about 1kb gzipped. Dumped legacy code for thing like IE8 and workarounds for very old browsers. Removed some of the complex math code involved in building matrix() and matrix3d() values from scratch in favor of using native strings like translate(), rotate(), rotateY(), etc. in CSS transforms. Handle fewer edge cases where it's appropriate to just train users to input cleaner values. For example, the old CSSPlugin would parse things like margin:"10px 5px" to bust it out into marginTop, marginBottom, marginLeft, and marginRight internally. But it seemed appropriate to keep the core leaner and tell people to define those values individually. (Let me know if you disagree). It helped to consolidate all the Lite/Max flavors into a single Tween and Timeline class. Instead of 4 different render() methods with lots of redundancies, we only have 2 that are much more concise. Skipped inlining some things like pieces of the easing logic. Lots of refining and reorganizing code, passing around object references instead of using "this" keyword, arrow functions, and various techniques for shortening code. What old code will definitely break? Anything that references TweenMax.ticker or TweenLite.ticker (use the new gsap.ticker, and remember that to add listeners to the ticker it's much simpler - see above) Anything that references _gsTransform (use the new gsap.getProperty() method instead) TweenLite.isTweening() - it's now gsap.isTweening() TimelineLite.exportRoot() - it's now gsap.exportRoot() Anything referencing one of the removed features mentioned above, like className tweens. BezierPlugin-based animations (replaced by MotionPathPlugin). Timeline .call() method no longer has a "scope" parameter (3rd). In modern development, it just seemed unnecessary and got in the way. The "cycle" feature of the old stagger methods is gone, in favor of the new (cleaner) way explained above. timeline.getLabelTime("myLabel") has been removed. Use timeline.labels.myLabel instead. Anything that references a tween's "target" property (it's now a targets() getter that always returns an array). Anything that directly references ThrowPropsPlugin (it's renamed InertiaPlugin and it doesn't have a .to() method attached to it because it's totally unnecessary now with the new API not requiring a duration). Anything that references an ease's "getRatio()" method. Eases are pure functions now, so you'd feed the value into the ease directly, like "power2(0.25)". Anything that uses get/set properties inside of a tween. It's easily done using other methods these days. .killDelayedCallsTo() is now .killTweensOf(). Can't you make the file size even smaller? Kb is such an easy metric to focus on, but it only tells part of the story. GSAP isn't aiming to be the smallest animation library - for us, it's about being the most trusted, capable tool that professional animators can rely on day in and day out. That means we had to make some design decisions that cost a bit more kb but we think they're well worth the tradeoff: Solve browser bugs and inconsistencies. For example, Safari doesn't honor the z component of transform-origin when doing 3D rotations, Firefox doesn't play nicely with origins on SVG elements and some browsers ignore transforms that are applied in CSS or the transform attribute when they're also applied a different way as well. GSAP implements workarounds under the hood so your animations "just work" across browsers whenever possible. Performance. Sometimes it actually takes more code to ensure things perform better, like avoiding layout thrashing and various other caching techniques that make your animations buttery smooth. After all, animation is the most performance-sensitive part of UX. It's typically better to pay a few extra milliseconds on load to get smoother animations across your user's entire experience on your site. Capability and flexibility - you want confidence as an animator that your toolset is going to be rich and strong enough to tackle whatever challenges come your way. Plenty of animation engines cover the basics, but GSAP aims to go well beyond the basics and let you do complex sequencing, morphing, inertia-based animations, custom easing and just about anything else you can imagine. Do you have demos for all these cool new features? Absolutely! Check out the collection. We included some of our favorites below as well. GSAP 3 Logo by Jack Doyle Stack Loader by Chris Gannon Race Car Island by Steve Gardner Squiggle Text Animation by Cassie Evans GSAP 3 Cube Swimmer by Pete Barr Low Poly Experiment by Chris Gannon Alien Abduction by Cassie Evans Cube Walk 3 by Pete Barr A special shout-out to @dsenneff who created the GreenSock 3 intro animation! Resources GSAP 3 Highlights video - Learn more about a few of the features we think you'll like most about GSAP 3. GSAP 3 Starter Pen - Play around with GSAP 3 in CodePen! This pen allows you to copy the resource URLs easily. Download the files to use locally. Using a build tool? npm install gsap will get you the files. If you're a Club GreenSock user, there's a gsap-bonus.tgz tarball file in the local download above that you can simply drop into your project's folder and then npm install ./gsap-bonus.tgz and BOOM, it'll be installed just like any other package! See the installation docs for more information. Questions? Hit us up in the forums or contact us directly. We'd love to hear what you think of GSAP 3. Happy tweening!
-
Timeline and Condition ( Screen size and page position)
ZachSaucier replied to CedGrvl's topic in GSAP
Hey CedGrvl. Sorry to say, but neither approach is very good. The main reason for that is because every time the scroll event fires you'd be creating new tweens and timelines for every section of the page. That can't be good What you should be doing instead is only recreating the tweens and timelines on resize if that's even necessary. Otherwise your tweens and timelines should be fine because the page dimensions are the same as they were when it was initialized. Now, to answer your question about which approach of the two is better. I think your first approach is missing some pseudo-code because it's not equivalent to the second approach in terms of the theoretical logic. It's missing conditional checks and creating one of two timelines for each section based on the viewport size. Assuming that is just a mistake and that the logic for that is supposed to be there, I would probably use a variant of your second approach. In general it is good to put the building of complex timelines into their own functions so that your code is more modular, as "Writing Smarter Animation Code" by our very own Carl says. However, the way that you have it setup, with functions within functions, isn't optimal because those functions are recreated every time and functions are somewhat expensive. Rewriting your psuedo-code, I'd probably do something along the lines of this: let masterTL, mobileMasterTL = new TimelineMax({paused: true}), tabletMasterTL = new TimelineMax({paused: true}), desktopMasterTL = new TimelineMax({paused: true}); // keep track of the furthest position that we have been to (to not go backwards) let furthestPos = 0; // for desktops const mql = window.matchMedia('screen and (min-width: 992px)'); // for tablets const mql2 = window.matchMedia('screen and (min-width: 576px) and (max-width: 991px)'); // our sections const pages = document.getElementsByClassName('js-page'); // Keep track of our offsets and hrefs const offsets = []; // Setup our page function init() { updateOffsets(); setupTimelines(); checkSwitchMasterTL(); window.addEventListener('resize', () => requestAnimationFrame(handleResize)); window.addEventListener('scroll', () => requestAnimationFrame(handleScroll)); } // Update each element's recorded offset top position on page resize function updateOffsets() { for(let i = 0; i < pages.length; i++) { let myObject = { "positionPage": pages[i].getBoundingClientRect().top, "hrefPages": pages[i].dataset.href } offsets[i] = myObject; } } // Create the timelines in each section for each section // Do this for each section... function initFirstSection() { let myHREF = offsets[0]["hrefPages"]; // setup the desktop animations let dtl = new TimelineMax(); // ... desktopMasterTL.addLabel("start" + myHREF); desktopMasterTL.add(dtl); desktopMasterTL.addLabel("end" + myHREF); // setup the tablet animations let ttl = new TimelineMax(); // ... tabletMasterTL.addLabel("start" + myHREF); tabletMasterTL.add(ttl); tabletMasterTL.addLabel("end" + myHREF); // setup the mobile animations let mtl = new TimelineMax(); // ... mobileMasterTL.addLabel("start" + myHREF); mobileMasterTL.add(mtl); mobileMasterTL.addLabel("end" + myHREF); }; // Create timelines for the second section function initSecondSection() { // ... } // Call all of our section timeline setup functions function setupTimelines() { // Init all of our sections' timelines initFirstSection(); initSecondSection(); // .... } // Switch between the timelines based on the current viewport width function checkSwitchMasterTL() { // desktop if(mql.matches) { masterTL = desktopMasterTL; tabletMasterTL.progress(0).pause(); mobileMasterTL.progress(0).pause(); } // tablet else if(mql2.matches) { masterTL = tabletMasterTL; desktopMasterTL.progress(0).pause(); mobileMasterTL.progress(0).pause(); } // mobile else { masterTL = mobileMasterTL; desktopMasterTL.progress(0).pause(); tabletMasterTL.progress(0).pause(); } } // Update our offsets and see if we need to switch timelines function handleResize(e) { updateOffsets(); checkSwitchMasterTL(); } // Check to see if we need to fire any animations function handleScroll(e) { // Iterate backwards through our offsets, tweening the furthest one down the page // if the offset is in view let viewportBottom = scrollY + innerHeight; for(let i = offsets.length - 1; i > 0; i--) { let scrollPos = offsets[i]["positionPage"]; if(scrollPos > scrollY && scrollPos < viewportBottom && furthestPos < scrollY) { let myHREF = offsets[i]["hrefPages"]; // We use tweenFromTo to play a section of our master timeline and make sure // that the rest of the page is setup the way we need it to be. // tweenFromTo docs: https://greensock.com/docs/v2/TimelineMax/tweenFromTo() masterTL.tweenFromTo("start" + myHREF, "end" + myHREF); // Update our furthest Y position variable furthestPos = scrollY; } } } requestAnimationFrame(init); The advantages of an approach like this: You do most of the work when setting up the page. All of the tweens and timelines are created at that point. The only things that you're doing on resize are checking to see if you need to switch between timelines and updating the offset positions of your sections. On scroll all you're doing is checking the scroll position and playing the relevant animation (if necessary). It's very modular. It's easily extendable - all you need to add per section is an initFirstSection equivalent function and call that function inside of setupTimelines. Note that this code is completely untested other than for basic syntax errors Some other notes: You might not need the mobile timeline logic. I just included it based on your media point. I figured it's better to add it and take it away if need be than have to not have it and have to add it later. Generally speaking you should put variables that don't change outside of functions that are called multiple times. That saves the computer from having to do the same work every time. You should consider using overwrite: "all" on your tweens since you have multiple timelines affecting the same element. You've got to be a little careful about how you structure the animations. What are you expecting break to do? I think you're wanting return there instead. But if you use if statements, it's not much more processing to just let it check the other conditionals. Sorry for the long post - hopefully it's very helpful! -
Why are you even using "transform" to being with? transform:'rotate('+r+') translate('+radius+',0.1) rotate('+(-r)+')' Use gsap transform syntax instead (x, y, scale, rotation, etc). That can be done by changing the transformOrigin, and using rotation. Then there wouldn't be an overwrite problem.
-
I didn't use one in my demo. I just read the commented out .set() call that you had. It had an ease so I commented about it. You can look at the variable that they are being assigned to (xMove and yMove). Then look where that variable is being used: TweenMax.to($landingWrapper, 8, { scrollTo: { x: xMove, y: yMove }, ease: Power0.easeNone, overwrite:"all" }); No .set() calls are being used in that demo that you posted - only a couple of .to() calls. But that demo faces the same issue as your first one - I'd recommend an approach like the one I used in the post above Sure, if you do it properly You just have to make sure that they're not both being used at the same time and are set up correctly to play nicely.
- 3 replies
-
- mousescroll
- autoscroll
-
(and 1 more)
Tagged with:
-
Hey Tessa and welcome to the GreenSock forums. Your tweens conflict a good bit here. I'd recommend using one tween per mousemove call and using overwrite: "all" to make sure and stop conflict with previous tweens. Doing both of those things seems to take away the stuttering. https://codepen.io/GreenSock/pen/ExxmBbr?editors=0010 Side note: it doesn't make sense to put an ease on a .set() call
- 3 replies
-
- mousescroll
- autoscroll
-
(and 1 more)
Tagged with:
-
When it overlaps, it kills the first x animation. Setting overwrite to false will prevent that. var tl = new TimelineMax({repeat:-1}); tl.addLabel("start"); tl.to("#cat",0.5,{x:"+=300",ease:Quad.easeOut },"start"); tl.to("#cat",3,{x:"+=470", ease:Linear.easeNone, overwrite: false},"start+=0.4"); These are probably the 3 most used overwrite settings. The default is auto. In the next version of GSAP, false will be the default. "none" (0) (or false) - no overwriting will occur. "all" (1) (or true) - immediately overwrites all existing tweens of the same target even if they haven't started yet or don't have conflicting properties. "auto" (2) - when the tween renders for the first time, it will analyze tweens of the same target that are currently active/running and only overwrite individual tweening properties that overlap/conflict. Tweens that haven't begun yet are ignored. For example, if another active tween is found that is tweening 3 properties, only 1 of which it shares in common with the new tween, the other 2 properties will be left alone. Only the conflicting property gets overwritten/killed. This is the default mode and typically the most intuitive for developers. You can also tell when something gets overwritten like this. https://codepen.io/osublake/pen/06dcaf7668cb3925c779a7c7e57cb5c3 https://greensock.com/docs/v2/TweenLite/static.onOverwrite https://greensock.com/docs/v2/TweenLite/static.defaultOverwrite
-
Hi, guys. I needed to create animation like this (in principle): 1. animate rectangle in few steps (=in timeline) 2. when finished, run animation BACKWARDS - 2x faster. But this part is only small part of complex timeline. I tried to achieve this effect by .reverse() method - in two ways: 1) First, I put .add(t2) followed by .add(t2.reverse()) into one timeline. I found out that .add(t2.reverse()) overwrite previous .add(t2) - if I understand this behavior well. However I didn't get what I wanted. This example is represented by blue square in CodePen. 2) So I tried another way - I used onComplete parameter where I called this.reverse(). I didn't expect to get the result that I got. When onComplete is called, red square jumps to initial state without any animation. I'm little bit confused because when I use only one timeline - without calling timeline in timeline as in example - everything works well. Can anybody please tell me what I did wrong and show me better approach? Thank you very much in advance. Karpec
-
I can't create a code-pen the code is all using c# for values and variables, equally the images are stored securely on IP restricted connections, there isn't a need to view the demo anyway I just need to know how to allow vertical scrolling of the web page when clicking and dragging vertically on the slider section. This is the draggable code is there is a value I need to change It fully prevents the web page being scrolled over on mobile as it only allows the horizontal scroll, I obviously don't want that because it is useless to the web pages functionality, I am surprised whatever is doing it is set up this way in the first place. var w_width = $(window).width(); var position_obj = []; const slider = document.querySelector('.slides'); var half_w_width = w_width / 2; $('.slide').each(function () { position_obj.push($(this).offset().left); }); $(document).ready(function () { if ($('.slides').length === 0) { return; } Draggable.create(".slides", { type: "scrollLeft", edgeResistance: 0.9, maxDuration: 1.2, minDuration: 1.2, lockAxis: true, onThrowUpdate: function () { var wrapper_left = this.x * -1 + half_w_width; $(position_obj).each(function (i, val) { obj_c = i + 1; if (val < wrapper_left) { $('.slide').removeClass('active'); $('#slide_' + obj_c).addClass('active'); } }); }, snap: function (e) { var span_window_w = $(window).width(); return -Math.round(Math.round(e / (.3 * span_window_w)) * (.3 * span_window_w)); // This changes the threshold for dragging and snapping the obj's }, }), TweenMax.set(".slides", { overflow: "scroll" }), $(".slides").scroll(function () { $(".parallax").each(function () { var leftOffset = $(this).offset().left; var element_w = $(this).width(); leftOffset < w_width && leftOffset + element_w > 0 && TweenLite.to($(this), 1.2, { xPercent: (w_width - leftOffset) / w_width * $(this).attr("data-velocity"), overwrite: 0 }); }); }); });
- 4 replies
-
- mobile animation
- scrolling
-
(and 3 more)
Tagged with:
-
overwrite Animation changed after restarting timeline
GreenSock replied to kevinMario's topic in Banner Animation
Welcome @kevinMario! Yeah, this is an overwriting issue. When a tween renders for the first time, it checks to see if there are any other tweens of the same property (on the same target) and if any are found, it kills them so that they're not fighting for control. Otherwise, you'd have one tween making the property go one direction, and another tween making it go in another direction. That's what we call "auto overwriting". You have overlapping/conflicting tweens - that's what's causing the problem. The reason it works the first time is because overwriting doesn't occur until the tween renders for the first time. So as soon as the 2nd tween starts, the first one gets killed (and that one doesn't come back). Therefore, the second time through the timeline, that first tween is dead. You can easily see if there's an overwrite happening by using the TweenLite.onOverwrite static method: TweenLite.onOverwrite = function(overwrittenTween, overwritingTween) { console.log("overwritten!"); } You can either prevent them from overlapping (adjust your code) or you could set overwrite:false on your tweens. Or set TweenLite.defaultOverwrite = false. I hope that helps!- 6 replies
-
- 2
-
-
-
- overwriting tween
- overlap
-
(and 1 more)
Tagged with:
-
Very interesting - it definitely seems Vue-related. If I remove Vue from the equation, it all works as expected. From what I can tell, the issue gets introduced as soon as you load CSSPlugin which enables the "autoCSS" feature, wrapping all the non-protected properties into a css:{} object in the vars (protected ones are things like onComplete, overwrite, etc.). If you set autoCSS:false on your first tween, it seems to resolve things too. I wonder if Vue is somehow swapping things out from underneath GSAP. Very odd indeed.