Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Oscar Rottink

GSAP 3D transform round error

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

I'm no real programmer but I created this: http://fizion.maakt.nu/gstest/

 

Not sure why but there's something wrong with the 3D transform. If you look (in Chrome) at the developer tools you see that it will be something like this after one (or a few) clicks

-webkit-transform: matrix3d(0.99992, 0, -0.01243, 0, 0, 1, 0, 0, 0.01243, 0, 0.99992, 0, 0, 0, 0, 1);

I removed the perspective from the wrapper but still the same. I tried to do something with roundProps but no luck so far.

 

As far as I could see the first click is always working like it's supposed to be working. Since I rotate with 90 degrees I'm not sure why it behaves like this. If you click more often the difference will get bigger and bigger which is not really my intention.

 

Hope someone can help me out.

Link to comment
Share on other sites

Hi,

 

I'm not sure what could be happening, maybe the relative values ("+=90") perhaps you could try using absolute values like this approach:

 

See the Pen IJfAy by rhernando (@rhernando) on CodePen

 

See the Pen vjGxH by rhernando (@rhernando) on CodePen

 

Is more simple, you get the right values and it renders the right way all the time.

 

Rodrigo.

  • Like 2
Link to comment
Share on other sites

Thanks Rodrigo! I'll try that. I see that you have two div's per card. I was trying that at first but now I smuggle and swap the div's content at 90 degrees.

 

:ugeek: edit: works if I use whole number instead of +=90 but well, that's not what I expect. So I leave the example as it is.

Link to comment
Share on other sites

I see exactly what's happening, and it's actually not a GSAP issue. Let me explain...

 

In your setIndex() method, you're looping through all the cards and adding a click() handler, but you're calling that method after all of your swapCard() tweens. So each time I click a card, ANOTHER click handler is getting ADDED to the other one(s). So if I click on the same card 4 times and then click the other one, setIndex() gets called 4 times (once for each handler you added)!

 

That's a memory leak problem, so you should certainly fix it, but let me explain why you were seeing what looked like a rounding error with GSAP's matrix stuff...

 

When those 4 tweens were created for the same element (or however many, based on how many clicks happened), they all got put into the render queue. The default overwrite mode is "auto" which means that when the tween starts (the very next tick in this case), the tween will look for any other tweens of the same property of the same element, and kill any that it finds. Perfect....

 

So your first tween would render for the first time, and let's say it's going from 0 to 90, thus the first render may put it at 0.01 degrees (hypothetically). It'd look for any tweens before it in the queue (if tweens start at exactly the same time, the later ones always overwrite the earlier ones), and it wouldn't find any. Then the next tween would begin, and it WOULD find a tween to kill (the first one that just rendered). So it'd kill that one. Perfect. But you're doing a relative tween (like "+=90"), so that just adds 90 to the current value which is 0.01 in this case! See the issue? So when that tween ends, it'd be at 90.01 degrees, hence the values that looked slightly off to you. 

 

This isn't a flaw in GSAP - it's doing exactly what it's supposed to do. 

 

There are 2 solutions:

  1. You can add overwrite:"all" to your tween inside the setIndex() method. That way, it immediately kills any tweens of that object, rather than waiting for the first render.
  2. You could track the target rotation in your own variable, and feed absolute values to your tweens instead of using relative ones. Frankly, this is the approach I'd take because it elegantly handles situations where users click many times fast - it can shoot ahead to exactly the value you want regardless of any partially-finished tweens. For example:
var rotation = 0;
$("#id").click(function() {
    rotation += 90;
    TweenMax.to(this, 1, {rotation:rotation});
});

Either way, though, you should definitely adjust the way you're adding click handlers so that they're not duplicated over and over. 

 

Does that clear things up? 

  • Like 5
Link to comment
Share on other sites

Thanks Carl for you explanation. Like I said, I'm no programmer but I'll dive into your stuff tomorrow. I think I get the part of the tweens added many times. And I'm a curious person so I'm sure I'll find out the best way.

 

I'll don't get it that when I use absolute values it does work since the script (how bad it may be programmed) stays the same. 

 

But I'll test something tomorrow, there is no hurry. I once was good at Flash (version 4 haha) and well.. things changed. So I don't blame anyone but me. But I'm that guy who doesn't like to program a lot but wants some animation. I just want to learn but I hope you guys also learn from a user like me (not the best one).

 

