31st October, 2017

Animating Clipped Shapes

See the Pen SA 15 by Varun Vachhar (@winkerVSbecks) on CodePen.

Another #postAboutYourPen post. This time I’m going to explain how I recreated Herry Koo’s SA 15 dribbble shot using SVG and animejs.

The Ingredients

An arc is a section of circle or an ellipse. To create this arc you need the starting point, the end point and the radius of the circle that these two points are on. There are two circles that can connect any two points: a big one and a small one. SVG allows us to pick which one we want using the large-arc-flag. We can also control whether the arc should be drawn clockwise or anti-clockwise using the sweep-flag.

A rx ry x-axis-rotation large-arc-flag sweep-flag x y

Dribbble shots are 800 x 600px so that’s what I picked for the vieBox. This makes it easy to open the gif in Preview, measure stuff and use those values in the SVG. I measured the circle to be 113px. The left slice was 154px wide and the right slice 72px. With a bit of trial and error I found the start and end-points of the arcs. I drew the arcs using the path element.

<!--
  Move to the starting point then draw an arc to the end point
  and close the shape by going back to the starting point

  M start_x start_y A 113 113 0 large-arc-flag 1 end_x end_y Z
-->
<path class="js-left-slice"
  d="M 441.6 405 A 113 113 0 1 1 441.6 195 Z" />

<path class="js-right-slice"
  d="M 441.6 195  A 113 113 0 0 1 441.6 405 Z" />

See the Pen SA 15 Process 1 by Varun Vachhar (@winkerVSbecks) on CodePen.

These paths create the outline. The sliding fill inside them was created using clipped rectangles. For the clipPath we use the same paths as the outline and then apply them to the rectangles using the clip-path attribute.

<defs>
  <clipPath id="left-slice-mask">
    <path d="M 441.6 405 A 113 113 0 1 1 441.6 195 Z" fill="#fff" />
  </clipPath>
  <clipPath id="right-slice-mask">
    <path d="M 441.6 195  A 113 113 0 0 1 441.6 405 Z" fill="#fff" />
  </clipPath>
</defs>
<rect
  class="js-right-fill"
  x="441.6" y="187" width="72" height="226"
  clip-path="url(#right-slice-mask)"
/>

To slide the fill in-and-out I animate the x value using animejs. The clipPath remains static. It’s only the rectangles that are moving.

See the Pen SA 15 Process 2 by Varun Vachhar (@winkerVSbecks) on CodePen.

The combined shape is moved up-down and left-right by animating translateX and translateY. We apply the same animation at the same time to both the arc slice and clipped rectangle. Note, you do not need to animate the position of the clipPath.

See the Pen SA 15 Process 5 by Varun Vachhar (@winkerVSbecks) on CodePen.

The little circle that burst out. Well… that’s just a circle. At the appropriate time I hide the left slice and rectangle and show the circle instead. The circle scales down as it moves to the left and then stretches — using scaleX — as it moves back to the right.

See the Pen SA 15 Process 3 by Varun Vachhar (@winkerVSbecks) on CodePen.

The squirmy line effect that everything has is known as squigglevision. I used the code from this example.

See the Pen SA 15 Process 4 by Varun Vachhar (@winkerVSbecks) on CodePen.

The rest is all about matching the movement and timing of the original animation.

Here are a couple more examples of animating clipped shapes. For these I used a slightly different technique. They have shapes which are filled with an animated SVG pattern.