Search code examples
svgcss-animations

SVG Triangle To Circle Animation


I am currently trying to create an animation where a triangle morphs into a circle and back again. My current problem is that when they morph into each other, the lines curve in different ways.

enter image description here
Transition between circle and triangle

In this image you can see that the top left side curves outwards, whiles the bottom left side curves inwards. I am trying to make it so the transition is symmetrical.

I have tried changing the control points to adjust how the curve functions but I cannot make the transition look symmetrical.

Somewhat new to this, so please excuse my terminology but if anyone could help, I would appreciate it a lot.

Here is my current code:

<svg width="50%" height="50%" viewBox="0 0 100 100">
  <path transform="scale(0.5)" transform-origin="center" style="transform-box: fill-box;">
    <animate 
       attributeName="d" 
       dur="3000ms" 
       repeatCount="indefinite"
       values="M 0,0 C 100,50 100,50 100,50 0,100 0,100 0,100
               0,50 0,50 0,50 0,0 0,0 0,0 Z;
                     
               M 50,0 C 77.5,0 100,22.5 100,50 100,77.5 77.5,100 50,100 22.5,100 0,77.5
               0,50 0,22.5 22.5,0 50,0 Z;
                     
               M 0,0 C 100,50 100,50 100,50 0,100 0,100 0,100
               0,50 0,50 0,50 0,0 0,0 0,0 Z;"/>
  </path>
</svg>


Solution

  • You were pretty close.
    For a more symmetric morphing animation just "pull" the 2 cubic bézier control points to the starting and end coordinates separately:

    Triangular path

    M 0 0 
    C 0 0     100 50  100 50 
    C 100 50  0 100   0 100 
    C 0 100   0 50    0 50 
    C 0 50    0 0     0 0 
    Z
    

    As you can see

    1. cubic control point coordinates equal the previous commands on-path point
    2. control point coincides with the segment's final point

    <svg width="50%" height="50%" viewBox="0 0 100 100">
      <path transform="scale(0.5)" transform-origin="center" style="transform-box: fill-box;">
        <animate 
           attributeName="d" 
           dur="3000ms" 
           repeatCount="indefinite"
           values="M 0 0 C 0 0 100 50 100 50 C 100 50 0 100 0 100 C 0 100 0 50 0 50 C 0 50 0 0 0 0 Z;
                         
                   M 50,0 C 77.5,0 100,22.5 100,50 100,77.5 77.5,100 50,100 22.5,100 0,77.5
                   0,50 0,22.5 22.5,0 50,0 Z;
                         
                   M 0 0 C 0 0 100 50 100 50 C 100 50 0 100 0 100 C 0 100 0 50 0 50 C 0 50 0 0 0 0 Z;"/>
      </path>
    </svg>