javascriptcsssvgcss-animationssvg-animate

How can I modify my CCS-animated objects in an SVG with JS to animate randomly, rather than all at once?


I have a map that I am trying to animate on a web page. The SVG I am working on can be seen here: https://svgshare.com/i/stq.svg

I have successfully animated the map so that the icons pulse and change opacity, but all of the icons are moving concurrently. Instead, I want each icon (which a made up of a group of two paths) to animate independently. So that rather than every icon growing and shrinking at the same time, it looks like they are growing and shrinking randomly across the map.

I am having trouble modifying my CSS animation using a javascript, and could use some help. I have grouped the icons and labeled them independently (group 1, group 2, group 3... etc.), but I am stuck on how to instruct them to animate independently.

Here's my HTML/CSS:

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 576.91 353.74" style="enable-background:new 0 0 576.91 353.74;" xml:space="preserve">

<style>
    .st0{fill:#FFCA19;stroke:#FFFFFF;stroke-miterlimit:10;}
    .st1{fill:#FFFFFF; opacity: 0; animation: pulse 3s ease-in-out infinite; animation-delay: calc(var(--delay) *1ms);}
    .st2{fill:#E24D25; opacity: 0; animation: pulse 3s ease-in-out infinite; animation-delay: calc(var(--delay) * 1ms);}
    
    @keyframes pulse {
      0% { transform: scale(1); opacity: 0.1; }
      50% { transform: scale(1.02); opacity: 1; }
      100% { transform: scale(1); opacity: 0.1; }
    }
    .st1 { transform-origin: center; }
    .st2 { transform-origin: center; }

}
</style>

The SVG code comes next, and within it, there are grouped paths (st1 and st2), which each make up one icon. I'll only post two of the groups for space's sake, but there are 22 total groups, each structured as follows.

<g id="group1">
    <path class="st1" d="M81.47,126.76l-6.86,11.88c-0.95,1.64,0.24,3.69,2.13,3.69h13.72c1.89,0,3.07-2.05,2.13-3.69l-6.86-11.88
        C84.78,125.12,82.42,125.12,81.47,126.76z"/>
    <path class="st2" d="M92.59,138.64l-6.86-11.88c-0.95-1.64-3.31-1.64-4.26,0l-6.86,11.88c-0.95,1.64,0.24,3.69,2.13,3.69h13.72
        C92.35,142.33,93.54,140.28,92.59,138.64z M85.28,140.14h-3.37v-2.97h3.37V140.14z M85.36,131.94c0,0.88-0.37,2.95-0.66,4.38h-2.2
        c-0.29-1.43-0.66-3.46-0.66-4.35v-1.78h3.51V131.94z"/>
</g>
<g id="group2">
    <path class="st1" d="M360.83,172.37l-6.86,11.88c-0.95,1.64,0.24,3.69,2.13,3.69h13.72c1.89,0,3.07-2.05,2.13-3.69l-6.86-11.88
        C364.14,170.74,361.78,170.74,360.83,172.37z"/>
    <path class="st2" d="M371.95,184.26l-6.86-11.88c-0.95-1.64-3.31-1.64-4.26,0l-6.86,11.88c-0.95,1.64,0.24,3.69,2.13,3.69h13.72
        C371.71,187.94,372.9,185.9,371.95,184.26z M364.64,185.76h-3.37v-2.97h3.37V185.76z M364.72,177.56c0,0.88-0.37,2.95-0.66,4.38
        h-2.2c-0.29-1.43-0.66-3.46-0.66-4.35v-1.78h3.51V177.56z"/>
</g>

So far, I've only been able to get it to animate all at once, and haven't been able to get the icons to animate randomly as described above.


Solution

  • To Animate them independently, we need to use animationDelay. Here is a small javascript snippet that will add a random animation delay to each of the group.

    document.querySelectorAll( 'g' ).forEach(node => {
      let animationDelay = Math.random() * -6+'s'
      node.querySelectorAll('path').forEach(pathEle => pathEle.style.animationDelay = animationDelay)
    });
    

    Thanks to @somethinghere for the initial code in comment.