用css变量而非写死left/top,因::after伪元素无法被js直接修改样式,但能响应--x/--y变化;需在mousedown中计算相对偏移并减半宽高以中心为原点,再通过transform-origin: calc(50% + var(--x)) calc(50% + var(--y))锚定点击点,动画后须及时removeproperty清空变量防错位。

为什么用 CSS 变量而不是直接写死 left/top?
因为伪元素 ::after 无法在 JS 中直接读取或修改其 left/top,但能响应 CSS 自定义属性变化;用 --x 和 --y 把坐标传进 CSS,再通过 calc() 或 translate() 计算位置,就能避免每次点击都手动操作 DOM 样式,也规避了伪元素复用时的坐标残留问题。
如何用 --x 和 --y 控制涟漪起始点?
关键不是“设值”,而是“怎么设得准”。必须在 mousedown 或 touchstart 事件里计算相对偏移,再赋给按钮的 style.setProperty():
-
event.clientX - btn.getBoundingClientRect().left得到相对于按钮左边缘的 X 坐标 -
event.clientY - btn.getBoundingClientRect().top得到 Y 坐标 - 然后统一减去按钮宽高的一半:
btn.offsetWidth / 2和btn.offsetHeight / 2,让坐标以中心为原点(否则transform-origin会错位) - 最后调用
btn.style.setProperty('--x', x + 'px')和btn.style.setProperty('--y', y + 'px')
注意:不要用 click 事件——它比 mousedown 晚,用户松手时涟漪已开始动画,坐标可能漂移。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
transform: translate(var(--x), var(--y)) scale(0) 为什么必须加 transform-origin: center?
因为 scale() 默认以元素中心缩放,而涟漪要从点击点出发。如果只靠 translate() 移动位置却不改 transform-origin,放大时圆心仍是伪元素自身中心,不是你点的位置。
- 伪元素
::after必须设width: 100%; height: 100%,否则transform-origin: center无效 -
transform-origin要写成transform-origin: calc(50% + var(--x)) calc(50% + var(--y))才真正锚定点击点(不是center) - Chrome 112+ 支持该语法,但 Safari 16.6 之前不认
calc()在transform-origin里的写法,得 fallback 到 JS 动态设置style.transformOrigin
动画结束后怎么清空变量防止下次点击错位?
CSS 变量不会自动重置,上次点击留下的 --x/--y 会在下一次动画里继续生效,导致涟漪从错误位置炸开。
- 不能靠
transitionend清——伪元素没这个事件 - 必须监听伪元素动画结束:给
::after加animation: ripple 600ms forwards,然后用 JS 监听animationend事件 - 事件回调里执行
btn.style.removeProperty('--x')和btn.style.removeProperty('--y') - 更稳妥的做法是:每次点击前先清空,再设新值,避免残留
真机调试时最容易漏掉这步,尤其连点场景下,第二个涟漪常从上个坐标炸开——这不是 bug,是变量没清理干净。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










