Jump to content
Gary

Translate() and Translate3d()

Recommended Posts

I like to use a center origin on my animated div, which I achieve with:

 

transform: translate(-50%, -50%)

 

CSS lets me keep that constant and then, also, add a 3d transform.   So, this is valid and works as expected:

 

transform: translate(-50%, -50%) translate3d(-100, 100, -20);

 

How can I do the same with greensock?  I tried doing something like this, but no deal.

 

{

   x: "-100px - 50%",

   y: "100px - 50%",

   z: -20

}

 

Hopefully there's some simple answer.  By the way, awesome API.  I'm a huge fan in just one day.

 

See the Pen LvmrC by anon (@anon) on CodePen

Share this post


Link to post
Share on other sites

Hi and welcome to the GreenSock forums.

 

Good news is that if you want to use the center of the element as the origin point GSAP uses it as default, so all you have to do is the following:

TweenLite.to(element, time, {x:-100, y:100,z:-20});

If you want to change the origin point you can use transformOrigin in the config object:

TweenLite.to(element, time, {x:-100, y:100,z:-20, transformOrigin:"0% 100%"});

Rodrigo.

Share this post


Link to post
Share on other sites

Thanks very much for the reply, Rodrigo.  Although the name aligns with what I am talking about, I don't think the css transform-origin helps here, even though the default in css and GreenSock is "50% 50%".  I'm talking about shifting the divs to the left and up by 50% in the 2D space (hence the -50% -50%).

 

Imagine a canvas div that is 1000px by 1000px.  I wish to center divs on the canvas, regardless of their extents, by placing them at left: 500px; top: 500px;   To make them centered, I use transform: translate(-50%, -50%)  This is the starting point, before I do 3D transforms.

 

If I translate using translate3d, it will offset from there, including the x and y dimensions.  The transform-origin affects how the rotate works, after the translate3d.

 

Is there a way to combine percentage and absolute values in GreenSock, similar to the CSS calc function?  Otherwise, it seems that GreenSock might be losing some flexibility by using the x and y properties for both translate and translate3d functionality.  I know it is all just being munged into a matrix behind the scene, so having the ability to combine percentages and absolutes into the x and y properties would solve it.

 

Thanks in advance!

Share this post


Link to post
Share on other sites

Ah, got it now. Sorry the neurons aren't spinning as fast this late ;)

 

What you can do is sequence the elements. Two options.

 

First create two separate tweens in order to first set the element in the center of the screen and then animate it to the values you want. For this GSAP has a nifty method called set() which is basically a tween that lasts zero seconds.

// first set up the position using a set() instance
TweenLite.set(element, {x:"50%", y:"50%"});

// then animate it to the position
TweenLite.to(element, time, {x:-100,y:100,z:-20});

Create a timeline to do the same:

var tl = new TimelineLite();

tl
  .set(element, {x:"50%", y:"50%"})//  center the element
  .to(element, time, {x:-100, y:100, z:20});// move it to the desired position

Although in this cases I always go with a little function to center the elements relative to either the viewport or their parents:

var winWidth = $(window).width(),
    winHeight = $(window).height(),
    elWidth = $("#elementID").outerWidth(),
    elHeight = $("#elementID").outerHeight(),
    centerPoint = {x:(winWidth - elWidth)/2, y:(winHeight - elHeight)/2};

TweenLite.set("#elementID", centerPoint);

Rodrigo.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks, Rodrigo.  The TweenLite.to still doesn't take the -50% into account.  

I would need it to be something like this, which I guess isn't supported.  

// first set up the position using a set() instance
TweenLite.set(element, {x:"-50%", y:"-50%"});

// then animate it to the position (with the percentage still intact)
TweenLite.to(element, time, {x:-100 - 50%,y:100 - 50%,z:-20});

I love what I am seeing with GSAP, but this appears to be something where CSS is superior.  Is there a wishlist somewhere that I could add this to?

 

I created a codepen that demonstrates it.  

 

See the Pen ItymG by anon (@anon) on CodePen

Share this post


Link to post
Share on other sites

Hi Gary,
 
Thanks for the codepen, it was very helpful.
 
The thing is that CSS transforms are chainable, so basically you're moving the element to -50% in both axis and then to the indicated positions  x:0 and y:0, starting from the current position, which is -50%. Using GSAP is a bit different. The engine records the element's initial position and then you can move it to the indicated position. Later if you create another tween with an absolute value the engine will move the element to that new value considering it's initial position, not the current one. Fortunately the engine also accepts strings in order to move the elements relative to their current position, like this:

TweenLite.set("#greenBox",{x:"-=25", y:"-=25"});

That code moves the element 25px to the left and top of it's current position. So what you can do is something like this:

TweenLite.set("#div1",{x:"-50%",y:"-50%"});
TweenLite.set("#div1",{x:"+=0", y:"+=0"});

TweenLite.set("#div1",{x:"-50%",y:"-50%"});
TweenLite.set("#div1",{x:"-=50", y:"-=50"})

My recommendation would be to use a set instance at the beginning of your code and then in your function use relative values.

 

I set up a simple codepen:

 

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

 

Rodrigo.

Share this post


Link to post
Share on other sites

Thank-you for all your help Rodrigo.  Your example actually proved the problem.  I forked it and updated it some.

 

