纯css实现波纹效果
说明
:使用伪元素:after定义波纹效果,一开始opacity为0,用户不可见,点击后进入active状态,opacity变为0.3,不缩放,transition: 0s。退出active状态后,自然重新显示:after中的样式,opacity变为0,放大10倍,由于transition设置1s,故有一个肉眼可见的变化过程。用户看到的效果
:一个圆逐渐变大变淡,最后消失。缺点
:使用css实现的,无法定位鼠标位置,每次波纹出现的位置都是固定的。<button class="btn ripple">Button</button>
.btn { position: relative; margin: 0 auto; width: 200px; height: 50px; line-height: 50px; border-radius: 4px; box-shadow: 0 0 10px gray; background-color: #fff; overflow: hidden; cursor: pointer; } .ripple { position: relative; //隐藏溢出的径向渐变背景 overflow: hidden; } .ripple:after { content: ""; display: block; position: absolute; width: 100%; height: 100%; top: 0; left: 0; pointer-events: none; background-image: radial-gradient(circle, #666 10%, transparent 20%); background-repeat: no-repeat; background-position: 50%; transform: scale(10, 10); opacity: 0; transition: transform 1s, opacity 1s; } .ripple:active:after { //设置初始状态 transform: scale(0, 0); opacity: .3; transition: 0s; }
使用js实现波纹效果
说明
:使用js可以获取鼠标(手指)位置,从而改变波纹位置,这里我使用vue封装了一个组件 = =
监听的事件是touchstart和touchend(手指触摸屏幕)(手机),电脑端可以改为mousedown和mouseup(鼠标事件)<template> <div class="ripple--wapper" ref="rootElement"> <div class="ripple--container" ref="rippleContainer" @touchstart="showRipple" @touchend="cleanRipple"></div> <slot /> </div> </template> <script> export default { name:'ripple', data () { return { timer: 0 } }, props: { size: { type: Number, default: 100 } }, deactivated () { if(this.timer) { clearTimeout(this.timer) } while (this.$refs.rippleContainer.firstChild) { this.$refs.rippleContainer.removeChild(this.$refs.rippleContainer.firstChild) } }, methods:{ showRipple (e) { const target = this.$refs.rippleContainer const ripple = document.createElement('span') const size = this.size const pos = this.$refs.rippleContainer.getBoundingClientRect() const clientX = e.targetTouches[0].clientX const clientY = e.targetTouches[0].clientY const x = clientX - pos.left - size / 2 const y = clientY - pos.top - size / 2 const style = `top:${y/50}rem;left:${x/50}rem;width:${size/50}rem;height:${size/50}rem` ripple.setAttribute('style', style) const container = this.$refs.rippleContainer container.appendChild(ripple) }, cleanRipple () { const _this = this if(this.timer) { clearTimeout(this.timer) } this.timer=setTimeout(() =>{ //清除ripple if (_this.$refs.rippleContainer && _this.$refs.rippleContainer.firstChild) { _this.$refs.rippleContainer.removeChild(_this.$refs.rippleContainer.firstChild) } }, 1000) } } } </script> <style lang="less"> @import "~assets/variable"; .ripple--wapper { position: relative; overflow: hidden; //禁止文本选择 -webkit-user-select: none; -moz-user-select: none; -webkit-user-select:none; -o-user-select:none; user-select:none; .ripple--container { position: absolute; top: 0; right: 0; bottom: 0; left: 0; span { position: absolute; transform: scale(0); border-radius: 100%; opacity: .3; background-color: #333; animation: ripple .2s; } @keyframes ripple { to { opacity: 0; transform: scale(2); } } } } </style>