SOURCE

console 命令行工具 X clear

                    
>
console
(function () {
  // 返回元素的宽度和所创建的span的中心点的坐标
  function getCoordinates (e, element) {
    const width = element.offsetWidth
    let x = e.pageX - element.offsetLeft - width / 2
    let y = e.pageY - element.offsetTop - width / 2
    let node = element.parentNode
    while (node !== document) {
      x -= node.offsetLeft
      y -= node.offsetTop
      node = node.parentNode
    }
    return { width, x, y }
  }
  
  // 在鼠标位置创建span
  function createSpan (element, coordinate) {
    console.log(coordinate)
    let span = document.createElement('span')
    span.className = 'ripple'
    element.appendChild(span)
    span.style.cssText = `width:${coordinate.width}px;height:${coordinate.width}px;top:${coordinate.y}px;left:${coordinate.x}px;`;
    return span
  }

  // 添加动画结束事件监控
	function animationEnd(element, handler) {
		element.addEventListener('animationend', handler, false);
		element.addEventListener('webkitAnimationEnd', handler, false);
		element.addEventListener('mozAnimationEnd', handler, false);
		element.addEventListener('OAnimationEnd', handler, false);
	};  
  
  window.addRipple = function (elements) {
    for (let value of elements) {
      value.addEventListener('click', (e) => {
				let span = createSpan(value, getCoordinates(e, value))
        span.className += ' ripple-effect';
        animationEnd(span, function () {
          this.parentNode.removeChild(span)
        })
      })
    }
  }
} ())

const target = document.querySelectorAll('.btn-ripple')
addRipple(target)
<div class="btn-group">
  <button class="btn btn-ripple">Primary</button>
</div>
.btn-group {
  position: absolute;
  top: 45%;
  left: 45%;
}
.btn {
  outline: 0;
  border: none;
  background-color: #31b794;
  color: #fff;
  padding: 8px 20px;
  font-size: 14px;
  border-radius: 5px;
}
.btn-ripple {
  position: relative;
  overflow: hidden;
}

.ripple {
  border-radius: 50%;
  position: absolute;
  transform: scale(0);
  opacity: 1;
  background-color: rgba(0,0,0,0.2);
}
.ripple-effect {
    animation: rippleEffect 2s cubic-bezier(0.23, 1, 0.32, 1);
}
@keyframes rippleEffect {
  100% {
    transform: scale(2);
    opacity: 0;
  }
}