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>
TRY IT
Top comments (0)