Search code examples
javascriptanimationsvgfrontendgsap

How do I replicate the exact animation done on flecto.io hero section


I came across https://flecto.io(use a vpn if the site doesn't open) and the site caught my attention. I want to replicate the animation in the hero section. To be more precise, that is the part where the green rectangle turned into a cross-like shape.

Starting shape enter image description here

Final Shape (I removed unwanted distractions) enter image description here

I understand that this could be done with the use of gsap morphSVG plugin. But I am finding the use of that plugin for this purpose to be difficult. Here is a link to the demo I am working on Here.

HTML

<div class="container">
    <svg viewBox="0 0 1900 1500" fill="none">
      <g>
        <path id="rectangle" d="M0 0H1889V157V758V915H0V758V178.5V0Z" fill="black"/>
       
         <path id="final-stage" class="hide" d="M505.5 125.5H22.5H19C9.05887 125.5 1 133.559 1 143.5V774C1 783.941 9.05887 792 19 792H198.5C208.441 792 216.5 800.059 216.5 810V898C216.5 907.941 224.559 916 234.5 916H1426.5C1436.44 916 1444.5 907.941 1444.5 898V809.5C1444.5 799.559 1452.56 791.5 1462.5 791.5H1872C1881.94 791.5 1890 783.441 1890 773.5V144C1890 134.059 1881.94 126 1872 126H1385.5C1375.56 126 1367.5 117.941 1367.5 108V19C1367.5 9.05887 1359.44 1 1349.5 1H541.5C531.559 1 523.5 9.05888 523.5 19V107.5C523.5 117.441 515.441 125.5 505.5 125.5Z" fill="black" stroke="black" />
      </g>
    </svg>
  </div>

CSS

.container {
  width: 800px;
  height: 800px;
  display: flex;
  justify-content: center;
  align-items: center;
}
svg {
  width: 100%;
  height: 100%;
}

.hide {
  visibility: hidden;
}

Javascript (I am using gsap plugin, and gsap morphSVG plugin on codepen)

gsap.registerPlugin(MorphSVGPlugin);

// MorphSVGPlugin.defaultType = "rotational";

var tl = gsap.timeline();
const rectangle = document.getElementById("rectangle");

  tl.to(rectangle, { duration: 1, morphSVG: {shape: "#final-stage", shapeIndex: -2 }});

This was my result https://streamable.com/mnh46o (this content might not be available in the future)

The thing is that after inspecting the site, the creators didn't morph a rectangle into a cross. They broke down their shape into smaller forms, consisting of two frames with different builds.

enter image description here

Notice that the first frame is a solid shape that has a cut out of a cross, while the second is a combination of several shapes that form the cut out of a cross. Why did they build the hero section this way? I am yet to figure it out. But I believe that this method is what makes their animation smoother than my method of morphing an SVG into a cross.

So, what do you all think? How can I replicate this design? What is the best method to do this?


Solution

  • You need two paths; the starting and ending path. The animation can either be done using CSS animations or with SVG animation with SMIL.

    In you code there are 27 commands in the ending path, so you should have the same number of commands in the starting path.

    Here, I have created a "crude" version where the starting path is just a square, the commands are relative, and most of the commands just have zeros. In a production ready version you would match all the commands so that they move in the right way and also maintain the rounded corners.

    path {
      d: path('m 1 1 h 0 h 0 c 0 0 0 0 0 0 v 915 c 0 0 0 0 0 0 h 1889 c 0 0 0 0 0 0 v 0 c 0 0 0 0 0 0 h 0 c 0 0 0 0 0 0 v 0 c 0 0 0 0 0 0 h 0 c 0 0 0 0 0 0 v -915 c 0 0 0 0 0 0 h 0 c 0 0 0 0 0 0 v 0 c 0 0 0 0 0 0 h -1889 c 0 0 0 0 0 0 v 0 c 0 0 0 0 0 0 z');
      animation-duration: 3s;
      animation-name: anim;
      animation-fill-mode: forwards;
    }
    
    @keyframes anim {
      from {
        d: path('m 1 1 h 0 h 0 c 0 0 0 0 0 0 v 915 c 0 0 0 0 0 0 h 1889 c 0 0 0 0 0 0 v 0 c 0 0 0 0 0 0 h 0 c 0 0 0 0 0 0 v 0 c 0 0 0 0 0 0 h 0 c 0 0 0 0 0 0 v -915 c 0 0 0 0 0 0 h 0 c 0 0 0 0 0 0 v 0 c 0 0 0 0 0 0 h -1889 c 0 0 0 0 0 0 v 0 c 0 0 0 0 0 0 z');
      }
      to {
        d: path('M505.5 125.5H22.5H19C9.05887 125.5 1 133.559 1 143.5V774C1 783.941 9.05887 792 19 792H198.5C208.441 792 216.5 800.059 216.5 810V898C216.5 907.941 224.559 916 234.5 916H1426.5C1436.44 916 1444.5 907.941 1444.5 898V809.5C1444.5 799.559 1452.56 791.5 1462.5 791.5H1872C1881.94 791.5 1890 783.441 1890 773.5V144C1890 134.059 1881.94 126 1872 126H1385.5C1375.56 126 1367.5 117.941 1367.5 108V19C1367.5 9.05887 1359.44 1 1349.5 1H541.5C531.559 1 523.5 9.05888 523.5 19V107.5C523.5 117.441 515.441 125.5 505.5 125.5Z');
      }
    }
    <svg viewBox="0 0 1900 1500">
      <path fill="black" stroke="black"/>
    </svg>