跳转到主内容
极星编程网:以代码为星,赴技术山海!

CSS如何实现点击盒子时产生向外扩散的涟漪效果_结合伪元素与Scale动画

涟漪效果的核心原理是用JS获取点击坐标并动态设置CSS变量,使::after伪元素圆心精准落在点击处,再通过transform: scale()动画实现扩散。纯CSS无法读取坐标,故必须结合JS计算偏移量、监听click事件、设置--x/--y变量,并配合relative定位、border-radius:50%及cubic-bezier过渡。 涟漪效果的核心原理是什么 本质是用
::after
伪元素 在点击位置生成一个圆形,初始
scale(0)
,再通过
transform: scale()
动画撑开,配合
opacity
淡出。关键不是“画圆”,而是让圆心精准落在鼠标点击坐标 —— 这必须靠 JS 获取
clientX/clientY
并设置为伪元素的
left/top
偏移。 为什么不能只用纯 CSS 实现完整涟漪 因为纯 CSS 无法读取点击坐标。常见误区是写死
left: 50%; top: 50%
,结果涟漪永远从盒子中心炸开,和点击位置无关。真实交互中用户可能点在右下角,涟漪也得从那里开始扩散。 必须用 JS 计算偏移量,并动态写入内联样式或自定义属性: 监听
click
事件,获取
e.clientX - rect.left
和
e.clientY - rect.top
把这两个值设为元素的
style.setProperty('--x', x + 'px')
和
--y
CSS 中用
left: var(--x); top: var(--y)
定位伪元素圆心 如何用
::after
伪元素画出圆形涟漪 伪元素本身不接受 JS 操作,所以定位和动画必须靠 CSS 变量 +
transform
配合。注意几个硬性约束: 立即学习 “ 前端免费学习笔记(深入) ”; 使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件 如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Andr​​oid友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Andr​​oid应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更 下载
position: relative
必须加在目标盒子上,否则
::after
的
absolute
会相对 body 定位
::after
要设
content: ''
、
border-radius: 50%
、
background: rgba(0,0,0,0.1)
动画用
transform: scale(0) → scale(3)
,别用
width/height
,否则触发重排,卡顿 过渡时间建议
transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94)
,比线性更自然 示例关键 CSS:
.ripple { position: relative; overflow: hidden; } .ripple::after { content: ''; position: absolute; width: 10px; height: 10px; background: rgba(0,0,0,0.2); border-radius: 50%; transform: translate(-50%, -50%) scale(0); transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); left: var(--x, 50%); top: var(--y, 50%); }
点击后如何清理已播放的涟漪动画 连续点击会叠加多个
::after
动画实例?不会 —— 伪元素只有一个,但多次设置
--x/--y
会让它跳到新位置并重新播放 scale 动画。问题在于:如果用户快速连点,前一个动画还没结束,新动画会打断它,导致缩放不完整。 解决办法是加节流或等动画结束再允许下一次触发: 用
getComputedStyle(el).getPropertyValue('transform')
判断是否还在动(不推荐,性能差) 更稳妥的是用
setTimeout
记录状态,比如设置
isRippling = true
,0.45s 后置为
false
或者直接在每次点击时先重置:
el.style.removeProperty('--x'); el.style.removeProperty('--y')
,再设新值,强制重绘 真正容易被忽略的是:如果盒子有
border
或
padding
,
rect.left/top
计算要减去它们,否则偏移错位。用
getBoundingClientRect()
是最稳的。

相关文章