Jump to content
GreenSock

Search the Community

Showing results for 'overwrite'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • GreenSock Forums
    • GSAP
    • Banner Animation
    • Jobs & Freelance
  • Flash / ActionScript Archive
    • GSAP (Flash)
    • Loading (Flash)
    • TransformManager (Flash)

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge

Categories

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Personal Website


Twitter


CodePen


Company Website


Location


Interests

  1. GreenSock

    GSAP 3 Release Notes

    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!
  2. Hi All, Does anyone know how to make the banner loop in AS2? Can it be done in TweenNano? Below is my code so far: --------- import com.greensock.*; import com.greensock.easing.*; //Scene 1 TweenNano.to(bg1, 1, {_x:0, _y:0, _alpha:100, ease:Cubic.easeOut}); TweenNano.to(logo, 1, {_x:13, _y:20, _alpha:100, delay:.5, ease:Fade.easeOut, overwrite:false}); TweenNano.to(text1, 1, {_x:267.35, _y:45, _alpha:100, ease:Cubic.easeOut, delay:1.3, overwrite:false}); TweenNano.to(text2, 1, {_x:378, _y:45, _alpha:100, ease:Cubic.easeOut, delay:3.5, overwrite:false}); TweenNano.to(text3, 1, {_x:475.05, _y:45, _alpha:100, ease:Cubic.easeOut, delay:4.5, overwrite:false}); TweenNano.to(text4, 1, {_x:584.2, _y:45, _alpha:100, ease:Cubic.easeOut, delay:5, overwirte:false}); TweenNano.to(bg1, 1, {_x:0, _y:0, _alpha:0, ease:Cubic.easeOut, delay:7.5, overwrite:false}); TweenNano.to(text1, 1, {_x:267.35, _y:45, _alpha:0, ease:Cubic.easeOut, delay:7.5, overwrite:false}); TweenNano.to(text2, 1, {_x:378, _y:45, _alpha:0, ease:Cubic.easeOut, delay:7.5, overwrite:false}); TweenNano.to(text3, 1, {_x:475.05, _y:45, _alpha:0, ease:Cubic.easeOut, delay:7.5, overwrite:false}); TweenNano.to(text4, 1, {_x:584.2, _y:45, _alpha:0, ease:Cubic.easeOut, delay:7.5, overwirte:false}); //Scene2 TweenNano.to(bg2, 1, {_x:0, _y:0, _alpha:100, ease:Cubic.easeOut, delay:7.8, overwrite:false}); TweenNano.to(text5, 1, {_x:362.3, _y:27.5, _alpha:100, ease:Cubic.easeOut, delay:8, overwrite:false}); //CTA TweenNano.to(CTA, 1, {_x:629.45, _y:35.5, _alpha:100, ease:Cubic.easeOut, delay:8.5, overwrite:false}); Many Thanks!
  3. Thanks for your reply and suggestions, Zach! Much appreciated. Those changes have brought me very close to a solution. On touch devices, I am still having a few issues, however. Basically, if the Draggable section is part way in the viewport, and the user tries to grab it and scroll back up, Draggable events are firing and the user can't really scroll up normally. I messed around with a few options using the deltas and Draggable.enable()/disable(), but can't quite get it - basically I would need a way to disable Draggable if the user is scrolling vertically. As a side note, I did have to remove the overwrite: 'auto' on the updateProxy function or else that will kill the inertia movements. And related to that, when inertia movements are still going and a touch user tries to grab the screen to stop, a bunch of flickering starts happening as the native scroll position and the inertia movements are fighting. I suppose this is where the overwrite would come in handy, but I would really like to have the inertia preserved if possible - do you happen to have any additional ideas on that? Thank you again for your help!
  4. Hi, I'm trying to figure out how to make a tween autocomplete when it is overwritten. I have something rotating by '+=180', so if it is interrupted, it ends up at an odd angle. Is there an easy way to do this in GSAP JS? Thanks, Gavan
  5. Hey guys, I'm running into problems when i scroll down or up too quickly. It must be something quite simple, I'm missing. If you scroll down slow, then box 1 appears, and then as you go further down, box-2 appears. But if you scroll down quickly, past both triggers, box 1 doesn't disappear quick enough and all the boxes appear on top of each other. I'm using fromTo's and I've tried "immediate render: false" and "overwrite" but, have not been able to work out what is causing this issue. Hope that all made sense. I've made a minimal codepen demo to show what's going on. Any help is greatly appreciated. Cheers
  6. Hi, Experimenting with js version. I wonder if there is a js version of overwrite manager? I am having weird behavior sometimes. And right now i guess we should not use tweenlite/max for production. ?
  7. @OSUblake for the case of Angular, I have the refresh in the OnInit hook method. This is just after registering the plugins and before using the scrollTo plugin. A brief below. ngOnInit() { gsap.registerPlugin(ScrollTrigger); gsap.registerPlugin(ScrollToPlugin); ScrollTrigger.refresh(); // refresh here ... gsap.to(window, { scrollTo: { y: this.triggers[i].trigger, autoKill: false }, overwrite: true, duration: 1, ease: 'expo.out' ... }); } I am guessing the ScrollTrigger.refresh() worked for my case because the elements used with the scroll plugin are the triggers on my ScrollTrigger config. For context, It is for the implementation I was assisted with here:
  8. Hi, I would like to reset the scroll position before navigating away from a page. ScrollPlugin seems to remember the position from the previous page when on a new page. I have a sample usage: gsap.to(window, { scrollTo: { y: this.triggers[i].trigger, autoKill: false }, overwrite: true, duration: 1, ease: 'expo.out' });
  9. Hello, Here's the scenario: I create e-Learning and in the past I have used simple jQuery to show and hide divs when buttons are clicked. I'm still doing this, but I'm now using TweenMax to add some nice animation. My problem is that if you click the buttons quickly in turn I get an animation build up. I would like only the last animation to finish, before the last button click animation starts. I've tried using Overwrite, but nothing seems to effect it. You may ask "But why would a user go click happy on the buttons?". But that just what some people do. Here's my jQuery and TweenMax code: var tl = new TimelineMax; $(document).ready(function() { $("#Person001_btn").click(function() { tl.to([introduction, Person001, Person002, Person003, Person004, Person005, Person006], 0.75, {css:{left:"-600px", autoAlpha:0}, ease:Power2.easeInOut}); tl.to(Person001, 0.5, {css:{left:"0px", autoAlpha:1}, ease:Power2.easeInOut}); }); $("#Person002_btn").click(function() { tl.to([introduction, Person001, Person002, Person003, Person004, Person005, Person006], 0.75, {css:{left:"-600px", autoAlpha:0}, ease:Power2.easeInOut}); tl.to(Person002, 0.5, {css:{left:"0px", autoAlpha:1}, ease:Power2.easeInOut}); }); $("#Person003_btn").click(function() { tl.to([introduction, Person001, Person002, Person003, Person004, Person005, Person006], 0.75, {css:{left:"-600px", autoAlpha:0}, ease:Power2.easeInOut}); tl.to(Person003, 0.5, {css:{left:"0px", autoAlpha:1}, ease:Power2.easeInOut}); }); $("#Person004_btn").click(function() { tl.to([introduction, Person001, Person002, Person003, Person004, Person005, Person006], 0.75, {css:{left:"-600px", autoAlpha:0}, ease:Power2.easeInOut}); tl.to(Person004, 0.5, {css:{left:"0px", autoAlpha:1}, ease:Power2.easeInOut}); }); $("#Person005_btn").click(function() { tl.to([introduction, Person001, Person002, Person003, Person004, Person005, Person006], 0.75, {css:{left:"-600px", autoAlpha:0}, ease:Power2.easeInOut}); tl.to(Person005, 0.5, {css:{left:"0px", autoAlpha:1}, ease:Power2.easeInOut}); }); $("#Person006_btn").click(function() { tl.to([introduction, Person001, Person002, Person003, Person004, Person005, Person006], 0.75, {css:{left:"-600px", autoAlpha:0}, ease:Power2.easeInOut}); tl.to(Person006, 0.5, {css:{left:"0px", autoAlpha:1}, ease:Power2.easeInOut}); }); }); And if it helps, here is the HTML: <div class="PeopleThumbContainer" id="PeopleThumbContainer"> <div class="Person"> <a href="#" class="Person" id="Person001_btn"> <p>Janine<br /> Cost Centre Manager<br /> Capita Symonds</p> <img src="images/people/person_001.jpg" /></a></div> <div class="Person"> <a href="#" class="Person" id="Person002_btn"> <p>Barry<br /> Web developer<br /> Capita L&D</p> <img src="images/people/person_002.jpg" /></a></div> <div class="Person"> <a href="#" class="Person" id="Person003_btn"> <p>Reginald<br /> Consultant<br /> Capita IB Services</p> <img src="images/people/person_001.jpg" /></a></div> <div class="Person"> <a href="#" class="Person" id="Person004_btn"> <p>Lisa<br /> Cost Centre Manager<br /> Capita Symonds</p> <img src="images/people/person_001.jpg" /></a></div> <div class="Person"> <a href="#" class="Person" id="Person005_btn"> <p>Nigel<br /> Cost Centre Manager<br /> Capita Symonds</p> <img src="images/people/person_001.jpg" /></a></div> <div class="Person"> <a href="#" class="Person" id="Person006_btn"> <p>Sarah<br /> Cost Centre Manager<br /> Capita Symonds</p> <img src="images/people/person_001.jpg" /></a></div> </div> <div class="PeopleContainer" id="PeopleContainer"> <div class="Introduction" id="Introduction"><a name="maincontent" id="maincontent"></a> <p>What do people like about working in Capita? What are the benefits of working for such a large organisation?</p> <p><strong>Select the employees on the right</strong> to see what they have to say about things?</p> </div> <div class="PeopleContent" id="Person001"> <img src="images/people/person_001_big.png" /> <div class="text"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p> <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> </div> </div> <div class="PeopleContent" id="Person002"> <img src="images/people/person_002_big.png" /> <div class="text"> <p>Text 2</p> </div> </div> <div class="PeopleContent" id="Person003"> <img src="images/people/person_001_big.png" /> <div class="text"> <p>Text 3</p> </div> </div> <div class="PeopleContent" id="Person004"> <img src="images/people/person_001_big.png" /> <div class="text"> <p>Text 4</p> </div> </div> <div class="PeopleContent" id="Person005"> <img src="images/people/person_001_big.png" /> <div class="text"> <p>Text 5</p> </div> </div> <div class="PeopleContent" id="Person006"> <img src="images/people/person_001_big.png" /> <div class="text"> <p>Text 6</p> </div> </div> </div> Thanks is advance. Barry
  10. Big Thank You to @Carl for his solution, using the overwrite special property after the first add className Taken from TweenMax Docs special property overwrite: overwrite: String (or integer) - Controls how (and if) other tweens of the same target are overwritten. There are several modes to choose from, but "auto" is the default (although you can change the default mode using theTweenLite.defaultOverwrite property): "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. "concurrent" (3) - when the tween renders for the first time, it kills only the active (in-progress) tweens of the same target regardless of whether or not they contain conflicting properties. Like a mix of "all" and "auto". Good for situations where you only want one tween controling the target at a time. "allOnStart" (4) - Identical to "all" but waits to run the overwrite logic until the tween begins (after any delay). Kills tweens of the same target even if they don't contain conflicting properties or haven't started yet. "preexisting" (5) - when the tween renders for the first time, it kills only the tweens of the same target that existed BEFORE this tween was created regardless of their scheduled start times. So, for example, if you create a tween with a delay of 10 and then a tween with a delay of 1 and then a tween with a delay of 2 (all of the same target), the 2nd tween would overwrite the first but not the second even though scheduling might seem to dictate otherwise. "preexisting" only cares about the order in which the instances were actually created. This can be useful when the order in which your code runs plays a critical role.
  11. First, I want to thank you for all of the classes. Great stuff. Second, I've been struggling for days with this animation. Perhaps I don't quite understand how invalidate or overwrite work. Here's what I'm trying to accomplish. Basically, the following code builds out three clickable graphics in a timeline. When any graphic is clicked, the first timeline reverses and loads a new timeline, which shows a definition graphic and a reset button. When the reset button is clicked, the latter timeline is reversed and calls back the first timeline - all of that works great. The problem arises when the user clicks a different graphic than the first time around - instead of showing the corresponding definition graphic on a click, the original definition graphic the user chose plays first, followed by the correct definition graphic and reset button. If the user continues to choose different graphics, things pile up and get really messy. What I want to happen is to have the second timeline overwritten each time the user makes a new choice. Make sense? For the life of me, I can't understand why invalidate() is not simply clearing all values so that the second timeline is created from scratch each time. Any ideas/help would be appreciated. import com.greensock.*; import com.greensock.easing.*; import flash.events.MouseEvent; OverwriteManager.init(OverwriteManager.AUTO); var flavorexplained:TimelineMax = new TimelineMax({paused: true, overwrite: true, onReverseComplete:funcTest}); function funcTest():void { flavorexplained.invalidate(); timeline.restart(); } var timeline:TimelineMax = new TimelineMax({overwrite: true, onReverseComplete:flavorexplained.play}); timeline.append(TweenMax.to(question, .7, {x:7.5, y:147})); timeline.append(TweenMax.to(chocolate, .4, {x:204.95, y:157, delay: .25, ease:Back.easeInOut})); timeline.append(TweenMax.to(vanilla, .4, {x:312.95, y:156.5, ease:Back.easeInOut})); timeline.append(TweenMax.to(strawberry, .4, {x:256.95, y:160, ease:Back.easeInOut})); chocolate.addEventListener(MouseEvent.CLICK, clickHandler); strawberry.addEventListener(MouseEvent.CLICK, clickHandler2); vanilla.addEventListener(MouseEvent.CLICK, clickHandler3); function clickHandler(event:MouseEvent):void { timeline.reverse(); var flavorX:TweenMax = ( TweenMax.to(noway, .7, {x:275, y:200, ease:Back.easeInOut, overwrite:true}) ); flavorexplained.append(flavorX); flavorexplained.append(TweenMax.to(resetbutton, .7, {x:512, y:228, ease:Back.easeInOut})); } function clickHandler2(event:MouseEvent):void { timeline.reverse(); var flavorX:TweenMax = ( TweenMax.to(strawexplained, .7, {x:275, y:200, ease:Back.easeInOut, overwrite:true}) ); flavorexplained.append(flavorX); flavorexplained.append(TweenMax.to(resetbutton, .7, {x:512, y:228, ease:Back.easeInOut})); } function clickHandler3(event:MouseEvent):void { timeline.reverse(); var flavorX:TweenMax = ( TweenMax.to(vanillaexplained, .7, {x:275, y:200, ease:Back.easeInOut, overwrite:true}) ); flavorexplained.append(flavorX); flavorexplained.append(TweenMax.to(resetbutton, .7, {x:512, y:228, ease:Back.easeInOut})); } resetbutton.addEventListener(MouseEvent.CLICK, clickHandlerA); function clickHandlerA(event:MouseEvent):void { flavorexplained.reverse(); }
  12. Hi all, I cannot find what is causing my GSAP in Safari is buggy , laggy, choppy... well what else word can I describe haha. One of the forum links itself looks laggy in Safari. I attached the mp4 video file: left - chrome, right - safari. Here is my GSAP code for reference: function animateFrom(elem, direction) { direction = elem.getAttribute("data-reveal-direction") ?? 0.2; const delay = elem.getAttribute("data-reveal-delay") ?? 0; let x = 0, y = direction * 100; if (elem.classList.contains("js-reveal_fromLeft")) { x = -100; y = 0; } else if (elem.classList.contains("js-reveal_fromRight")) { x = 100; y = 0; } console.log("x: ", x); console.log("y: ", y); // gsap.set(elem, { x: x, y: y, autoAlpha: 0 }); elem.style.transform = "translate(" + x + "px, " + y + "px)"; elem.style.opacity = "0"; const tl = gsap.timeline({ scrollTrigger: { trigger: elem, once: true, markers: true, }, }); tl.to(elem, { duration: 1.25, x: 0, y: 0, autoAlpha: 1, ease: "power2.out", // overwrite: "auto", delay: delay, }); } function hide(elem) { gsap.set(elem, { autoAlpha: 0 }); } // Scroll reveal gsap.utils.toArray(".js-reveal").forEach(function (elem) { animateFrom(elem); }); gsap-safari-laggy.mp4
  13. Hey mapo and welcome to the GreenSock forums! Thanks for being a Shockingly Green member. I think most of your jumpiness comes from the difference in the default value of overwrite between GSAP 2 and GSAP 3. In GSAP 2 it was "auto" by default and in GSAP 3 it is false by default. Changing it removes a bit of the jumpiness for me. You can change the default by saying gsap.defaults({overwrite: "auto"}); or you could apply it to just the tweens you want to by saying overwrite: "auto" in their vars parameter. @GreenSock another instance where people are tripping over this. But maybe it will lessen once people are converting GSAP 2 things to GSAP 3 a while from now?
  14. Hi, I have a question about use of transformAroundPoint with overwrite. When I write OverwriteManager.init(); TweenLite.to(testMovie,1,{transformAroundPoint:{point:new Point(0,0)}}); and then try to overwrite it with, TweenLite.to(testMovie,1,{point:new Point(80,80),overwrite:2}); this seems like not working. Does overwrite not work on point() for transformAroundPoint? If overwrite doesn't work on transformAroundPoint, is there any alternative way to do the same thing? Thank you,
  15. Hey dawid660. A few notes: In general it's best to create animations at the start and use control methods inside of your functions for interaction. I talk more extensively about that in my article about animating efficiently which I highly recommend. Part of what makes killing off the old animation more difficult is that you don't save the reference to any of the tweens that you're creating inside of the arrowsAnimation function. One way you could do so is to create a timeline within that function and add all of your tweens to that timeline. Then return the timeline from the function and save a reference to that timeline. That way you could use the variable (that points to the timeline) to kill off the animation. Alternatively if you are setting all of the properties that you're animating in the intersection observer callback you could use overwrite: 'auto' or overwrite: true to kill off any tweens that are in conflict. Using GSAP's ScrollTrigger would likely make this sort of thing more easy. You don't need the quotes around numerical values. That's one of the most common GSAP mistakes.
  16. 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.
  17. Just one quick [untested] idea: liveSnap: {x: (value) => { // animate to the snapped value gsap.to(target, {x: gsap.utils.snap(100, value), duration: 0.3, overwrite: true}); // but return the unsnapped value return value; }},
  18. tldr. it feels that possibly timelines due to their nature of taking in element values straight away (not at the time of playing), might be the cause of glitch because values are constantly changing especially that its 3 timelines controlling elements. I am trying with overwrite both auto and true, but it's not working correctly. There are two problems in which focusing on the second is more important. The first one is the issue of inputing, in this case hovering, as Blake mentioned. There are methods to solve this, one being what Blake suggested. The result should strive to avoid triggering, hovering on/off , in a consecutive way. Here especially as hovering off reverses() the timeline. The second is really the overwriting issue. What seems a viable solution to me possibly presents a cornerstone mechanics for interactive control of multiple elements. On each hover, a timeline is created with .to(). At that moment timeline renders and picks up the current values in order to create the interpolation. And it starts interpolating. On a new hover, the same thing is repeated, the then-active timeline is paused/killed, and a new one is taking over. This seems plausible. In terms of Promise.All, it seems to me that it is better suited for chaining timelines/animations. Here it is taking over method, for multiple elements at the same time. Is this possibly not well suited for GSAP timelines? I pondered possibly trying to do this with JS/classes/CSS/transition. A bigger overkill would be canvas I presume.
  19. Thanks for the info. Since it is my opensource project and I want it to be as forward compatible and versatile for people that might not be using it in the same ways that I am now, is overwrite:auto going to remain current or are things moving toward a more CPU friendly way of handling things? Also lets say that someone wanted to do a physics simulation behind the video player using GSAP would the overwrite:auto cause conflict? About what you said about the isTweening, I think the isTweening might be the only way to tell tweening object to stop and change direction handled by multiple but similar events, like when you mouse over the player you need to see the cursor and the controls. It's the same for the controls but you no longer need the timeout to hide the controls and the cursor; but you want a timeout when leaving the controls to hide the controls and the cursor (especially if the video is playing) all of which need to be interrupted and overwritten by the last event in 1/10000000 of a second depending on how fast your kid(or me) is spasming the mouse around. Im I right in my thinking if using isTweening in that scenario? If not Im thinking that im thinking about this entire redesign thing wrong then. Thanks again Jack!
  20. Ugh, sorry to hear about the trouble, @N1DAN. Sounds super frustrating. I'm not in a position to be able to wrap my head around 2500+ lines of code and debug it for you, but the only thing that came to mind is that perhaps you're creating conflicting tweens. Before version 3, GSAP used overwrite: "auto" as the default which means that it automatically tried to find competing tweens of the same properties of the same objects and killed any it finds. For some people that was a bit confusing, plus it cost CPU cycles so in version 3 there is no overwriting by default. You opt-in to ensure developers are more aware. Of course it's best to not create conflicting tweens to begin with, but try just adding this to the top of your file: gsap.defaults({overwrite: "auto"}); Does that resolve anything for you? Other than that, there really isn't anything I can think of that'd cause such simple tweens to behave differently in the newer version. Trust me - the new version is far more capable, plus the syntax is easier and the overall file size is significantly smaller. So you're making a good move by updating. I'm confident that once you get past this issue, you'll love working with GSAP 3. Let me know how that overwriting tweak goes. I have a sneaking suspicion it'll solve things for you based on what you described.
  21. That's because you're trying to animate an attribute but you forgot to use the AttrPlugin, so GSAP is taking you literally and attempting to directly get/set properties like "stopColor". Minor note: you don't have to pass an Array of selector text - you can just use a normal selector text string with commas: // BAD gsap.to(['#cursor-gradient-1', '#cursor-gradient-2'], { stopColor: '#000' }); // GOOD gsap.to('#cursor-gradient-1, #cursor-gradient-2', { attr: {"stop-color": '#000'} }); Does that clarify things? Oh, and you don't need to have this line: gsap.killTweensOf(['#cursor-gradient-1', '#cursor-gradient-2', '#cursor-fill-1', '#cursor-fill-2']); You can simple set overwrite: true or overwrite: "auto" on your tweens. I mean it's totally fine if you prefer explicitly killing things like that, but it seemed more verbose than necessary. Happy tweening!
  22. If you're animating the same properties in different timelines you can use overwrite:true Possibly even https://greensock.com/docs/v3/GSAP/Timeline/invalidate() Scaling/moving on hover is always a tricky one though because inevitably you'll find a spot whilst hovering where the element will get 'stuck' scaling up and down and in and out of your mouse 'hit area' Blake will be able to advise more on the react side of things.
  23. So, on click kill all ScrollTrigger's then scale to 100% and create a new ScrollTrigger (that does no animation). And that one has two hooks: on leave and leaveBack, that then kills it self and reinstates all previous ScrollTrigger's that where killed by the click? Seems a lot more complicated than `overwrite: true`, which if it would work does everything above, but with one line of code. Why doesn't overwrite work? Are there plans to make it work in combination with ScrollTrigger?
  24. Hello, In my react application, there are three section with class .cts which contains image and some content. All the three section is wrapped in a main container. Now I have implemented the animation as follow: const scrollColorElems = document.querySelectorAll(".cst"); scrollColorElems.forEach((colorSection, i) => { console.log(colorSection.clientTop); const prevColor = i === 0 ? "gray" : scrollColorElems[i - 1].dataset.scrollcolor; ScrollTrigger.create({ trigger: colorSection, start: "top center", end:"bottom center", markers:"true", onEnter: () => gsap.to("#ftiot", {backgroundColor: color, overwrite: 'auto'}) // onLeaveBack: () => onLeaveBack(prevColor), onEnterBack: () => gsap.to("#ftiot", {backgroundColor: color, overwrite: 'auto'}), }); }); Now the problem I am facing is the start marker keeps changing its position and become pretty inconsistent. In the below screenshot you can see the start marker is way below the top offset marked by black border of the trigger container even though I have specified "top center" as starting point in start property.
  25. When you do a timeline.tweenTo(), that's just creating a linear tween that automatically sets its duration to the amount between the current playhead position and the destination. So, in your example, let's walk through what happens... Click "Pos2", and it starts a 2-second tween (because that's how far it is to that position). 0.5 seconds later, click "Pos1" which now creates a 0.5-second tween back to the start (because that's how far it is) Now you've got TWO tweens created, both vying for control of the playhead. The 0.5-second one "wins" while it's running because it runs last (since it was created last) The 0.5-second tween to the start finishes first. The 2-second tween still has 1 second left to play so it keeps going. The position suddenly jumps from "Pos1" to part-way to "Pos2" (because that's where that second tween was in its progression). Make sense? That should also explain why @akapowl's solution worked. That was essentially hiding the problem because the tweens were always the same duration, thus the "new" one always runs longer than the "old" one (therefore no jump). There are a bunch of solutions. Perhaps the easiest is to just have the new tweenTo() tweens overwrite the old ones so you don't have multiple going at the same time. Here's an example of that: https://codepen.io/GreenSock/pen/8e4fd7788a7b9b84664236ef155577a2?editors=0010 Of course you could directly animation the progress like Zach showed. In the next release, I'll force the overwrite of .tweenTo() tweens to be "auto" because that's more intuitive and would resolve this anyway.
×