Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
garyw

Animating position doesn't work when container is scaled

Recommended Posts

I am creating a drag & drop exercise. When the user is done dragging, the dragged object should automatically animate to its target.

 

This works correctly in normal circumstances. However, when the parent container is scaled, the calculation for determining the target position does not work and the dragged object does not land correctly on the target.

 

I thought it might be related to dragging using x and y, so I changed the code to use left and top. I still have the same issue.

 

You can see the issue in the CodePen. The viewport container element automatically resizes to fit the browser window/frame.

 

Note that I use a function called getDocumentRelativePosition (which can be seen in the CodePen) to determine the left and top values of elements, because in practice, the dragged object can be inside a different relative container than the target object.

 

Any ideas?

 

See the Pen jOEdWLK by og-elmonty (@og-elmonty) on CodePen

Edited by garyw
Updated tags
Link to post
Share on other sites

This isn't really a GSAP issue, but I love challenges like this...

 

The problem is that you're calculating things based on the global coordinate system which is what getBoundingClientRect() uses, but your elements are nested inside of a transformed parent, so it throws all those measurements off. For example, if getBoundingClientRect() shows that the elements are 100px away from each other, but they're inside a container that's scaled to 0.5, they're actually 200px away from each other according to their local coordinate system. 

 

When you start nesting things in DIFFERENT parents, it gets even more complex. I'm not aware of any other tool out there that does these calculations for you...but I have good news. There's a secret MotionPathPlugin.getGlobalMatrix() method that's like magic for situations like this. I whipped together a function that you can feed two elements to and it'll spit back the gap according to the fromElement's parent coordinate space (which is what you need in order to move it correctly). Here's a fork of your codepen: 

See the Pen dyPaRRw?editors=0010 by GreenSock (@GreenSock) on CodePen

 

In your demo, try nesting the "drag me" element in a completely different element, and transform things in funky ways - it should still perfectly line up their top left corners when you release. 🎉

 

And here's another codepen that shows a bunch of nested elements with various transforms and we're able to pin the red dot on the top left corner of the inner-most element: 

See the Pen 65112f4c320a2175d043cc626e6479d8 by GreenSock (@GreenSock) on CodePen

 

I hope that helps!

  • Like 3
Link to post
Share on other sites

Jack, you are a lifesaver. Thanks so much!

  • Like 1
Link to post
Share on other sites

I just enhanced the helper method a bit so that you can control the alignment origins (like [0, 0] for the top left corner, [0.5, 0.5] for the center, [1, 1] for the bottom right, etc.) and added it to the helper functions section of the official docs. Here's a revised demo: 

 

See the Pen gOYymrg?editors=0010 by GreenSock (@GreenSock) on CodePen

 

By default now, it'll align the centers.

  • Like 1
Link to post
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.

×