DEV Community

Cover image for Ripple Effect using JS animation api
Frank Wisniewski
Frank Wisniewski

Posted on

3 1

Ripple Effect using JS animation api

see comments in Source Code

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <title>Ripple sample</title>
  <!-- 
    Pico.css • Minimal CSS Framework for semantic HTML
  -->
  <link rel="stylesheet"
    href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
  <style>
    h1{
      font-weight:400;
      text-align:center;
    }
    h2{
      text-align:center;
      font-weight:500;
    }
    button{
      /*
        it is important to use position: relative
      */
      position:relative;
      width:200px;
      font-weight:400;
      text-transform: uppercase;
      margin:0 auto;
      box-shadow: 2px 3px 4px rgba(0,0,0,0.4);
      transition: all 200ms ease;
    }
    button:active{
      box-shadow:none;
    }
  </style>

</head>
<body class=container>

  <hgroup>
    <h1>Ripple</h1>
    <h2>using animation.api</h2>
  </hgroup>

  <button>click me</button>
  <p></p>
  <button class=secondary>click me</button>
  <p></p>
  <button class=contrast>click me</button>

<script>
  "use strict";

  function rippleEffect ( evt ) {
    // get Coordinates from current Button
    let offset = this.getBoundingClientRect(), 
        // create the ripple div
        ripple = document.createElement( 'div' ),
        // save the overflow style from current Button
        aktOverflow = getComputedStyle( this ).overflow,
        // set colors for ripple
        light = `rgba(255,255,255,0)`,
        dark =  `rgba(255,255,255,.3)`,
        // calc the diagonal width from element
        scale = Math.sqrt( 
          ( offset.width*offset.width ) + 
          ( offset.height*offset.height ) )/10;
    // set overflow Button 
    this.style.overflow = 'hidden';
    // style the ripple Element
    ripple.style = `
      width:20px;
      height:20px;
      border-radius: 50%;
      background: radial-gradient(circle, 
      ${dark} 0%, ${light} 5%, ${light} 7%, 
      ${dark} 13%, ${dark} 17%, ${light} 30%, 
      ${light} 35%, ${dark} 51%,${dark} 58%,
      ${light} 68%, ${light} 75%, ${dark} 100%);
      position: absolute;
      opacity: 0;
      transform-origin: 'center center';
      left: ${evt.clientX - offset.left -10}px;
      top: ${evt.clientY - offset.top -10}px;`
    // inject ripple in button
    this.prepend( ripple );
    // create the animate object
    let rippleAni = ripple.animate( [
        { transform: 'scale(0)', opacity:1 },
        { transform: `scale(${scale})`, opacity: .1 }
      ],
      { duration: 600}
    );
    // kill the ripple when animation finished
    Promise.resolve( rippleAni.finished )
      .then( () => { 
        ripple.remove();
        this.style.overflow=aktOverflow;
        }
      );
  }

  document.querySelectorAll( 'button' ).forEach( 
      el => el.addEventListener( 'click', rippleEffect )
  )

</script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

TRY IT

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay