<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Fig. 2 | Material Design Ripple</title>
<link rel='stylesheet prefetch' href='css/https___codepen_io_pixela.css'>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<span class="wire" id="bound">Area</span>
<script src="js/index.js"></script>
</body>
</html>
/*Downloaded from https://www.codeseek.co/pixelass/fig-2-or-material-design-ripple-YXbNJd */
body {
margin: 50px;
font-family: sans-serif;
background: #424242;
}
.wire {
display: block;
width: 10em;
height: 10em;
box-shadow: 0 0 0 2px;
font-size: 20px;
line-height: 10em;
margin: -5em;
position: absolute;
top: 50%;
left: 50%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-align: center;
border: 0;
background: white;
overflow: hidden;
}
.tracker {
background: rgba(0, 0, 0, 0.3);
height: 20px;
width: 20px;
border-radius: 100%;
pointer-events: none;
-webkit-animation: scale-in .4s ease-in-out;
animation: scale-in .4s ease-in-out;
transition: opacity .4s .2s ease-out;
}
@-webkit-keyframes scale-in {
from {
-webkit-transform: translate(-50%, -50%) scale(0);
transform: translate(-50%, -50%) scale(0);
}
to {
-webkit-transform: translate(-50%, -50%) scale(1);
transform: translate(-50%, -50%) scale(1);
}
}
@keyframes scale-in {
from {
-webkit-transform: translate(-50%, -50%) scale(0);
transform: translate(-50%, -50%) scale(0);
}
to {
-webkit-transform: translate(-50%, -50%) scale(1);
transform: translate(-50%, -50%) scale(1);
}
}
/*Downloaded from https://www.codeseek.co/pixelass/fig-2-or-material-design-ripple-YXbNJd */
// the bounding box
var bound = document.getElementById('bound');
// listen to events
bound.addEventListener('mousedown', appendRipple);
bound.addEventListener('mouseup', removeRipple);
// flag to track animations
var animating;
var blocked;
// make tracker global
var tracker;
/**
* handle the animation end of the growing ripple
* @prop {Event} event The event that triggered the action
* @return no return
**/
function endIn(event) {
// clear animation flag
animating = false;
event.target.removeEventListener('animationend', endIn);
}
/**
* start the process of removing the ripple
* @prop {Event} event The event that triggered the action
* @return no return
**/
function startOut(event) {
// clear animation flag
animating = true;
// if the trigger was an event we need to clear the listener
if (event) {
event.target.removeEventListener('animationend', startOut);
}
tracker.style.opacity = 0;
// add a new listener
tracker.addEventListener('transitionend', removeFromDOM);
}
/**
* removes the element from the DOM tree
* @prop {Event} event The event that triggered the action
* @return no return
**/
function removeFromDOM(event) {
// clear animation and blocked flag
animating = false;
blocked = false;
event.target.removeEventListener('transitionend', removeFromDOM);
event.target.remove();
}
/**
* append a ripple to a clicked area
* @prop {Event} event The event that triggered the action
* @return no return
**/
function appendRipple(event) {
// don't proceed until the last ripple has been removed
if (blocked) {
return;
}
blocked = true;
// get event coordinates
var y = event.layerY;
var x = event.layerX;
// get event dimensions
var w = event.target.offsetWidth;
var h = event.target.offsetHeight;
// get offset
var offsetX = Math.abs(w / 2 - x);
var offsetY = Math.abs(h / 2 - y);
// get delta
var deltaX = w / 2 + offsetX;
var deltaY = h / 2 + offsetY;
// calculate size
var size = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2) - 2 * deltaX * deltaY * Math.cos(90 / 180 * Math.PI)) * 2;
// create an element
tracker = document.createElement('div');
// position it
tracker.classList.add('tracker');
tracker.style.position = 'absolute';
tracker.style.transform = 'translate(-50%,-50%)';
tracker.style.left = x + 'px';
tracker.style.top = y + 'px';
tracker.style.height = size + 'px';
tracker.style.width = size + 'px';
// handle animation tracking
animating = true;
tracker.addEventListener('animationend', endIn);
// append it to the event.target
event.target.appendChild(tracker);
}
/**
* remove a ripple from a clicked area
* @prop {Event} event The event that triggered the action
* @return no return
**/
function removeRipple(event) {
var ripple = event.target.querySelector('div');
if (ripple) {
if (animating) {
// if the ripple is still animating we need to wait
tracker.addEventListener('animationend', startOut);
} else {
// otherwise we can start removing the ripple
startOut();
}
}
}