And I'm not sure about your theory that every click adds another onclick event handler. But I might be wrong. As far as I know it does it one time and after a click it disables the click even to prevent multiple clicks. At http://fizion.maakt.nu/fizion/ there's the stuff I have now with all relative numbers changed to absolute. Same script but it does work.

 

So why does it work? And no, you are way better in programming anything but I just don't get it. Just the same script. I asked another fellow to look at it.. but it really seems the script gives a float back were it should be an integer.

 

And that's pure common sense, += just ain't what it is. I just changed the numbers to absolute. It works now so I don't complain but I think it's not really like it is supposed to be.Besides my programming skills which are rubbish. :)

Link to comment
Share on other sites

Please take a look at this:

See the Pen nDhwe by jamiejefferson (@jamiejefferson) on CodePen

 

This is basically your "not working" page moved into CodePen, with a few console logs attached. If you click the first card a bunch of times, you'll see one log for each click, and the transform won't have the rounding error you mentioned. One click at a time and the relative values are working just fine.

 

After clicking the first card a few times and then clicking the second card however, you will see multiple clicks fired at once, and this card will then have the "misaligned" transform. This matches exactly the situation Jack described.

 

On each click, you are only removing the click listener with .off() from the card that was clicked. All other cards keep their click listeners, and then a new one is added to all cards again in setIndex(). They will continually stack every time you click on other cards. You might want to think of a different measure to prevent fast clicking. e.g. TweenMax has an isTweening() method, so you could check TweenMax.isTweening(this) before doing the click action.

  • Like 5
Link to comment
Share on other sites

hi OzBoz,

 

The issue of the relative values is a bit tricky, but one a lot of us has tripped on I can assure  you that.

 

When you have multiple events triggering, a double click for example, and a tween instance being created on each of them the overwrite manager kills the tween created by the first click, so the tween created on the second tween comes in effect and do it's job. Since we're talking about the same tween, with the same values and the same target nothing changes between the first and second tween, with the exception of the values being tweened. Take the following code:

button.click(function()
{
  TweenLite.to(element, 1, {rotationY:"+=90", ease:Linear.easeNone});
});

If the original angle in the Y axis is 0 then after two clicks the element should be rotated 180 degrees in the y axis, ie, to the original angle we add 90 degrees on each click, right?. But what if the second click comes before the first tween is over, lets say after 0.6 seconds?. The engine kills the first tween, that hasn't finished yet and creates a new one, that will add 90 degrees to the CURRENT angle. But the current angle is not 90 degrees, is 54 degrees, so when the second tween is over the element will be sitting at 144 degrees and not 180.

 

On the other hand when using absolute values, like this:

button.click(function()
{
  TweenLite.to(element, 1, {rotationY:90, ease:Linear.easeNone});
});

No matter how many clicks events are triggered the element's final angle will always be 90 degrees. Sure the initial value (something the engine records on every instance you create) won't be 0 (also something important to keep in mind, specially if you want to repeat, replay or reverse an instance), but the ending value will be the one expected.

 

Basically a relative value will add or subtract a given number(indicated in the vars) to the current property value, while an absolute value will tween the property from it's current value to the target one.

 

I hope this makes things more clear.

 

Rodrigo.

  • Like 3
Link to comment
Share on other sites

Please take a look at this:

See the Pen nDhwe by jamiejefferson (@jamiejefferson) on CodePen

 

This is basically your "not working" page moved into CodePen, with a few console logs attached. If you click the first card a bunch of times, you'll see one log for each click, and the transform won't have the rounding error you mentioned. One click at a time and the relative values are working just fine.

 

jamiejefferson

 

Ah now I get it! That was also what Carl meant but your explanation and example makes it clear. Cool! Pretty stupid indeed to remove it once and add it again in a loop. I'll try the your suggestion about isTweening. Much nicer anyway :)

 

 

Basically a relative value will add or subtract a given number(indicated in the vars) to the current property value, while an absolute value will tween the property from it's current value to the target one.

 

I hope this makes things more clear.

 

Rodrigo.

 

Thanks again Rodrigo, at http://fizion.maakt.nu/fizion/ I do have a version with the absolute values which works. But like Carl and Jamie said I'm doing some pretty stupid stuff as well.

 

You guys are a great help! I'll keep this updated if I get somewhere I want to be, just have some ideas for my own site like this (rough sketch) http://ozboz.nl/troep/fiz14.jpg and it's fun to try to get it realized and learn a lot.

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.

×