vue实现水波涟漪效果的点击反馈指令
水波效果
当用户点击时,会以点击中心为圆心产生一个水波扩散的涟漪效果,适用各个场景,美观又不浮夸,关键是可以给用户带来很直观的反馈。
来看实现
首先这里基于Vue3自定义指令进行封装,Vue3的自定义指令跟Vue2相比变动不是很大,。我们的目标是完成一个水波指令的基本原型,这里循序渐进展开。
定制一个水波纹默认样式
水波纹实际上就是通过用户点击的位置生成一个小圆圈,并且尺寸逐渐扩大到整个被点击元素的一个过程,所以这里先制定一个水波基本的样式,并设置好过度动画,过度动画应该是一个先慢后快的一个过程,这里使用贝塞尔曲线定制
.my-ripple { position: absolute; top: 0; left: 0; z-index: 100; border-radius: 50%; background-color: currentColor; opacity: 0; transition: transform 0.2s cubic-bezier(0.68, 0.01, 0.62, 0.6), opacity 0.08s linear; will-change: transform, opacity; pointer-events: none; }
计算水波纹的位置和直径
如果确定了水波的直径、创建时的(x,y)、过度动画结束时的(x,y),我们就可以通过transition去渲染水波动画了,创建时的(x,y)就是用户点击的位置,但是水波的直径和过度动画结束时的(x,y)怎么计算呢?我们的元素都是矩形,不论用户从元素的任意坐标进行点击,以矩形斜边作为直径的圆都可以完美的覆盖整个元素,斜边的计算我们利用小学数学知识求两边平方和进行开方得到,下面是过度动画结束时的水波推演图。
第一个箭头: 期望得到的水波
第二个箭头: 元素(0,0)点创建的水波
第三个箭头: 元素(0,0)点创建的水波, 不带圆角效果
我们可以发现通过元素(0,0)点创建的水波进行一定偏移就可以得到我们想要的水波,由此我们可以推断出
动画结束时的水波的尺寸 = 圆的斜边
创建时的(x,y) = 用户点击的位置
过度动画结束时的(x,y) = 元素(0,0)点创建的水波进行x和y的偏移得到
function computeRippleStyles(element, event) { const { top, left } = element.getBoundingClientRect() const { clientWidth, clientHeight } = element const radius = Math.sqrt(clientWidth ** 2 + clientHeight ** 2) / 2 const size = radius * 2 const localX = event.clientX - left const localY = event.clientY - top const centerX = (clientWidth - radius * 2) / 2 const centerY = (clientHeight - radius * 2) / 2 const x = localX - radius const y = localY - radius return { x, y, centerX, centerY, size } }
鼠标按下时创建水波
然后我们需要在鼠标按下时创建水波,监听鼠标按下的事件,这里以pc端为例子,刚创建水波时使用transform缩小到0.3,这是作者尝试过相对合适的创建大小, 然后修改transform触发过度水波扩散动画,这里还加入了透明度的过度,可以使水波涟漪更有质感。
function createRipple(event) { const container = this const { x, y, centerX, centerY, size } = computeRippleStyles(container, event) const ripple = document.createElement('div') ripple.classList.add('my-ripple') ripple.style.opacity = `0` ripple.style.transform = `translate(${x}px, ${y}px) scale3d(.3, .3, .3)` ripple.style.width = `${size}px` ripple.style.height = `${size}px` // 记录水波的创建时间 ripple.dataset.createdAt = String(performance.now()) const { position } = window.getComputedStyle(container) container.style.overflow = 'hidden' position === 'static' && (this.style.position = 'relative') container.appendChild(ripple) window.setTimeout(() => { ripple.style.transform = `translate(${centerX}px, ${centerY}px) scale3d(1, 1, 1)` ripple.style.opacity = `.25` }) } const VRipple = { mounted(el) { el.addEventListener('mousedown', createRipple) } }
鼠标抬起时销毁水波
当鼠标抬起时,只需要找到这个生成的水波节点修改透明度,再等到透明度修改动画结束之后将水波纹节点移除即可
function removeRipple() { const container = this const ripples = container.querySelectorAll('.my-ripple') if (!ripples.length) { return } const lastRipple = ripples[ripples.length - 1] // 通过水波的创建时间计算出扩散动画还需要执行多久,确保每一个水波都完整的执行了扩散动画 const delay = 300 - performance.now() + Number(lastRipple.dataset.createdAt) setTimeout(() => { lastRipple.style.opacity = `0` setTimeout(() => lastRipple.parentNode?.removeChild(lastRipple), 300) }, delay) } const VRipple = { mounted(el) { el.addEventListener('mousedown', createRipple) document.addEventListener('mouseup', removeRipple) }, unmounted(el) { el.removeEventListener('mousedown', createRipple) document.removeEventListener('mouseup', removeRipple) } }
通过指令binding去扩展你的水波选项
你还可以通过binding去扩展你的指令,比如可以提供修改颜色,禁用状态等等选项,这里就不详细展开了。我们来看一下成果。
写在最后
到此为止我们就实现了一个简单的ripple指令,在我们的组件库中也有这样的指令,所以更完善的版本可以去看我们的源码。 先要感谢一下掘金社区,已经有一部分小伙伴开始pr一些代码到我们的仓库中来,我们也很高兴能和社区的小伙伴们去一起做这样一件事情,另外我们的组件库团队一直在募集爱好者来参与贡献,有兴趣的小伙伴欢迎加入讨论,加入方式就是直接去仓库提issue留邮箱,我们会第一时间处理,有没有兴趣都希望为我们点点star,关注一下我们,社区小伙伴的支持和兴趣是我们最大的动力。
仓库地址
文档地址
以上就是vue实现水波涟漪效果的点击反馈指令的详细内容,更多关于vue 点击反馈指令的资料请关注猪先飞其它相关文章!
相关文章
- 这篇文章主要介绍了vue中activated的用法,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...2021-01-03
基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件功能
这篇文章主要介绍了基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-02-23Antd-vue Table组件添加Click事件,实现点击某行数据教程
这篇文章主要介绍了Antd-vue Table组件添加Click事件,实现点击某行数据教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-17- 这篇文章主要介绍了vue 实现动态路由的方法,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-06
- 这篇文章主要介绍了Vue组件跨层级获取组件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-28
- 这篇文章主要介绍了Vue基于localStorage存储信息代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-16
- 这篇文章主要介绍了vue 监听 Treeselect 选择项的改变操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
- 这篇文章主要介绍了vue 获取到数据但却渲染不到页面上的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-19
antdesign-vue结合sortablejs实现两个table相互拖拽排序功能
这篇文章主要介绍了antdesign-vue结合sortablejs实现两个table相互拖拽排序功能,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-09- 最常见的多环境配置,就是开发环境配置,和生产环境配置,本文主要介绍了vue项目多环境配置的实现,感兴趣的可以了解一下...2021-07-20
- 这篇文章主要介绍了Vue 3.0 中 jsx 语法使用,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...2020-11-13
vue项目页面嵌入代码块vue-prism-editor的实现
这篇文章主要介绍了vue项目页面嵌入代码块vue-prism-editor的实现,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-30vuejs element table 表格添加行,修改,单独删除行,批量删除行操作
这篇文章主要介绍了vuejs element table 表格添加行,修改,单独删除行,批量删除行操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-18解决vue的router组件component在import时不能使用变量问题
这篇文章主要介绍了解决vue的router组件component在import时不能使用变量问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27vue Treeselect下拉树只能选择第N级元素实现代码
这篇文章主要介绍了vue Treeselect下拉树只能选择第N级元素实现代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01- 这篇文章主要为大家详细介绍了vue实现同时设置多个倒计时,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-05-20
- 这篇文章主要为大家详细介绍了vue实现div单选多选功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-07-16
Ant design vue table 单击行选中 勾选checkbox教程
这篇文章主要介绍了Ant design vue table 单击行选中 勾选checkbox教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-25- 这篇文章主要介绍了vue treeselect获取当前选中项的label实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
- 这篇文章主要介绍了Vue select 绑定动态变量的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-23