katerlouis Posted April 20 Posted April 20 Like I said in the other thread, I've just discovered gsap "keyframes" and am loving it. That got me thinking: Often I find myself in a spot where I want a specific property to have a different easing, which always required to split it into multiple tweens, which I then usually bundled in a timeline to treat it as one single tween again (reliable onComplete, one single source of truth for pausing and progress manipulation etc.) A simple example is moving an element in an arc. Instead of defining a path it follows, you can create the same effect by having different eases for the x and y axis. While you can get the same duration per "sub tween" by using defaults for the timeline, you'd still have to set the position `.to(..., 0)` by hand for every sub tween. // works, but feels overly verbose and quirky const tl = gsap.timeline({ defaults: { duration: 0.378, } }) .to(myElem, { x: 200, ease: 'power2.out', }, 0) .to(myElem, { y: 200, ease: 'power2.in', // ! in }, 0) What if you could do something like this? gsap.to(myElem, { duration: 0.378, x: { value: 200, ease: 'power2.out', }, y: { value: 200, ease: 'power2.in', // ! in }, // ... more properties all sharing the same "main ease" })
Rodrigo Posted April 20 Posted April 20 Yeah, there is no feature like that in GSAP and I couldn't really tell you how feasible that could be. Perhaps it wouldn't be too complicated after all, but you could create your own function that takes all those parameters and creates a Tween for each entry, but basically you'd be writing the same logic with less repetition, something like this: const tl = gsap.timeline(); function addTweens(timeline, target, duration, properties) { for (const p in properties) { timeline.to(target, { duration, ...properties[p], }, "<"); } } addTweens( tl, ".box", 0.75, { x: { x: 100, ease: "power2.in" }, y: { y: 200, ease: "power2.out", }, rotation: { rotation: 360, ease: "back.out", } } ) Of course this could get a bit more trickier if you want to use the same Timeline for different elements and create a more convoluted sequence, but would be my first approach to something like this. Here is a simple demo: See the Pen JoRVmRr by GreenSock (@GreenSock) on CodePen. Hopefully this helps Happy Tweening!
Rodrigo Posted April 20 Posted April 20 I forgot, you can use your own notation there without the need to repeat the property like this: { x: { x: 200, ease: "power2.in" }, } It would be like this: function addTweens(timeline, target, duration, properties) { for (const p in properties) { const props = properties[p]; props[p] = props.value; delete props.value; timeline.to( target, { duration, ...props }, "<" ); } } I updated the demo in the previous post. Finally you can simplify it even further and just use an array: function addTweens(timeline, target, duration, properties) { for(let i = 0; i < properties.length; i++) { timeline.to( target, { duration, ...properties[i] }, "<" ); } } addTweens(tl, ".box", 0.75, [ { x: 100, ease: "power2.in" }, { y: 200, ease: "power2.out" }, { rotation: 360, ease: "back.out" } ]); Lots of options! Happy Tweening! 1
GreenSock Posted April 21 Posted April 21 Yeah, one of the performance optimizations in GSAP is that each tween can calculate a single ratio that gets applied to all of its property tweens, so it doesn't have to run an ease calculation for each and every property. I'm personally not so sure creating an object syntax like that is a good thing. It feels a tad clumsy and I worry that then people will start wondering "what if I want a different onComplete for each property? And onUpdate? And..." (where does it end?)
Cassie Posted April 21 Posted April 21 Quote I updated the demo in the previous post. Finally you can simplify it even further and just use an array: function addTweens(timeline, target, duration, properties) { for(let i = 0; i < properties.length; i++) { timeline.to( target, { duration, ...properties[i] }, "<" ); } } addTweens(tl, ".box", 0.75, [ { x: 100, ease: "power2.in" }, { y: 200, ease: "power2.out" }, { rotation: 360, ease: "back.out" } ]); Lots of options! Happy Tweening! I like this as a solution! Keeps the performance optimisations, and quicker to write. (I also tend to make emmet snippets for stuff like this that I do a lot.) https://www.smashingmagazine.com/2021/06/custom-emmet-snippets-vscode/
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now