Run the codepen and click the +50 and -50 buttons.  They do as you would expect.  However, try typing into the divs and see what happens.  GSAP is not emitting styles that keep it center oriented.  Sure, you can write code that statically centers it when you first lay it there, but that would be a pain to keep varying sized things centered, especially when CSS does it for free.

 

Also, try clicking the set 0,0.  This sets the value to absolute 0,0 but loses the -50%,-50% offset that is making it center aligned.  This needs to be applied each time the absolute value is set to overcome the natural left,top alignment.

 

I think this might be a significant flaw with GSAP and might be a showstopper for me, which is a huge bummer since everything else is so amazing.

 

See the Pen LvmrC by anon (@anon) on CodePen

Share this post


Link to post
Share on other sites

As the docs say, "x/y translation is always in px (percentage-based translation isn't supported due to the degree to which it would degrade performance, but you can do percentage-based movement using "top" and "left" instead)"

 

The challenge with supporting percentage-based values is twofold:

  1. It requires analyzing the native width/height of the element which can be quite slow. GSAP is highly optimized for performance and we didn't think that the speed degradation was worthwhile since it's so uncommon for people to use percentage-based translation. In other words, we'd rather have things be super fast for the 99% than slow everything down so that we can support an edge case. 
  2. Another performance optimization is using matrix() and matrix3d() values for transforms, but those can't be used for percentages. Extra conditional logic would have to run on each render to define the transform string differently if percentages are used. Again, it comes down to performance (and file size to some degree, but that's not the biggest factor). 

You can certainly get percentages if you either use your own onUpdate logic or create your own plugin for that. Not to make it sound super-simple because...believe me, I know how difficult it is to appropriately handle transforms (vendor prefixes, allowing independent control of each transform component, etc.) but my point is that it's possible. 

 

If you'd like to hire us on a consulting basis to help you create something like that, send me a PM or email and we can look at the schedule and talk pricing. 

 

Really, pretty much anything can be animated with GSAP. 

  • Like 4

Share this post


Link to post
Share on other sites

Hey Gary,

 

I see what you mean but there are a few things to be considered.

 

First instead of using (0,0) in your function you can pass ("-50%","-50%") and the element will be centered according to it's initial values.

 

Second GSAP is not intended to be a responsive or architectural library, is an animation library therefore is highly optimized to perform better than any other out there and with an amazing set of tools in the belt.

 

Third, getting constant updates of the element's current size is not an option because of optimization. I don't know how it would affect performance but Jack's primary concern IS performance.

 

What you could do is create a specific code for each key-up event, in order to recalculate the element's size and then create the tween again in order to keep it in the current position.

 

Rodrigo.

 

EDIT:

There's the official explanation :D

  • Like 2

Share this post


Link to post
Share on other sites

Well, that's unfortunate.  I respect and applaud for ensuring great performance.  I just don't think this would add any overhead, since CSS does it.  I used contenteditable in my example just to show it.  I actually don't know what the user or the data will embed.  I'll muscle through it and try to get it to work, although I'll feel dirty writing a bunch of centering code that I used to get for free, and probably will not perform as well which will mitigate some of the GSAP performance gains.

 

A lot of people are starting with center alignment because it is much more natural: Put something at 0,0 and it is always center of the screen, even if the window is resized, the device is rotated, etc.

 

I believe this could be added to GSAP with zero impact on performance.  Since I don't know where else to put wishlist stuff, I'll describe it here.

 

1] Add a vars special property named entityOrigin or entityAlignment or something like that.  It's default would be 0,0 which is top-left.  This is what it does now.  The value could be an amount to shift the element (e.g. -50% -50%) or a position in the element like CSS' transformOrigin (e.g. 50% 50%)

 

2] If the special property is changed from the default, always emit a transform with a 2d translate that shifts the item in place.  e.g. translate(-50%, -50%).  If there are other transforms, put them after the 2d translate

 

3] The translate() function is always used just for entity origin.  If the x: and y: properties are used, they are always put into translate3d() or matrix().  So you get both, a relative item shift for the origin and a translation to move the element around.

 

Example:  

TweenLite.to(element, time, {x: 75, y: 90, itemOrigin: "50% 50%"});

Would emit...

<div style="transform: translate(-50%, -50%) translate3d(75px, 90px, 0px)">Some Content</div>

The browser, not GSAP, keeps the item aligned by origin (center aligned in this example).  There isn't any performance cost in GSAP.

 

Doing this would have little impact on GSAP performance and make it simpler to build encompassing effects like carousels and coverflows that are generally center oriented.

 

Thanks for all the help.

Share this post


Link to post
Share on other sites

It's not quite that simple, but I really appreciate the thoughtful suggestion. Let me chew on it a bit and see if there's something I could implement that'd be intuitive. Perhaps a "transformOffset" that's just for percentages. There are still some challenges, though, that'd need to be overcome. I'll ponder it. 

  • Like 1

Share this post


Link to post
Share on other sites

Any development on this?  I find I often use gsap to position elements with complex transforms, so performance for handling translate percentages is not a problem.  

Share this post


Link to post
Share on other sites

Yep, I think you're talking about xPercent and yPercent which were added quite a while back :) 

//results in "translate(-50%, -50%) translate3d(100px, 200px, 0)"
TweenLite.to("#element", 2, {xPercent:-50, yPercent:-50, x:100, y:200}); 
  • Like 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.