htmlcssanimationtransform

Butterfly flapping wings animation SVG


I'm trying to animate butterfly wings, which should look like butterfly flapping wings. Can you help me achieve this?

Here is the JSfiddle: https://jsfiddle.net/qfoy6hbc/

.butterfly {
  width: 150px;
  height: auto;
}

.left-wing {
  animation: left 1s linear infinite alternate;  
  transform-origin: right;
}

.right-wing {
  animation: right 1s linear infinite alternate;  
  transform-origin: left;
}

@keyframes left{
  to {transform:rotateY(20deg)}
}
@keyframes right{
  to {transform:rotateY(-20deg)}
}
<svg id="Layer_2" class="butterfly" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 442.32 429.5">
  <defs>
    <style>
      .cls-1 {
        stroke-width: 0px;
      }
    </style>
  </defs>
  <g id="Layer_1-2" data-name="Layer 1">
    <g>
      <g class="left-wing">
        <path class="cls-1" d="M42.56,2.5c-8.1,6.9-11.3,21.2-16.1,71-3.9,41.1-6.6,57.7-13.6,83-2.9,10.5-3.5,14.1-3.1,18.9,1.6,17.6,20.9,37.3,52.2,53.3,13.2,6.7,39.3,17,58,22.8,15.2,4.7,45.5,12.5,48.6,12.5,2.4,0,2.9-3.9,2.9-24.9,0-39.9-7-88.3-16.9-118.2-11.4-33.9-28.4-59-64.1-94.8C71.96,7.7,60.36,0,50.96,0c-4.3,0-6,.5-8.4,2.5Z"/>
        <path class="cls-1" d="M32.76,237.1c-8.9,2.6-22.4,26.1-28.7,49.9-6.4,24.2-5.2,44.6,3.4,56.3,15.6,21.2,52,13.3,107-23.2,12.3-8.1,27.6-20.9,37.6-31.2,8.2-8.5,16.5-19,15.8-20.1-.3-.4-2.1-.8-4.1-.8-5.3,0-23.5-4.8-56-14.9-46.7-14.5-66.1-18.6-75-16Z"/>
      </g>
      <g class="right-wing">
        <path class="cls-1" d="M405.16,119c-20.1,2.3-56.1,10.1-72.2,15.7-29.1,10.1-53,25.5-79.6,51.1-14.6,14-31.7,32.8-43.9,48.2-9.9,12.5-24.2,33.8-23.7,35.4.4,1.3,26.4,12,41.3,17,15.7,5.3,56,15.2,69.2,17,6.2.9,17.7,1.6,25.5,1.6,27.2,0,42.9-6.5,50.5-20.8,1.8-3.3,3.2-6.6,3.2-7.3,0-2.4,11.2-29.4,17.2-41.4,3.3-6.6,13.7-25.5,23.1-42,23.1-40.7,28.1-52.3,26.2-62.1-.9-4.8-5.9-9.9-11.1-11.3-6.1-1.5-17.1-2-25.7-1.1Z"/>
        <path class="cls-1" d="M184.86,285.1c1.7,29,12.1,63.5,29.2,96.9,7.8,15.3,14.8,25.5,23.3,34.1,10,9.9,16.8,13.4,26.6,13.4s15-2.8,24-11.9c16.2-16.5,28.5-49.1,28.5-75.6,0-9.6-1.4-14-5.2-17.2-4-3.4-19-11.2-31.8-16.6-18.3-7.8-84-31.7-92.9-33.9l-2.4-.6.7,11.4Z"/>
      </g>
      <path class="cls-1" d="M189.66,216.6c-1.2.8-2.2,2.5-2.2,3.8,0,1.2-1.2,3.8-2.6,5.7-4.6,6.2-6.3,10.5-7.4,19.5-2,15.2-3.7,20.9-10.8,35.1-10.1,20.3-11.2,23.9-11.1,38.1.1,17,.3,17.2,7.7,7.8,3.4-4.2,7.3-9.6,8.6-11.9,3.2-5.4,6.1-16.6,8.1-31.2,1.8-13.4,3.7-18.9,11.2-33.2,5-9.8,5.3-10.7,5.3-17.7,0-4.1.5-7.8,1-8.1,1.7-1,1.1-6.1-.8-7.8-2.3-2.1-4.1-2.1-7-.1Z"/>
    </g>
  </g>
