纯 css3 无法实现真正水波纹扩散动画,必须用 canvas 或 svg + javascript 才能模拟正弦波形、动态裁剪和进度控制;css 方案仅为缩放+透明度的视觉近似。

直接说结论:纯 CSS3 无法实现真正“水波纹扩散”动画,必须配合 canvas 或 SVG + JavaScript 才能生成数学建模的正弦波形、动态裁剪和随进度变化的涟漪半径;所谓“CSS-only 水波纹”基本是静态遮罩+缩放+透明度过渡的视觉近似,不具物理模拟特性,也不支持百分比进度控制。
为什么 background-image + transition 做不出真实水波纹
CSS 的 transition 和 @keyframes 只能驱动有限属性(transform、opacity、filter),无法按帧生成波峰/波谷路径。所谓“水波纹按钮”常见实现其实是:background-size 从 0% 突变到 200%,再叠加 border-radius: 50% 裁成圆形——这本质是「放大高斯模糊圆斑」,不是水波。
- 它不能响应点击位置(始终居中扩散)
- 无法控制波长、频率、衰减速度等物理参数
- 在 Retina 屏或不同 DPR 下容易模糊失真
-
filter: blur()在部分旧版 Safari 中渲染异常或性能卡顿
canvas 绘制圆形波浪的核心三步
真正可复用、可控制的水波纹效果,需用 canvas 手动绘制正弦波路径并裁剪进圆形区域。关键不在“动”,而在“怎么动”:
- 调用
ctx.beginPath()+ctx.arc()先画一个基准圆作为裁剪边界 - 用
ctx.clip()锁定后续所有绘制只在该圆内生效 - 循环计算角度 θ,用
Math.sin(θ * frequency + time * speed)动态偏移半径,连点成波
示例关键片段:
const canvas = document.getElementById('waveCanvas');
const ctx = canvas.getContext('2d');
function drawWave(progress) { // progress ∈ [0, 1]
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const baseRadius = Math.min(centerX, centerY) * 0.8;
<p>ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(centerX, centerY, baseRadius, 0, Math.PI * 2);
ctx.clip(); // ⚠️ 必须 clip 后再绘波形</p><p>ctx.beginPath();
for (let a = 0; a 2; a += 0.05) {
const r = baseRadius + Math.sin(a 4 + performance.now() <em> 0.002) </em> 10 <em> (1 - progress);
const x = centerX + Math.cos(a) </em> r;
const y = centerY + Math.sin(a) * r;
if (a === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
}
ctx.closePath();
ctx.fillStyle = 'rgba(66, 133, 244, 0.6)';
ctx.fill();
}</p>
响应式适配时最易忽略的两个坑
canvas 元素默认是 300×150 像素,且其内部绘图坐标系与 CSS 渲染尺寸无关——这是绝大多数人动画错位、模糊、拉伸的根源。
- 必须显式设置
canvas.width和canvas.height为设备像素值(如canvas.width = canvas.offsetWidth * window.devicePixelRatio) - 每次窗口 resize 后,要重设 canvas 尺寸 + 重绘,不能只靠 CSS
width: 100%拉伸 - 若用于图片叠加,
<img>需设display: block防止底部留白;canvas应与img同级并用position: absolute叠加,而非包裹
真正做响应式水波纹,别纠结“能不能纯 CSS”,先确认是否需要精确进度反馈、点击定位、多层波干扰等交互需求——有,就老实用 canvas;只是要个悬停动效,用 background + scale 更轻量也更稳。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











