Jump to content
GreenSock

celli

MorphSVG and Shape Index

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 Guys!

 

I am working with the MorphSVG plugin and testing things out with the shape index to make the morph line-up with similar points from one shape to the next. If you see the codePen, I think I picked the most compatible ShapeIndex number, but still you see the SVG overlaps (any way to avoid that?)... I am wondering if there is a way to align certain points so that it morphs in a more natural way ?

 

I remember in Flash there was a way to align points with the shapeTweens, so you would align point A to point A, and B to B on the morphing shapes to help guide which points will morph with each other. For instance, I would like the snake head not to morph at all because that is the same on both shapes--the only way I can think of to get that to work, would be to separate the snake-head on each shape, and only morph the body, but that might produce unexpected results as well... any guidance would be grateful!

See the Pen RWebeM by celli (@celli) on CodePen

Link to comment
Share on other sites

You're code is wrong so you're not actually setting the shape index. You also had an extra quotation mark in your SVG.

 

See the Pen qOJEVe?editors=101 by osublake (@osublake) on CodePen

 

The plugin was actually auto selecting 28 for you. 

 

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

 

Making that morph look good is probably not going be easy. It's actually very similar to my grass demo, but I'm only using morphing to make the blades grow, and not to move them around. 

 

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

 

The main problem with your animation is that the Bezier points are crossing over each other. A lot of this is caused by the start of your path being in the center of one of the snakes. I think you could solve some of the crossing over problem by splitting your snakes up into different paths. A left side, a right side, and no head. You could then apply those paths to some dummy elements and morph them. On each update you would have to get the current path from the dummy elements, combine them, and then apply the path to the real element.

 

This would probably be much easier to do if the morphSVG plugin did not require the object to be an SVG element. I know how to trick it, but I'm not going to get into that.

  • Like 4
Link to comment
Share on other sites

Thanks OSUblake, this makes sense. I fixed most of the things and it looks pretty good--but I guess it's a bit of trial and error, to see what two shapes work best together, see updated codepen: 

See the Pen epPJzr by celli (@celli) on CodePen

. I assume there might be a way to make sure the bezier curves are more smooth ? If you see here it would look better if the curves stayed smoother as they morphed... what do you think ?

Link to comment
Share on other sites

wow. that's a nice improvement, celli.

 

 

Great advice, Blake!

  • Like 1
Link to comment
Share on other sites

Nice work guys. One other idea in a case like this is to actually take your more complex shape (the curvy one), copy it, and inside a program like Illustrator, just move the points yourself to make the new shape. That way, both paths should start/end at the same spot along the path, they'll have matching numbers of points, and they should animate in a very predictable way (at least in theory, unless Illustrator messes with things in an odd way when exporting). You could set the shapeIndex to 0 in that case, just to make sure MorphSVGPlugin doesn't auto-select some other value thinking that it's "better" (it selects the one that make the points travel the shortest distance overall which is usually exactly what you want, but not always). 

  • Like 4
Link to comment
Share on other sites

A new CodePen is pasted below per Jacks suggestion to make the new shape more matching to the curvy one, is much better !

I guess snakes are never really straight anyway :)

See the Pen vNVyMR by celli (@celli) on CodePen

  • Like 1
Link to comment
Share on other sites

Your snake needs more points. The plugin has a method to add more points to a path by subdividing. I can explain how to do that later, but adding more points will prevent the curves from distorting. Look at the animation in this tweet. It's pretty much what you are trying to do.

 

https://twitter.com/OSUbowen/status/654347001811849217

Link to comment
Share on other sites

OSUblake... yea that is Awesome! How do I subdivide path to add more ? Are there docs on that ?

Link to comment
Share on other sites

It's not documented and it requires a couple of other steps, but I can walk you through it. Nothing hard. I'll make something later tonight to show you how to do it.

 

The reason a curve can become distorted during a morph is that the control points can become unaligned with each other. Kind of like when you hold ALT down while drawing with the pen tool. The handles are no longer linked with each other. Making sure the number of points are equal is part of the solution. If that doesn't work, adding more points will reduce the problem. The trade-off is that the more points you have, the slower it will run, so you have to find the right balance.

  • Like 1
Link to comment
Share on other sites

I've been playing around with trying to morph "S" shaped curves like your snake, and I'm not having much luck. Maintaining a continuous curve seems pretty hard to do using only morphing for that shape. I tried several different techniques, including converting the shape into a polygon, and the problem still persisted. If a polygon has the same problem as a Bezier curve, that means the problem will most likely not go away by adding more subdivisions. The morph is creating cusps on the path, which is a condition where the path will fold or reverse on itself. No matter how many subdivisions you add, the cusp will still be there.

 

