Jump to content
Search Community

svgOrigin with smoothOrigin issue

WD40andTape 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

Hi all, first of all loving the forums, lots of helpful people creating a wonderful referencing resource. What I'm trying to do should theoretically be very simple, but I've been struggling with it for a week, I've read all of the available documentation and forum posts with no luck.

 

I need to arbitrarily move SVG elements to an absolute position (relative to the viewbox), rotate them around their centers, or rotate them around an absolute position (possibly interrupted during), any number of times in any order.

The problem is that with smoothOrigin DISABLED the elements jump and do not rotate around the intended point, with smoothOrigin ENABLED the elements drift and do not stop at the expected point.

 

Can I reset the svgOrigin so that the new position is in the same coordinate frame?

Anyone have any experience dealing with this? A quick pointer in the right direction would be much appreciated!

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

Edited by WD40andTape
Clarified problem.
Link to comment
Share on other sites

Hm, I can't quite understand what you're trying to do or what the problem is. Can you create a super-reduced test case (maybe with just 2 or 3 tweens) that illustrates the issue clearly? I think that'd help us understand. I didn't notice any odd behavior in the demo you posted, but I might be missing something. 

Link to comment
Share on other sites

7 hours ago, GreenSock said:

Hm, I can't quite understand what you're trying to do or what the problem is. Can you create a super-reduced test case (maybe with just 2 or 3 tweens) that illustrates the issue clearly? I think that'd help us understand. I didn't notice any odd behavior in the demo you posted, but I might be missing something. 

 

Hi GreenSock, thanks for having a look and sorry that you found it ambiguous. Rotating with svgOrigin and smoothOrigin appears to permanently change the global coordinate system for that element, i.e. {x:0,y:0} no longer refers to the top-left corner of the viewbox, and I can't figure out how to reverse that change.

 

I've done as you said and included some more comments, hopefully it helps to clarify things. The red circle shows the expected behavior, the blue circle shows the true behavior. 

 

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

 

Link to comment
Share on other sites

Ah, okay, I see the confusion. You're just misunderstanding how origins work with transforms. 

 

I've added a semi-transparent circle representing the origin for the red as well as the blue circles. Transforms are applied based on the origin:

See the Pen 153fcb667dc8acb1aff03e0041b144c6 by GreenSock (@GreenSock) on CodePen

 

So, for example, when you rotate, it's obviously rotating around that origin (100,100). Then, you're telling the blue circle to move 100px down (y:100) which it does. And you told the red to move -200px on the x-axis (x:-200), which it does. Again, watch the origins. 

 

It sounds like maybe you thought that  every x/y coordinate would be relative to the top left corner of the entire SVG document (?) But no, just like with CSS transforms (or really any transform system including SVG), it's relative to the origin which, in this case, you set to 100,100 initially. 

 

Does this clear things up? 

 

You could certainly put a function in place that'd do conversions for you if your goal is to have coordinates based on something else. 

  • Like 4
Link to comment
Share on other sites

Thank you, that certainly does help my understanding. I had also assumed that GSAP was doing the maths in the background to convert from transforms to global coordinates, e.g. so that rotations would cause a coordinate change.

 

Having said that, I'm still not sure how to tackle this. To restate I need 3 operations, all of which could be interrupted midway:

1. Rotate elements around an absolute position (relative to the top left of the entire SVG).

2. Move elements to an absolute position, e.g. [0,0] so that the circle sits at the top left of the SVG.

3. Rotate elements around their centers.

It's the combination of the first two which introduces the complexity, while the third is simple.

 

I guess I could either retrieve and transform between each of the coordinate systems, or write a function to perform point 1 using points 2 and 3. Any guidance? I'd be surprised if no one has come across this before.

Link to comment
Share on other sites

I think understanding how transforms work makes more sense if you start with canvas. There is no transform origin. And without a matrix, you have to do a series of transforms, and apply them in a certain sequence, which I learned as the acronym STARS. 

 

S - save (relevant to canvas)

T - translate to x and y

A - align (translate again to transform origin x and y)

R - rotate

S - scale

 

The translation will move the origin like this.

fkXnq54.jpg

 

