纯css变量无法动态计算波纹扩散半径,必须用js将点击坐标转为按钮内偏移后写入--x/--y,并通过radial-gradient或伪元素transform:scale()实现;e.offsetx因兼容性与失真问题不可靠,须用getboundingclientrect()配合clientx/clienty计算像素偏移,单位必须显式加px;伪元素需left:var(--x)、top:var(--y)、translate(-50%,-50%)定位起点并设border-radius:50%;连续点击前须重置--x/--y;扩散半径应基于按钮对角线自适应,用math.sqrt(width²+height²)×1.2计算;动画优先用transform:scale()避免重排;需加transform:translatez(0)确保合成层就绪。

纯 CSS 变量无法动态计算扩散半径,必须靠 JS 把点击坐标转成按钮内偏移后写入 --x/--y,再用 radial-gradient 或伪元素 transform: scale() 驱动视觉扩散——漏掉 JS 坐标归一化这步,波纹永远从中心炸开。
为什么不能直接用 e.offsetX 写入 --x
e.offsetX 在 IE 中不支持,且在有 transform、scale 或嵌套 iframe 的按钮里返回值严重失真。真实项目中 90% 的波纹偏移错误都源于此。
- 必须调用
button.getBoundingClientRect()获取按钮左上角相对于视口的left/top - 用
e.clientX - rect.left算出 X 方向相对按钮的像素偏移,Y 同理 - 写入时单位必须显式带
px:button.style.setProperty('--x', x + 'px'),否则 CSS 里var(--x)无法参与定位或calc()
radial-gradient 如何配合变量控制扩散起点
伪元素用 background-image: radial-gradient(circle, #fff 10%, transparent 10.01%) 模拟水波,但起点必须锚定到点击点,不能靠 background-position 动态设——它不响应 CSS 变量变化。
- 正确做法:伪元素设
left: var(--x); top: var(--y); transform: translate(-50%, -50%) scale(0) -
border-radius: 50%必须加,否则是方形光晕 - 每次点击前先重置:
button.style.setProperty('--x', '0px'),否则连续点击时新波纹从旧坐标起始
扩散半径如何随按钮尺寸自适应
硬编码 width/height 会导致小按钮溢出、大按钮波纹过小。应让扩散范围覆盖按钮最大对角线距离。
- JS 中计算:
const maxRadius = Math.sqrt(rect.width ** 2 + rect.height ** 2) * 1.2 - 写入变量:
button.style.setProperty('--radius', maxRadius + 'px') - CSS 中用:
width: calc(var(--radius) * 2); height: calc(var(--radius) * 2)控制伪元素初始尺寸 - 动画用
transform: scale(0) → scale(1),比改width/height更高性能(不触发重排)
最常被忽略的是:伪元素插入后第一帧渲染依赖浏览器合成层就绪,若按钮在 will-change: transform 容器内或存在频繁滚动,需提前给按钮加 transform: translateZ(0) 强制硬件加速,否则首帧延迟明显。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











