Jump to content
Search Community

Prevent GSAP from transforming my transforms into matrix()

katerlouis test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

1) horizontally flip an image using css transform:scaleX(-1);
2) apply "scale" or "scaleY" in the tween
3) ???

4) the css scaleX(-1) makes the tween matrix X & Y values both negative = upside down image

Link to comment
Share on other sites

That's actually not a bug. And it demonstrates why we strongly recommend that you always apply transforms via GSAP instead of trying to mix CSS and GSAP...

 

The browser always reports the calculated values as matrix() or matrix3d() which are inherently ambiguous when it comes to rotational data in particular. A scaleX(-1) results in exactly the same matrix as a scaleY(-1) rotate(180deg) or rotateY(180deg) or rotateY(-180deg) or many other options. GSAP must pick one. Your particular scenario is interpreted as scaleY:-1, rotation:180. Again, that's not a bug - it's a perfectly valid parsing of the matrix that the browser provides.

 

If you set the value via GSAP, it always knows EXACTLY what you meant. Plus it is more performant (it can skip the parsing of the computed value on subsequent animations). More accuracy, better performance, and total reliability. 

 

It's fine if you set things in CSS if you want (to avoid an initial flash of unstyled content), but immediately set() them with GSAP too. Like:

TweenMax.set(element, {scaleX:-1});

 

Make sense? 

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