And rotation rotates the axes like this. However, since translation happens before rotation, translating on the x axis will be horizontal, even when rotated 90 degrees.

S82IPFZ.jpg

 

 

And as you can see here, that is exactly what GSAP is doing. The yellow box is canvas using the STARS method, the red box is SVG using GSAP, so there's nothing unusual about what's happening. It's just a little confusing.

 

To do what I think you're asking, you might need to do some trig. Here's a thread with some good examples that might help you out.

 

 

  • Like 5
Link to comment
Share on other sites

Hi OSUblake, first of all true to your title you're an absolute superhero - thank you! Based upon your answer I've spent a while creating an orbit method to manually calculate and set the correct x, y, and rotation at each frame. Hopefully others will find it useful in the future. :)

 

 

See the Pen YQydKQ by WD40andTape (@WD40andTape) on CodePen

 

Link to comment
Share on other sites

Hi @WD40andTape

 

I saw your message earlier, but it looks like I might be a little late getting back to you.

 

It's ok to ask for help. This forum is not like Stackoverflow, so nobody is going to accuse you of trying to freeload. Especially, with what you are trying to do. There aren't a lot of people that would be able to figure that out on their own.

 

One of the hardest things about working with transformed objects is figuring out its global position. You can simplify that calculation using a matrix or with vectors. Check out this little gem I posted the SVG Gotchas thread.

That's what I use to figure out how the bounding boxes are rotated later on in that thread.

See the Pen ZKGjRo?editors=0010 by osublake (@osublake) on CodePen

 

It's nice how SVG comes with it's own matrix, but for simpler stuff, it might be easier using vectors. In the thread I linked to earlier, I posted a demo based on vectors. What's going won't make sense unless you open it up in CodePen so you can see the console. For brevity, I didn't set the demo up to animate the actual rotation being applied, but the dots are moving to the correctly rotated end position.

 

 

 

I can take a look at your code later, but I think you might be able to use some of those techniques.

 

 

  • Like 3
Link to comment
Share on other sites

Hey @OSUblake, thanks, that's nice of you! :) ooh boy those are useful helper functions  - the transforms and bounding boxes were doing my head in - and particularly I think that I can learn from the code organisation in the last demo, shows your experience with the library!

 

My code is pretty simple bar the 'gotchas', it essentially: waits until the given time; calculates the element's transformed properties; calculates distance and angle to the rotation point; tweens these, using trig to calculate the updated position at each step; adds an instantaneous 'set' at each frame with the updated position.

 

That last step is required to actually follow the correct arc as it rotates, in your example the dots transition along a line from the start to end point of the rotation. That last step is also what is causing lag in more complex scenarios and inconsistencies if the rotation is interrupted (tweens normally just pverwrite current tweens, moving from the current to the next point). Any thoughts?

  • Like 1
Link to comment
Share on other sites

  • 3 months later...
On 12/06/2017 at 8:42 PM, OSUblake said:

My last example does everything you need. I didn't set it up to show the actual rotation being animated, but it can rotate around any point without any adjustments. I can show you later.

 

 

Hi @OSUblake, hope you're well, I'm back once again. :lol: I looked over your code again and for sure the ObservablePoint.rotate() function just calculates the end point of the rotation and the callback tweens to that point without any curvature (linearly). It becomes really clear what I'm talking about if you try to do an 180 or 360 degree rotation.

 

However, some space from the problem helped me think! I updated my function to precompute the rotation as a Bezier path, rather than setting the element's properties instantaneously at each proxy update. It seems less laggy, can be stopped or interrupted (overwritten) as expected, and generally integrates with the timeline more naturally. Hopefully something like this can be integrated into GSAP officially as it seems pretty basic but took a whole lot of work - I'm sure it can be improved more too!

 

See the Pen gGxZKR by WD40andTape (@WD40andTape) on CodePen

 

 

Link to comment
Share on other sites

The Bezier approach seems to work pretty good.

 

I don't know if this will simplify anything, but instead of making it linear, you could compute an arc path sort of like this demo, and then use the MorphSVGPlugin or Snap's toCubic method, and extract all the points to make a cubic Bezier motion path.

 

See the Pen OmgMNm?q=arc%26limit=mine by osublake (@osublake) on CodePen

 

 

 

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