SVG Shape Morphing Animation using Anime js

SVG shape transformation/morphing using anime js javascript animation engine.

 Yogesh    28 Nov, 2020    3058

IMG: SVG Shape Morphing Animation using Anime js

We can animate the SVG shape using different ways. In this tutorial we will simply cahnge the path of the SVG using javascript(anime.js engine).

Most important: All the shapes need to have the same number of points/vertex.

So, let's first create the SVG shapes. To create the SVG shapes you can use any SVG editor. In this article we will use Figma to draw the shapes using Figma Blogs plugin.

Shape 1

Shape1

Shape 1 SVG HTML

<svg width="232" height="232" viewBox="0 0 232 232" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M113.681 0.405432C140.791 -3.61542 160.464 23.2193 181.59 38.9367C201.162 53.4982 228.319 65.6645 231.728 88.2299C235.11 110.615 205.981 125.609 197.917 147.016C190.002 168.028 203.149 195.378 185.5 210.948C167.802 226.561 138.392 218.909 113.681 221.331C85.0062 224.141 53.4846 240.496 29.4373 226.245C5.43627 212.021 -4.40523 180.183 1.82604 155.042C7.65038 131.543 46.4045 127.901 59.0751 106.666C68.0264 91.6647 52.4372 72.3657 60.3771 56.9151C72.1732 33.9606 85.8165 4.53841 113.681 0.405432Z" fill="#9400D3" fill-opacity="0.63"/>
</svg>

And then create the next SVG using the above SVG path. Keep in mind that the number of points should be the same.

Shape 2

Shape1

Shape 2 SVG HTML

<svg width="232" height="232" viewBox="0 0 232 232" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M96.4471 0.00485847C112.78 0.353955 120.743 23.3279 136.438 28.208C167.018 37.7165 211.516 12.3999 228.811 41.1618C244.16 66.6863 199.506 91.5715 192.201 120.942C184.183 153.181 206.944 194.97 184.759 218.286C163.155 240.991 125.431 230.683 96.4471 221.576C72.4011 214.02 51.329 195.995 39.0405 172.5C29.0207 153.343 43.8906 128.944 37.1449 108.193C30.1072 86.544 -4.46888 76.2006 0.483266 53.8921C5.28215 32.2741 36.9775 36.7542 55.2855 26.4735C69.8111 18.3169 80.0668 -0.345241 96.4471 0.00485847Z" fill="#8DD5E6"/>
</svg>

Now, we have shape 1, shape 2. Next, we will replace shape 1's path attribute value with shape 2's path attribute value using the anime js.

HTML Structure

<svg id='svg' width="232" height="232" viewBox="0 0 232 232" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path id="svg_path" fill-rule="evenodd" clip-rule="evenodd" d="M113.681 0.405432C140.791 -3.61542 160.464 23.2193 181.59 38.9367C201.162 53.4982 228.319 65.6645 231.728 88.2299C235.11 110.615 205.981 125.609 197.917 147.016C190.002 168.028 203.149 195.378 185.5 210.948C167.802 226.561 138.392 218.909 113.681 221.331C85.0062 224.141 53.4846 240.496 29.4373 226.245C5.43627 212.021 -4.40523 180.183 1.82604 155.042C7.65038 131.543 46.4045 127.901 59.0751 106.666C68.0264 91.6647 52.4372 72.3657 60.3771 56.9151C72.1732 33.9606 85.8165 4.53841 113.681 0.405432Z" fill="#9400D3"/>
</svg>

Then make a list of the paths & store the values into an array in Javascript.

const paths = [
    'M113.681 0.405432C140.791 -3.61542 160.464 23.2193 181.59 38.9367C201.162 53.4982 228.319 65.6645 231.728 88.2299C235.11 110.615 205.981 125.609 197.917 147.016C190.002 168.028 203.149 195.378 185.5 210.948C167.802 226.561 138.392 218.909 113.681 221.331C85.0062 224.141 53.4846 240.496 29.4373 226.245C5.43627 212.021 -4.40523 180.183 1.82604 155.042C7.65038 131.543 46.4045 127.901 59.0751 106.666C68.0264 91.6647 52.4372 72.3657 60.3771 56.9151C72.1732 33.9606 85.8165 4.53841 113.681 0.405432Z',
    'M96.4471 0.00485847C112.78 0.353955 120.743 23.3279 136.438 28.208C167.018 37.7165 211.516 12.3999 228.811 41.1618C244.16 66.6863 199.506 91.5715 192.201 120.942C184.183 153.181 206.944 194.97 184.759 218.286C163.155 240.991 125.431 230.683 96.4471 221.576C72.4011 214.02 51.329 195.995 39.0405 172.5C29.0207 153.343 43.8906 128.944 37.1449 108.193C30.1072 86.544 -4.46888 76.2006 0.483266 53.8921C5.28215 32.2741 36.9775 36.7542 55.2855 26.4735C69.8111 18.3169 80.0668 -0.345241 96.4471 0.00485847Z',
    ];

