参考http://www.materializecss.cn/waves.html
<html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> p { height: 100px; line-height: 100px; text-align: center; width: 100px; background-color: #ccc; } /* Firefox Bug: link not triggered */ .waves-effect .waves-ripple { z-index: -1; } .waves-effect { position: relative; cursor: pointer; display: inline-block; overflow: hidden; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; vertical-align: middle; z-index: 1; -webkit-transition: .3s ease-out; transition: .3s ease-out; } .waves-effect .waves-ripple { position: absolute; border-radius: 50%; width: 20px; height: 20px; margin-top: -10px; margin-left: -10px; opacity: 0; background: rgba(0, 0, 0, 0.2); -webkit-transition: all 0.7s ease-out; transition: all 0.7s ease-out; -webkit-transition-property: opacity, -webkit-transform; transition-property: opacity, -webkit-transform; transition-property: transform, opacity; transition-property: transform, opacity, -webkit-transform; -webkit-transform: scale(0); transform: scale(0); pointer-events: none; } /*.waves-light此类class是wave颜色*/ .waves-effect.waves-light .waves-ripple { background-color: rgba(255, 255, 255, 0.45); } .waves-effect.waves-red .waves-ripple { background-color: rgba(244, 67, 54, 0.7); } .waves-effect.waves-yellow .waves-ripple { background-color: rgba(255, 235, 59, 0.7); } .waves-effect.waves-orange .waves-ripple { background-color: rgba(255, 152, 0, 0.7); } .waves-effect.waves-purple .waves-ripple { background-color: rgba(156, 39, 176, 0.7); } .waves-effect.waves-green .waves-ripple { background-color: rgba(76, 175, 80, 0.7); } .waves-effect.waves-teal .waves-ripple { background-color: rgba(0, 150, 136, 0.7); } .waves-effect img { position: relative; z-index: -1; } </style> </head> <body> <p class="waves-effect waves-orange">ppppp</p> <script> if (\'ontouchstart\' in window) { document.body.addEventListener(\'touchstart\', showEffect, false); } document.body.addEventListener(\'mousedown\', showEffect, false); var TouchHandler = { /* uses an integer rather than bool so there\'s no issues with * needing to clear timeouts if another touch event occurred * within the 500ms. Cannot mouseup between touchstart and * touchend, nor in the 500ms after touchend. */ touches: 0, allowEvent: function(e) { var allow = true; if (e.type === \'touchstart\') { TouchHandler.touches += 1; //push } else if (e.type === \'touchend\' || e.type === \'touchcancel\') { setTimeout(function() { if (TouchHandler.touches > 0) { TouchHandler.touches -= 1; //pop after 500ms } }, 500); } else if (e.type === \'mousedown\' && TouchHandler.touches > 0) { allow = false; } return allow; }, touchup: function(e) { TouchHandler.allowEvent(e); } }; var Effect = { // Effect delay duration: 750, show: function(e, element) { // Disable right click if (e.button === 2) { return false; } var el = element || this; // Create ripple var ripple = document.createElement(\'div\'); ripple.className = \'waves-ripple\'; el.appendChild(ripple); // Get click coordinate and element witdh var pos = offset(el); var relativeY = e.pageY - pos.top; var relativeX = e.pageX - pos.left; var scale = \'scale(\' + el.clientWidth / 100 * 10 + \')\'; // Support for touch devices if (\'touches\' in e) { relativeY = e.touches[0].pageY - pos.top; relativeX = e.touches[0].pageX - pos.left; } // Attach data to element ripple.setAttribute(\'data-hold\', Date.now()); ripple.setAttribute(\'data-scale\', scale); ripple.setAttribute(\'data-x\', relativeX); ripple.setAttribute(\'data-y\', relativeY); // Set ripple position var rippleStyle = { \'top\': relativeY + \'px\', \'left\': relativeX + \'px\' }; ripple.className = ripple.className + \' waves-notransition\'; ripple.setAttribute(\'style\', convertStyle(rippleStyle)); ripple.className = ripple.className.replace(\'waves-notransition\', \'\'); // Scale the ripple rippleStyle[\'-webkit-transform\'] = scale; rippleStyle[\'-moz-transform\'] = scale; rippleStyle[\'-ms-transform\'] = scale; rippleStyle[\'-o-transform\'] = scale; rippleStyle.transform = scale; rippleStyle.opacity = \'1\'; rippleStyle[\'-webkit-transition-duration\'] = Effect.duration + \'ms\'; rippleStyle[\'-moz-transition-duration\'] = Effect.duration + \'ms\'; rippleStyle[\'-o-transition-duration\'] = Effect.duration + \'ms\'; rippleStyle[\'transition-duration\'] = Effect.duration + \'ms\'; rippleStyle[\'-webkit-transition-timing-function\'] = \'cubic-bezier(0.250, 0.460, 0.450, 0.940)\'; rippleStyle[\'-moz-transition-timing-function\'] = \'cubic-bezier(0.250, 0.460, 0.450, 0.940)\'; rippleStyle[\'-o-transition-timing-function\'] = \'cubic-bezier(0.250, 0.460, 0.450, 0.940)\'; rippleStyle[\'transition-timing-function\'] = \'cubic-bezier(0.250, 0.460, 0.450, 0.940)\'; ripple.setAttribute(\'style\', convertStyle(rippleStyle)); }, hide: function(e) { TouchHandler.touchup(e); var el = this; var width = el.clientWidth * 1.4; // Get first ripple var ripple = null; var ripples = el.getElementsByClassName(\'waves-ripple\'); if (ripples.length > 0) { ripple = ripples[ripples.length - 1]; } else { return false; } var relativeX = ripple.getAttribute(\'data-x\'); var relativeY = ripple.getAttribute(\'data-y\'); var scale = ripple.getAttribute(\'data-scale\'); // Get delay beetween mousedown and mouse leave var diff = Date.now() - Number(ripple.getAttribute(\'data-hold\')); var delay = 350 - diff; if (delay < 0) { delay = 0; } // Fade out ripple after delay setTimeout(function() { var style = { \'top\': relativeY + \'px\', \'left\': relativeX + \'px\', \'opacity\': \'0\', // Duration \'-webkit-transition-duration\': Effect.duration + \'ms\', \'-moz-transition-duration\': Effect.duration + \'ms\', \'-o-transition-duration\': Effect.duration + \'ms\', \'transition-duration\': Effect.duration + \'ms\', \'-webkit-transform\': scale, \'-moz-transform\': scale, \'-ms-transform\': scale, \'-o-transform\': scale, \'transform\': scale }; ripple.setAttribute(\'style\', convertStyle(style)); setTimeout(function() { try { el.removeChild(ripple); } catch (e) { return false; } }, Effect.duration); }, delay); } } function showEffect(e) { var element = getWavesEffectElement(e); if (element !== null) { Effect.show(e, element); if (\'ontouchstart\' in window) { element.addEventListener(\'touchend\', Effect.hide, false); element.addEventListener(\'touchcancel\', Effect.hide, false); } element.addEventListener(\'mouseup\', Effect.hide, false); element.addEventListener(\'mouseleave\', Effect.hide, false); element.addEventListener(\'dragend\', Effect.hide, false); } }; function getWavesEffectElement(e) { if (TouchHandler.allowEvent(e) === false) { return null; } var element = null; var target = e.target || e.srcElement; while (target.parentNode !== null) { if (!(target instanceof SVGElement) && target.className.indexOf(\'waves-effect\') !== -1) { element = target; break; } target = target.parentNode; } return element; } function offset(elem) { var docElem, win, box = { top: 0, left: 0 }, doc = elem && elem.ownerDocument; docElem = doc.documentElement; if (typeof elem.getBoundingClientRect !== typeof undefined) { box = elem.getBoundingClientRect(); } win = getWindow(doc); return { top: box.top + win.pageYOffset - docElem.clientTop, left: box.left + win.pageXOffset - docElem.clientLeft }; } function isWindow(obj) { return obj !== null && obj === obj.window; } function getWindow(elem) { return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView; } function convertStyle(obj) { var style = \'\'; for (var a in obj) { if (obj.hasOwnProperty(a)) { style += a + \':\' + obj[a] + \';\'; } } return style; } </script> </body> </html>