Search code examples
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.