</svg>

Here is the SVG code and CSS animations


Solution

  • From the looks of it you're not transforming relative to the coordinate of the butterfly body/the point where the wings meet the body. This becomes super obvious if you pick something like 120 degrees instead of 20, so: you probably want a different transform-origin property.

    And to make "picking the right origin" much easier: export your butterfly without the rotations baked in, and then work on your animation transforms for that axis-aligned butterfly first. Then, once those work, all you need to do is rotate the entire butterfly by adding a transform: rotate(...) to the .butterfly class:

    .butterfly {
      width: 150px;
      height: auto;
      transform-origin: center center;
      transform: rotate(30deg);
    }
    
    .left-wing {
      animation: left 1s linear infinite alternate;
      transform-origin: calc(50% - 10px) 0;
    }
    
    .right-wing {
      animation: right 1s linear infinite alternate;  
      transform-origin: calc(50% + 10px) 0;
    }
    
    @keyframes left {
      to {
        transform:rotateY(80deg)
      }
    }
    
    @keyframes right {
      to {
        transform:rotateY(-80deg);
      }
    }
    <svg width="425" height="347" viewBox="0 0 425 347" class="butterfly">
       <g class="left-wing">
          <path d="M 3.25,6.76 C -4.76,25.69 4.27,46.37 6.75,65.56 14.46,100.95 22.40,136.62 22.61,173.00 c 3.94,24.18 30.50,33.68 51.07,39.65 42.38,9.42 86.46,8.82 129.48,4.56 -0.74,-23.72 -13.48,-45.91 -21.61,-68.07 C 162.29,104.79 135.37,61.45 93.11,35.75 70.03,22.05 46.59,6.50 19.95,1.04 14.11,0.51 6.82,1.60 3.25,6.76 z"/>
          <path d="m 65.65,233.12 c -12.55,15.35 -12.07,37.29 -12.06,56.28 1.39,21.08 6.32,48.74 28.95,56.75 24.19,4.94 44.32,-14.64 60.54,-29.88 25.67,-26.28 48.96,-56.42 60.65,-91.66 -10.50,-4.02 -34.04,2.36 -49.73,0.66 -28.26,1.12 -57.32,-1.40 -84.87,6.04 z"/>
       </g>
       <g class="right-wing">
          <path d="M 384.10,6.82 C 342.38,26.89 300.33,51.58 275.03,91.75 c -24.15,38.06 -43.48,79.81 -53.83,123.80 15.97,6.62 39.55,4.40 58.40,4.84 37.97,-2.15 79.42,-2.54 111.46,-25.75 18.11,-13.71 11.23,-38.03 14.84,-57.30 C 409.50,96.97 423.93,58.13 425.60,17.59 425.20,-7.03 398.35,0.14 384.10,6.82 Z" />
          <path d="m 225.14,232.32 c 16.51,39.80 44.53,74.74 78.20,101.41 14.53,10.95 36.75,20.29 52.19,5.71 19.62,-24.37 20.23,-59.03 13.70,-88.34 -1.21,-22.04 -24.69,-23.52 -41.67,-25.17 -35.43,-2.78 -71.03,-4.56 -106.57,-4.24 1.38,3.54 2.76,7.09 4.15,10.64 z" />
       </g>
       <path d="m 208.77,165.63 c -6.38,17.39 -1.35,35.52 -0.65,53.52 -1.69,19.82 -8.16,40.50 1.20,59.52 6.04,19.57 13.75,-15.67 13.20,-23.24 -0.60,-19.43 -7.44,-38.78 -2.02,-58.17 1.15,-6.41 1.76,-42.76 -11.73,-31.62 z" />
    </svg>

    And if you're going to put this on the web: optimize your SVG so it doesn't contain application-specific properties like layer ids, data attributes, <defs> that don't actually do anything, numbers with more than 2 digits after the decimal points, etc. No point in keeping any of that, it just makes your SVG needlessly big.