Jump to content
Search Community

prevent matrix tansforms, bake "pure" css-transforms into timeline

anaelyts test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

hello GreenSock forum,

I'm having problems when positioning 2 pictures in a timeline making them aligned to each other.  It works all fine from images 1 to 5 using tl.to with transforms. For picture _6 this only worked for a specific screen-resolution. It floats off when changing the screen-size. Applying a css-transform "perspective(75px) scale(.7) rotateY(6deg) translate(-51%,-7%) rotate(6deg)" and transition value to this one in css keeps it aligned.

So I was trying to follow part of Jack's advice in the post prevent-gsap-from-transforming-my-transforms-into-matrix which I understood it would bake a pure css-transformation into the timeline without the matrix() transformations:

tl_.to("._7", 1, {opacity: .5, onComplete:function() {
   $('._6')[0].style.transform = "perspective(75px) scale(.7) rotateY(6deg) translate(-51%,-7%) rotate(6deg)"}}, "=+2");

this code aims at starting the transformation (onComplete function), after img _7 gets faded halfway in...

when it comes to the result, looks like img _6 already appears transformed at the start of the tween. In the codepen img_6 should show without transformations at around 18 sec and start them when img _7 gets blended in (around 22 sec).

The effect can be seen, when inspecting element _6 and switching transform on and off at around 25sec. Is this a syntax issue or am I running into wrong direction?

Thanks for your advice
regards mario

See the Pen oNBPpBG?editors=1010 by anaelyts (@anaelyts) on CodePen

Link to comment
Share on other sites

  • Solution

Welcome to the forums, @anaelyts

 

It'd be super helpful if you could just isolate the one thing you're struggling with and eliminate all the extra fluff like the clipPath, opacities, all the extra images, etc. because it's just kinda hard to follow exactly what you're saying the problem is. I'll offer a few thoughts...

  • As you probably know, you're using a non-standard order of transforms which makes things tricky. One of the big benefits of GSAP is it lets you independently control each part of the transforms (x, y, scaleX, scaleY, rotation, etc.) which requires that they be applied in a consistent order. 
  • You're setting things via a string on the "transform" property which, again, we strongly recommend against because you lose all the performance and some of the accuracy benefits that GSAP offers. It's forced to apply those transforms and then have the browser return a computed matrix() or matrix3d() which it then must parse, and as you discovered the browser always reports those as px-based (you lose any responsive units like vw, vh, %, etc.). 
  • You directly set the element.style.transform but never told GSAP that it should parseTransform again (because you threw off the cached values). So GSAP will continue to use the cached values, making it appear as though it ignored your style.transform direct set on subsequent animations. You can set parseTransform: true on a subsequent tween to tell GSAP to clear out its cached transforms on that element. 

If you really need to set the transform components in a non-standard order, I whipped together an experimental plugin that lets you define the order in a comma-delimited "transformOrder" list that you'd add your tween(s):

 

// caveat: you must define each individual component in the list that you want rendered, so "scaleX,scaleY" instead of "scale", and "translateX,translateY" instead of "translate".
// example for just 2D stuff would be transformOrder: "x,y,rotation,skewX,skewY,scaleX,scaleY,perspective"
gsap.registerPlugin({
	name: "transformOrder",
	priority: -100, // make it run AFTER other properties update (transforms)
	register(core, Plugin) {
		const cache = {},
			propToAlias = {x: "translateX", y: "translateY", rotation: "rotate", rotationX: "rotateX", rotationY: "rotateY", transformPerspective: "perspective"},
			aliasToProp = {translateX: "x", translateY: "y", rotate: "rotation", rotateX: "rotationX", rotateY: "rotationY", perspective: "transformPerspective"},
			getFunc = template => {
				let props = template.split(",").map(p => aliasToProp[p.trim()] || p.trim()),
					transforms = props.map(p => propToAlias[p] || p),
					l = props.length,
					func = (ratio, data) => {
						let t = "",
							i = 0;
						for (; i < l; i++) {
							t += transforms[i] + "(" + data[props[i]] + ") ";
						}
						data.target.style.transform = t;
					};
				cache[template] = func; // use a cache to boost performance so that we don't have to keep re-creating the function for targets that share the same transformOrder.
				return func;
			};
		Plugin.prototype.init = function(target, vars) {
			this.func = cache[vars] || getFunc(vars);
			this.cache = gsap.core.getCache(target);
		}
	},
	render(ratio, data) {
		data.func(ratio, data.cache);
	},
	init: true
});

Then you'd add it to your tween like:

gsap.to(".box", {
	x: "-51%",
	scale: 0.63,
	rotation: -5,
	transformPerspective: "6vw"
	duration: 3,
	transformOrder: "transformPerspective,scaleX,scaleY,rotation,x,y"
});

And that basically overrides the normal rendering order. And in GSAP 3, you can use units on things like x, y, etc., it should work okay to include those in the individual components. 

 

I hope that helps!

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

hello Jack,

wow, I'm really impressed by your comprehensive answer. This points me in new directions, leaving my intentional path. Having built a couple of css-keyframe anims in the last time, I'm more than happy how flexible the timeline in GSAP can be built and edited. I think the approach with the transforms comes from my workflow (building and editing Animations in Chrome DevTools with Inspector). Your hints will keep me busy for a while now. Much to try from here. What I understand, if I use GSAP correct, Responsiveness will be in the result. Great and many thanks!

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...