Jump to content
Search Community

SVG Coordinates Instead of Relative Units for Movement

Noa 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

I'm attempting to animate an SVG shape along an existing SVG polyline. I'm trying to determine if this is possible to do using Timeline Max and animating to each of the points of my polyline progressively. I know I can pass x and y values a given element (say, "#tile") should be moved relative to its current position:

 

tl.to("#tile", 0.5, {x:0, y:285.4})

 

but I'd like to know if it's possible to pass specific coordinates for the SVG canvas so the element can move to those coordinates rather than just a set number of units from its current position. This way, I could enter the coordinates for each point on my polyline and have the #tile element move to each progressively.

 

The reason I'd like to move to actual SVG coordinates is that I want this svg and animation to be resizeable, and it also seems to be the most logical way to follow an existing path/polyline in an SVG.

 

I have an in-progress codepen showing the polyline I'd like to follow along with some tweening with the relative position that I'd like to replace with coordinates: 

 

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

 

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

Link to comment
Share on other sites

Hi and welcome to the GreenSock forums,

 

The easiest way to get something to follow a polyline would be to  use MorphSVG to convert your path data from your polyline to an array of points and then pass those points to the BezierPlugin as explained here: https://greensock.com/path-animation

 

I made a demo showing how that would work

 

var path = MorphSVGPlugin.pathDataToBezier("#route", {align:"#tile"});
console.log(path);
TweenMax.set("#tile", {xPercent:-50, yPercent:-50});// center tile on path
TweenMax.to("#tile", 8, {bezier:{values:path, type:"cubic"}, ease:Linear.easeNone})

 

See the Pen KxbqEd?editors=0110 by GreenSock (@GreenSock) on CodePen

 

If you want to use MorphSVG you can upgrade your membership to a Shockingly Green via your account dashboard

 

///

 

If you want to manually translate the coordinates of your #tile so that you can animate to coordinates on your line please read this post (especially blake's final demo)

 

You'll see that each chicken animates from the center of the box.

 

 

 

 

 

  • Like 6
Link to comment
Share on other sites

48 minutes ago, Noa said:

but I'd like to know if it's possible to pass specific coordinates for the SVG canvas so the element can move to those coordinates rather than just a set number of units from its current position. This way, I could enter the coordinates for each point on my polyline and have the #tile element move to each progressively.

 

Here's a tip. Don't position stuff you're going to move where you initially want it. If you drew your tile at 0,0 or centered on 0,0 you could easily move it to a coordinate on your polyline without any issues.

 

 

 

 

 

  • Like 6
Link to comment
Share on other sites

Thanks Craig! I'm thinking of independently animating each segment of the polyline so I can have the tile move to the end of the first segment, then wait for a click and continue to the second segment, etc. Would the best way to do this with MorphSVG be to break the path out into multiple polylines, or is there a way to achieve this level of control with MorphSVG and a single polyline?

Link to comment
Share on other sites

Craig,

 

Thanks, this is really helpful! I've been reading through the docs to try to find a way to specify a point on the path (as opposed to a percentage) to animate to - I see that I may be able to use addLabel(), but that's still only allowing positions in the timeline for positioning, not a point on the polyline. Is there a method that might allow me to accomplish that?

 

Maybe as a workaround, I should determine at what point in the timeline the tile will have reached each point on the polyline and add labels at those time points?

Link to comment
Share on other sites

You can make it work with the progress() method and no labels. All you need to do is measure each segment and divide that by the totalLength() of the polyline. Push those results into an array and you'll have a progress stop for each point. I forked my pen from above and changed the path to a polyline. How about something like this?

 

See the Pen PdXLja by PointC (@PointC) on CodePen

Hopefully that helps. Happy tweening.

:)

 

 

  • Like 5
Link to comment
Share on other sites

Nice job, @PointC

 

I made a demo to show the tile drawn centered at 0,0 and a lot of your code looks like mine. One issue though, .getTotalLength() won't work on a polyline/polygon with browsers from Seattle, so you should convert it to a path. Well maybe a clone so you don't have to deal with messing up the actual polyline points.

 

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

 

 

  • Like 4
Link to comment
Share on other sites

47 minutes ago, OSUblake said:

One issue though, .getTotalLength() won't work on a polyline/polygon with browsers from Seattle, so you should convert it to a path. 

 

ahhh... good catch. I like to pretend those browsers don't exist. ;) I actually thought .getTotalLength() worked for polylines, but I stand corrected. I made the switch in my demo. I just used my highlight path since it was a duplicate of the polyline.  

:)

 

  • Like 1
Link to comment
Share on other sites

.getTotalLength() for other shapes like a polyline is part of SVG 2.

https://developer.mozilla.org/en-US/docs/Web/API/SVGGeometryElement/getTotalLength

 

And Microsoft is like, meh... it can wait.

https://developer.microsoft.com/en-us/microsoft-edge/platform/status/svg2/?q=svg

 

 

I totally forgot about this. You can get the length using the DrawSVGPlugin.

 

var totalLength = DrawSVGPlugin.getLength(polyline);

 

  • Like 5
Link to comment
Share on other sites

12 hours ago, OSUblake said:

I totally forgot about this. You can get the length using the DrawSVGPlugin.

 

How did I not know that? Or did I know and forgot about it? ? 

 

I honestly can't tell anymore if I'm learning something for the first time or it's something I knew and it fell out of my thick skull. 

  • Haha 2
Link to comment
Share on other sites

I'm currently working on incorporating the segmented animation for the polyline and tile, but for some reason the animation stops are not aligning with the segments - can anyone see what I may be missing? The animation distances seem to become progressively smaller until the last, rather than moving from point to point. Here's a pen with my progress: 

See the Pen MqLvGp?editors=0010 by anon (@anon) on CodePen

 

Link to comment
Share on other sites

You're seeing the easing there. With Linear easing, your point on the path at progress(0.5) will be halfway on the path. But other types of easing will not necessarily be at the point you expect. They could be far ahead of the halfway point or way behind it. 

 

Switch line 25 to this and you'll be good to go.

tl.to("#tile", dur, { bezier:{values:path, type:"cubic"}, ease:Linear.easeNone });

 

See the Pen NLoEoJ by PointC (@PointC) on CodePen

 

If you want some easing between jumpPoints, you can add that to the tween on line 43.

 

Happy tweening.

  • Like 4
Link to comment
Share on other sites

Sure, happy to help. Just in case my explanation of the easing was as clear as mud, I made a quick demo for you. It has three boxes that all tween 400px on the x and they all start at the same time. You can drag the slider to control the progress of the timeline. You'll see at 50% the Linear tween is exactly at the halfway point where you would expect it to be whereas the easeIn looks like it barely started and the easeOut looks like it's about finished.

 

See the Pen aaXXwP by PointC (@PointC) on CodePen

Hopefully that helps a bit.

 

As @Carl mentioned earlier in the thread, you can upgrade to Shockingly Green to start using that MorphSVG plugin in the wild.

 

Let us know if you have any more GSAP questions. Happy tweening.

:)

 

  • Like 6
Link to comment
Share on other sites

I have one more question (although I'm not sure if it would be better to break this out into a separate post): I've been working on changing a class on the #tile element so the tile's color corresponds to the direction it's traveling. I'm using the onStart parameter of TweenMax.to(), but the issue is that starting a new tween before the last is complete seems to immediately trigger the onComplete, resulting in the class being added before the tile is on a given segment/direction. Is there a way to delay the calling of a function until the tile has reached a certain segment?

See the Pen MqLvGp?editors=0010 by anon (@anon) on CodePen

(clicking 'next' a few times quickly causes the classes to change before the tile has arrived on the relevant segment).

Link to comment
Share on other sites

I'm not sure I totally understand your question, but it looks to me like the appropriate thing to do would be to apply those class changes INSIDE the main timeline that has the other movement animations so that they're perfectly synchronized. You could do it with className tweens or with callbacks or whatever. 

  • Like 2
Link to comment
Share on other sites

8 hours ago, GreenSock said:

I'm not sure I totally understand your question, but it looks to me like the appropriate thing to do would be to apply those class changes INSIDE the main timeline that has the other movement animations so that they're perfectly synchronized. You could do it with className tweens or with callbacks or whatever. 

 

Yep - that's exactly what we did for this project. For anyone following along now or in the future, this conversation/project continued in this thread.

 

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