hWv758S.gif

 

 

To fix a problem like that, the morph would need to use an adaptive technique to constantly change the number of subdivisions in a shape. Unfortunately, the morph plugin cannot do that because internally it has to use an equal number of points during a morph. I was thinking that you might be able to be able to create a more adaptive-like morph by using more than 1 shape. Instead of morphing from shape A to shape B, you could create keyframe shapes to morph to, A to B, C, D, etc. Maybe something like this...

var morph = new TimelineMax({ paused: true })
  .to("#path", 1, { morphSVG: "#morphA", ease: Power0.easeNone })
  .to("#path", 1, { morphSVG: "#morphB", ease: Power0.easeNone })
  .to("#path", 1, { morphSVG: "#morphC", ease: Power0.easeNone })
  .to("#path", 1, { morphSVG: "#morphD", ease: Power0.easeNone });

TweenMax.to(morph, 2, { progress: 1 });

Even though adding more subdivisions doesn't seem to fix the problem for your particular case, I still made a demo to show how to do it. There's a lot of utility uses for subdividing, so other people might find this useful. It's pretty straightforward. Get. Convert. Subdivide. Convert. Set.

// Get the path data
var data = $("#path").attr("d");

// Convert data to bezier points
var bezier = MorphSVGPlugin.pathDataToRawBezier(data)[0];

// Subdivide
MorphSVGPlugin.subdivideRawBezier(bezier, 10);

// Convert bezier back to path data
var p = bezier;
data = "M" + [p[0], p[1]];

for (var i = 2; i < p.length;) {    
  data += "C" + [p[i++], p[i++], p[i++], p[i++], p[i++], p[i++]];
}

// Set path data back on element
$("#path").attr("d", data);

The morph isn't horrible, but it could be better...

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

  • Like 5
Link to comment
Share on other sites

great advice, and totally expands on the awesomeness of GSAP morphSVG! I love it!!

Link to comment
Share on other sites

The MorphSVG plugin is pretty freaking amazing and worth more than the price of a license. Morphing may be the star attraction of the plugin, but it also brings a new level of functionality to GSAP by giving users a fast way to access SVG path data.

 

When I saw the plugin exposed a method for this, I immediately knew what this could be used for, motion paths. I'm sure this will evolve into something else with more functionality, but for now you can use the plugin to create the values for a motion path in one line of code.

var values = MorphSVGPlugin.pathDataToBezier($("#path").attr("d"));

Add those values to the bezier plugin, and in no time at all you can have Sonic the Hedgehog running through a loop...

 

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

 

And why should SVGs have all the fun? We have access to path data, so that means we can use those values with the canvas. All it takes is a couple lines of code to get a morph working with the canvas. Check out a canvas and SVG morph running side-by-side. Can you tell the difference? 

 

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

  • Like 6
Link to comment
Share on other sites

oh man, that is really amazing. I love the motion path thing!

  • Like 1
Link to comment
Share on other sites

That's fantastic, Blake. Yeah, MorphSVGPlugin can totally be used for a bunch of other stuff, not just SVG. Thanks for showing a great canvas example! 

  • Like 1
Link to comment
Share on other sites

Thanks! This is why I love cubic Beziers.

 

The whole canvas thing is pretty is pretty awesome. I don't know what shocked me more. That it worked on my first attempt or that it looked exactly the same as the SVG. I can only imagine the type of the things that you could do using morphing with a powerful WebGL library like Pixi or Three. Now I need a method where I don't have to use an element as a proxy.

 

@Celli

The biggest problem people have with using the Bezier Plugin is that they can't visualize the path. This changes everything, and again is reason enough to become a club member. Check out Chris Gannon's creature using a motion path. Pretty awesome!

 

See the Pen qOawzL?editors=001 by chrisgannon (@chrisgannon) on CodePen

 

Here's the first motion path demo I made a couple of months ago. It's a little more complicated because it's using SVG and canvas. It's also responsive.

 

See the Pen 8e400cc14efe3cde1656728e0fb5e964?editors=001 by osublake (@osublake) on CodePen

 

  • Like 3
Link to comment
Share on other sites

  • 3 years later...
On 11/8/2015 at 2:09 PM, OSUblake said:

The morph isn't horrible, but it could be better...

I've seen a demo somewhere that tangled a line into knots (cusps), each of which disappeared smoothly, so perhaps there is a more straightforward way to do it. I wish I could say where the demo was or how it was made, but I spend hours here and there intensely browsing for ideas and frameworks, taking few notes, sorry. I do remember being impressed by the way the cusps disappeared so smoothly (I think topologically that cusps cannot disappear like that because they have to lead to singularities). (The opinions expressed here are opinions.)

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