Search code examples
svgsvg-animate

How to animate an SVG wave image?


I am new to SVG animation and I am trying to animate a "wave" background I made in Figma and exported as SVG.

Basically, as you see in the snippet, I'm trying to keep the shape of the wave, but make the contours move very subtly. Is that possible to do? If so, what approach should I use? I don't know where to start. I tried to use the SVG <animate> and messed around with the numbers, but it doesn't work and breaks the wave and does not even animate.

Would really appreciate an example or if someone can point me to the right direction so I can give it a try.

Here's my SVG original path:

<svg width="1279" height="650" viewBox="0 0 1279 650" fill="none" xmlns="http://www.w3.org/2000/svg">
  
  <path d="
    M   -138 -167.889
    C   -138 -167.889 
        2002 -494.389 
        1020.73 -167.889
        
    C   39.4558 158.611 
        1111.22 305.526 
        942.746 516.955
    C   681.205 845.177 
        -138 458.649 
        -138 458.649
    V   -167.889
    Z" 
    fill="#000000">
   </path>
  </svg>

Here's one where I tried to animate and failed spectacularly:

<div class="wave">
 <svg width="1279" height="650" viewBox="0 0 1279 650" fill="none" xmlns="http://www.w3.org/2000/svg">
  
  <path d="
    M   -138 -167.889
    C   -138 -167.889 
        2002 -494.389 
        1020.73 -167.889
        
    C   39.4558 158.611 
        1111.22 305.526 
        942.746 516.955
    C   681.205 845.177 
        -138 458.649 
        -138 458.649
    V   -167.889
    Z" 
    fill="#EDE5FA">
   
   <animate 
          repeatCount="indefinite" 
          fill="#454599" 
          attributeName="d" 
          dur="15s" 
          values="
             M   -138 -167.889
            C   -128 -167.889 
                2002 -494.389 
                1020.73 -167.889
                
            C   139.4558 158.611 
                1411.22 305.526 
                942.746 516.955
            C   881.205 845.177 
                -138 458.649 
                -138 458.649
            V   -167.889
            Z
            ">
        </animate>
   </path>
  </svg>

</div>

Thanks

<div class="wave">
 <svg width="1279" height="650" viewBox="0 0 1279 650" fill="none" xmlns="http://www.w3.org/2000/svg">
  
  <path d="
    M   -138 -167.889
    C   -138 -167.889 
        2002 -494.389 
        1020.73 -167.889
        
    C   39.4558 158.611 
        1111.22 305.526 
        942.746 516.955
    C   681.205 845.177 
        -138 458.649 
        -138 458.649
    V   -167.889
    Z" 
    fill="#000000">
   
   </path>
  </svg>

</div>


Solution

  • I managed to fix the code. My mistake was basically missing the ; in the <animate> block. Thanks, @enxaneta. Then, I used a nice trick to keep the overall shape and only marginally modify it so that we get the animated effect when it runs. Here's how I did it.

    First, create a wave form in Figma, and export it as an SVG. For example, one I made gave methe following code:

    <div class="wave">
        <svg width="1279" height="650" viewBox="0 0 1279 650" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d=" M-138 -167.889 C-138 -167.889 2002 -494.389 1020.73 -167.889C39.4558 158.611 1111.22 305.526 942.746 516.955C681.205 845.177  -138 458.649 -138 458.649V-167.889Z" fill="#000000"></path>
        </svg>
    </div>
    

    The second step is to go back to Figma and generate 3 other shapes from the original. I made some very subtle changes to the 3 other shapes and exported each one as an SVG. Those are the shapes that I will be using in my animation. In the code block below, I show the paths of those 3 shapes. I only need those for my animation. Example:

    M-138 -167.889C-138 -167.889 1986.46 -591.778 1020.73 -167.889C55 256 1148.99 306.909 942.746 516.954C736.5 727 -138 458.649 -138 458.649V-167.889Z;
    
    M-138 -167.889C-138 -167.889 1923.96 -760.278 1020.73 -167.889C117.5 424.5 1248.99 269.909 942.746 516.954C636.5 764 -138 458.649 -138 458.649V-167.889Z;
    
    M-138 -167.889C-138 -167.889 1989.46 -765.777 1020.73 -167.889C52 430 1302.99 226.348 942.746 516.955C582.5 807.561 -138 458.649 -138 458.649V-167.889Z;
    

    Now, all we need to do is put them together. We use the <animate> tag in the SVG and by making use of attributeName = "d", we are basically targeting the original path of the SVG. Notice how in the values attribute, I have 4 shapes, instead of the 3 I generated above. This is because I am simply repeating the first shape of the 3 new ones so that we complete the animation cycle and loopback to start:

    <svg width="1279" height="650" viewBox="0 0 1279 650" xmlns="http://www.w3.org/2000/svg">
        <path d="M-138 -167.889C-138 -167.889 2002 -494.389 1020.73 -167.889C39.4558 158.611 1111.22 305.526 942.746 516.955C681.205 845.177 -138 458.649 -138 458.649V -167.889Z" 
        fill="#000000">
        
        <!-- First shape and last shape in values are the same -->
        <animate 
                repeatCount="indefinite" 
                fill="#454599" 
                attributeName="d" 
                dur="12s" 
                values="
                    M-138 -167.889C-138 -167.889 1986.46 -591.778 1020.73 -167.889C55 256 1148.99 306.909 942.746 516.954C736.5 727 -138 458.649 -138 458.649V-167.889Z;
    
                    M-138 -167.889C-138 -167.889 1923.96 -760.278 1020.73 -167.889C117.5 424.5 1248.99 269.909 942.746 516.954C636.5 764 -138 458.649 -138 458.649V-167.889Z;
    
                    M-138 -167.889C-138 -167.889 1989.46 -765.777 1020.73 -167.889C52 430 1302.99 226.348 942.746 516.955C582.5 807.561 -138 458.649 -138 458.649V-167.889Z;
    
                    M-138 -167.889C-138 -167.889 1986.46 -591.778 1020.73 -167.889C55 256 1148.99 306.909 942.746 516.954C736.5 727 -138 458.649 -138 458.649V-167.889Z;
                ">
            </animate>
        </path>
    </svg>

    Enjoy :-)