Why I do think it's possibly a bug:
:-( Applying scaleX() alone in the tween does not cause the upside down behaviour, it only happens if you use scale() or scaleY().

:-( Manually adjusting the generated matrix value via console 'fixes' the 'problem' (until you scroll of course).
:-( Adding in scaleY() to the css has no effect on the generated matrix.
:-( Using matrix(-1, 0, 0, 1, 0, 0) in css  instead of scaleX(-1) also has no effect on the generated tween matrix, which ends up having both X&Y values negative as per before, eg, matrix(-1, 0, 0, -1, 0, 0).

:shock: Using TweenMax.set(element, {scaleX:"-1"}) also fails in a similar way, but slightly worse - now my image reverts to being rather fat looking...



I ended up using different logic to scale my image - manipulating width&height instead of using scale - obviously this is not a very dynamic solution but it's the ONLY thing I could get to work with my css-flipped image.

 

yep, yep, here is the codepen:

See the Pen WJMPgj by BugFree (@BugFree) on CodePen

 

(NB: Pasting a codepen URL in the middle of my post, autoloaded the preview & deleted all the text after the pen!)

 

EDIT update (not shown in pen):

:-( Using transform:rotateY(180deg) in the css just removes the X axis from the equation - it still has unwanted flip.

:-( Removing the css flip and directly using set() to flip, causes the same unflip as per using rotateY() when scrolling.

EVERYthing else I have tried gives the same result as shown in the pen.

 

Edited by bugfree
more info
Link to comment
Share on other sites

2 hours ago, bugfree said:

Why I do think it's possibly a bug:

 

Did you see this? 

 

8 hours ago, GreenSock said:

Your particular scenario is interpreted as scaleY:-1, rotation:180.

 

If you want to keep scaleX(-1) in your CSS, then you'll also need to set scaleY to 1, and rotation to 0.

 

Same matrix, different results.

 

See the Pen pVaBRz by osublake (@osublake) on CodePen

 

 

  • Like 3
Link to comment
Share on other sites

But, I do not want the image to flip during animation, just to scale bigger or smaller, while in a pre-flipped state.
That means changing both scaleX and scaleY simultaneously, not just one at a time & this goes for the matrix values as well.
I am not interested in ranging from -1 all the way to 1, I just wanted myimage to grow and shrink a little bit eg: scale(1) to scale(0.8).
This means it should tween from scale(-1,1) to scale(-0.8,0.8) & I cannot for the life of me find a dynamic way to do this.

 

See the Pen LmQobg by BugFree (@BugFree) on CodePen

I am after the effect as seen on Heros #5 & #6 however they should be facing toward each other, not away (try loading without JS).
This is getting horribly convoluted & escaping further from my imagined idea of applying a simple 'scale' to flipped & non-flipped images throughout the scene.

Should I make this into a new thread? Since it seems the topic of this thread is unavoidable.

Link to comment
Share on other sites

Yeah, I'm still having a really hard time understanding why you think this is a bug (I see no evidence of that), but I'm glad you @OSUblake delivered a solution for your scenario that works well. Scaling a parent is probably easiest, as he suggested. If I understand your goal properly, you could also do something like:

function scaleBy(element, factor) {
  var t = element._gsTransform;
  TweenMax.to(element, 2, {scaleX:t.scaleX * factor, scaleY:t.scaleY * factor});
}

//usage: 
scaleBy(element, 0.5);

 

That way, it doesn't matter if the current scale is positive or negative. 

 

Oh, and that code assumes you've set() your transforms initially (otherwise, there won't be a _gsTransform on the element yet). 

 

Happy tweening!

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

Doesn't really solve my 'problem' of doing what should be simple: setting an image to scale a little bit (which works flawlessly with 1 line of code) and then doing the exact same thing to an image that has been flipped using css.

Every solution involves adding extra code to make the flipped image behave properly: canvas, set(), parent container, helper func, even my solution of scaling W&H adds in undesired extra code to make it work as intended, reducing the dynamic flexibility & minimalistic code I was hoping to achieve.

 

I greatly appreciate the speed of which both Admin & Mod have responded to my questions & multiple solutions provided all do work as desired.
I hope this thread can help someone else in the future who is also stuck wondering why their simple flipped image is not behaving as expected when scaled.

 

EDIT: I do understand there are situations where flipping during animation is actually desired & it works great for that!

 

Thanks again GreenSock - you guys rock!

  • Like 1
Link to comment
Share on other sites

11 minutes ago, bugfree said:

Doesn't really solve my 'problem' of doing what should be simple: setting an image to scale a little bit (which works flawlessly with 1 line of code) and then doing the exact same thing to an image that has been flipped using css.

Every solution involves adding extra code to make the flipped image behave properly: canvas, set(), parent container, helper func, even my solution of scaling W&H adds in undesired extra code to make it work as intended, reducing the dynamic flexibility & minimalistic code I was hoping to achieve.

 

It sounds like you were expecting scale values to be relative and somehow build (combine) on top of each other rather than being absolute. If we did it that way, it'd lead to a lot of confusion. 

 

Ultimately you had things with a scaleX (or scaleY) of -1 and you were expecting that tweening to a value of 0.5, for example, would actually make it automatically go to -0.5 or maybe 0.5 * whatever the current value is, right? 

 

As for lots of extra code, that function I provided was meant to be reused as much as you want, so it should be very simple and concise. Let me know if you need any help with it, though. 

 

I realize you've got things working now, so that's great. And I sure appreciate the kind words at the end of your post. We really try to serve people well in these forums and it's nice to hear when folks like you notice the efforts. Happy tweening!

  • Like 4
Link to comment
Share on other sites

  • 2 years later...

Been scouring the net for solutions to prevent gsap from converting vh units to pixels when animating with scrollTrigger. Ended up using custom css variables which did the trick. It doesn't look elegant but it works. 


CSS

.attached-mastheadtitle {
	--npos: 0;
    --nposvh: calc(var(--npos) * 1vh);
    transform: translate3d(0,var(--nposvh),0);
}

JS

var nx = gsap.timeline(
                { 
                    scrollTrigger: { 
                        trigger: '.section-masthead',
                        scroller: scrollname,
                        scrub: true,
                        start: 'top top',
                        end: 'bottom top'
                    } 
                }
            )
            .fromTo('.attached-mastheadtitle', {'--npos': -60, color: '#ffffff' },{ '--npos': 0, color: '#5A6651' },0);


With this I don't need to worry about the animation "running out of the intended position" whenever the user rotates his/her iPad while browsing the website. 
 

Link to comment
Share on other sites

Hey Nekorin and welcome to the GreenSock forums.

 

11 hours ago, Nekorin said:

With this I don't need to worry about the animation "running out of the intended position" whenever the user rotates his/her iPad while browsing the website. 

I would think that would easily be fixed by calling ScrollTrigger.refresh() if the orientation changes (if the resize event doesn't fire, which automatically calls ScrollTrigger.refresh()).

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...