Jump to content
Search Community

MorphSVG on <g> error

iggy 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

Hey all,

 

I wanted to create a MorphSVG transition to look something like this. I drew a simple hamburger icon and "real" hamburger icon on sketch. It is a group of <g> with <rectangle> and <path> inside. I converted the non-path elements using 

 

MorphSVGPlugin.convertToPath("circle, polygon, rect, ellipse");

 

When I attempted to do morphSVG, it fails with this message:

WARNING: cannot morph a <G> element. Use MorphSVGPlugin.convertToPath(elementOrSelectorText) to convert to a path before morphing.

I have checked other forum post like this one and another similar one, but I am still seeing the error.

 

What am I missing?

See the Pen gqgdRM by iggyDood (@iggyDood) on CodePen

Link to comment
Share on other sites

There are actually a few problems:

  1. Morphing works by animating between two "d" attribute values on a <path> element. You cannot morph all the children of a <g> with a single tween (which is what your demo is attempting). So create a tween for each <path> instead. 
  2. You stored a reference (variable) to a specific element and THEN you ran MorphSVGPlugin.convertToPath(), but when you run that function it actually must create NEW elements to replace the original ones, so your reference isn't valid anymore. So make sure you run MorphSVGPlugin.convertToPath() FIRST, and then reference the [new] elements. 

Once challenge you've got is that your simple burger only has 3 elements, but the real burger has 4, thus they're mismatched. Of course you could just fade the 4th one in or something if you want. Totally up to you. 

 

I took a crack at writing a utility function for you that'll accept a group as the target as well as the morphSVG end value, and make it simpler: 

 

function morphGroup(start, duration, vars) {
  if (typeof(start) === "string") {
    start = document.querySelector(start);
  }
  var startChildren = start.children,
      shape = (typeof(vars.morphSVG) === "string") ? vars.morphSVG : vars.morphSVG.shape,
      end = (typeof(shape) === "string") ? document.querySelector(shape) : shape,
      endChildren = end.children,
      l = Math.min(startChildren.length, endChildren.length),
      _copy = function(original, add) {
        var o = {},
            p
        for (p in original) {
          o[p] = original[p];
        }
        for (p in add) {
          if (p === "morphSVG" && typeof(o[p]) === "object") {
            o[p] = _copy(original[p], {shape:add[p]});
          } else {
            o[p] = add[p];
          }
        }
        return o;
      },
      tl = new TimelineMax(),
      toFade, i;
  for (i = 0; i < l; i++) {
    tl.to(startChildren[i], duration, _copy(vars, {morphSVG:endChildren[i]}), 0);
  }
  if (startChildren.length > endChildren.length) {
    for (i = endChildren.length; i < startChildren.length; i++) {
      tl.to(startChildren[i], duration, _copy(vars, {autoAlpha:0}), 0);
    }
  } else if (startChildren.length < endChildren.length) {
    TweenLite.set(end, {autoAlpha:1}); //make sure the container is visible. 
    TweenLite.set(endChildren, {autoAlpha:0});
    for (i = startChildren.length; i < endChildren.length; i++) {
      tl.to(endChildren[i], duration, _copy(vars, {autoAlpha:1, x:0, y:0}), 0);
    }
  }
  return tl;
}

 

I noticed you've got different transforms applied to orient the start/end shapes, so the raw coordinates don't line up. That's why I animated the x and y values too. So your call could look like: 

 

morphGroup("#simple-burger", 1, {delay:1, morphSVG:"#real-burger", ease:Power1.easeInOut, y:-13.5, x:-5});

 

Demo: 

 

Does that help at all? 

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

Absolutely! This is very useful. I didn't realize some of these behaviors of MorphSVG - but after you explained it, it makes perfect sense! (I had a hunch earlier that my real-burger has 4 elements while the icons have 3 and it would cause problem - and you verified it). I looked at the code and it makes sense. 

 

I think in my case, it'd be much more painless in the future if I created equal amount of paths next time to have 1-1 morphing (so we don't have to worry about it). I modified my SVG at Sketch. I really appreciate the explanation and you taking your time with morphGroup function. I am saving the function for future reference. Thanks @GreenSock for prompt response and thorough explanation. 

 

I have updated my Codepen. I think it looks much better. Thank you for the help.

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