function createRipple(event, className) {
const btn = event.currentTarget;
const rect = btn.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = event.clientX - rect.left - size / 2;
const y = event.clientY - rect.top - size / 2;
const ripple = document.createElement('span');
ripple.className = `ripple ripple-${className}`;
Object.assign(ripple.style, {
width: ripple.style.height = size + 'px',
left: x + 'px', top: y + 'px'
});
btn.appendChild(ripple);
anime({ targets: ripple,
scale: [0, 4], opacity: [0.6, 0],
duration: 600, easing: 'easeOutCubic',
complete: () => ripple.remove()
});
}
核心原理
`getBoundingClientRect()` 获取按钮尺寸,`event.clientX/Y` 取点击的绝对坐标,两者相减得出相对按钮的圆心位置。涟漪 span 用 `position: absolute` 浮在按钮上,`scale: [0, 4]` 放大四倍同时透明度归零,制造扩散消失效果。`complete` 回调里删除 span 防止 DOM 堆积。
💡 涟漪尺寸用 `Math.max(width, height)` 保证圆形在任意形状按钮内都完整。若想要方形涟漪改成 `width` 和 `height` 分别等于按钮宽高即可。
getBoundingClientRect
scale animation
DOM cleanup
pointer-events