Then create the javascript event to animate the SVG path. Here, we've created the mouseover event to animate the SVG path values. You can customize the event like click, blur, etc... according to your need. In this function we will update the path value and change the color of SVG. To change the color of the SVG you need to change the fill attribute value of the path tag.

let svg = document.getElementById('svg');
let destination_path;
const colors = ['#9400D3', '#8DD5E5'];
svg.addEventListener('mouseover', () => {
  svg_path.attributes['fill'].value = colors[1];
  destination_path = paths[1];
  svgMorphing(destination_path);
});
svg.addEventListener('mouseleave', () =>{
  svg_path.attributes['fill'].value = colors[2];
  destination_path = paths[0];
  svgMorphing(destination_path);
});

Now, create the svgMorph function to animate the SVG shape. In this function we will use anime js function timeline to animate the SVG shape. svgMorphing function

function svgMorphing(path) {
  let timeline = anime({
    duration: 750,
    targets: '#svg_path',
    d: [{
      value: path
    }],
    easing: 'easeOutCubic',
  });
}

Combined Everything

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #svg_path {
      transition: all .75s;
    }
  </style>
</head>
<body>
  <svg id='svg' width="232" height="232" viewBox="0 0 232 232" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path id="svg_path" fill-rule="evenodd" clip-rule="evenodd" d="M113.681 0.405432C140.791 -3.61542 160.464 23.2193 181.59 38.9367C201.162 53.4982 228.319 65.6645 231.728 88.2299C235.11 110.615 205.981 125.609 197.917 147.016C190.002 168.028 203.149 195.378 185.5 210.948C167.802 226.561 138.392 218.909 113.681 221.331C85.0062 224.141 53.4846 240.496 29.4373 226.245C5.43627 212.021 -4.40523 180.183 1.82604 155.042C7.65038 131.543 46.4045 127.901 59.0751 106.666C68.0264 91.6647 52.4372 72.3657 60.3771 56.9151C72.1732 33.9606 85.8165 4.53841 113.681 0.405432Z" fill="#9400D3"/>
  </svg>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script> 
  <script>
    // Update svg shape
    const paths = [
    'M113.681 0.405432C140.791 -3.61542 160.464 23.2193 181.59 38.9367C201.162 53.4982 228.319 65.6645 231.728 88.2299C235.11 110.615 205.981 125.609 197.917 147.016C190.002 168.028 203.149 195.378 185.5 210.948C167.802 226.561 138.392 218.909 113.681 221.331C85.0062 224.141 53.4846 240.496 29.4373 226.245C5.43627 212.021 -4.40523 180.183 1.82604 155.042C7.65038 131.543 46.4045 127.901 59.0751 106.666C68.0264 91.6647 52.4372 72.3657 60.3771 56.9151C72.1732 33.9606 85.8165 4.53841 113.681 0.405432Z',
    'M96.4471 0.00485847C112.78 0.353955 120.743 23.3279 136.438 28.208C167.018 37.7165 211.516 12.3999 228.811 41.1618C244.16 66.6863 199.506 91.5715 192.201 120.942C184.183 153.181 206.944 194.97 184.759 218.286C163.155 240.991 125.431 230.683 96.4471 221.576C72.4011 214.02 51.329 195.995 39.0405 172.5C29.0207 153.343 43.8906 128.944 37.1449 108.193C30.1072 86.544 -4.46888 76.2006 0.483266 53.8921C5.28215 32.2741 36.9775 36.7542 55.2855 26.4735C69.8111 18.3169 80.0668 -0.345241 96.4471 0.00485847Z',
    ];
    const colors = ['#9400D3', '#8DD5E5'];
    let svg = document.getElementById('svg');
    let svg_path = document.getElementById('svg_path');
    let destination_path;
    svg.addEventListener('mouseover', () => {
      destination_path = paths[1];
      svg_path.attributes['fill'].value = colors[1];
      svgMorphing(destination_path);
    });
    svg.addEventListener('mouseleave', () =>{
      destination_path = paths[0];
      svg_path.attributes['fill'].value = colors[1];
      svgMorphing(destination_path);
    });
    function svgMorphing(path) {
      let timeline = anime({
        duration: 750,
        targets: '#svg_path',
        d: [{
          value: path
        }],
        easing: 'easeInQuad',
      });
    }
  </script>
</body>
</html>

You can animate more than 2 SVG shapes using custom event. For that, you need to update path var dynamically. Additionally you can animate SVG shape using the othe tools/plugins like SnapSVG, Greensock GSAP, MorphSVG, KUTE.js, d3 etc...


Credits / Resources

  • anime.js javascript animation engine => https://animejs.com/
  • Figma to create SVG shapes => https://www.figma.com/