抽奖转盘需JS动态控制旋转角度与缓动停驻,结合CSS动画实现先匀速后减速效果,通过Web Animations API设置cubic-bezier缓动,绑定onfinish回调判定中奖并禁用重复点击。

点击“开始”后转盘先匀速旋转几圈,再逐渐减速停在某个奖项上,这是抽奖转盘的核心交互。关键不是单纯用 CSS 动画跑完就结束,而是要结合 JavaScript 控制动画节奏、绑定结束回调,并防止重复点击。
用 CSS @keyframes 定义基础旋转动画
先写一个可复用的旋转动画,不指定具体时长和迭代次数,方便 JS 动态控制:
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
给转盘元素(比如 <div class="wheel">)加上过渡和初始样式:
.wheel {
transition: transform 0.1s ease-out;
transform-origin: center;
}
JS 控制旋转:先加速/匀速,再减速停准
真实抽奖不能靠预设动画播完——得动态算出目标角度,让转盘“自然停住”。常用做法是:
立即学习“前端免费学习笔记(深入)”;
- 随机生成一个基础圈数(如 5~8 圈),再加一个 0~360° 的偏移量,确保每次停的位置不同
- 总旋转角度 = 圈数 × 360 + 偏移角;例如 6.72 圈 → 6×360 + 259.2° = 2419.2°
- 用
element.animate()或transform: rotate(Xdeg)+transition实现带缓动的结束过程
推荐用 Web Animations API,更可控:
const spinAnim = wheel.animate(
[{ transform: 'rotate(0deg)' }, { transform: `rotate(${totalDeg}deg)` }],
{
duration: 4000,
easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)', // 模拟先快后慢
fill: 'forwards'
}
);
spinAnim.onfinish = () => {
const prizeIndex = Math.floor((totalDeg % 360) / anglePerItem) % items.length;
showPrize(items[prizeIndex]);
};
禁用重复点击 + 点击反馈
用户手快连点会导致动画错乱或逻辑冲突,必须加状态锁:
- 点击“开始”按钮时立即将其
disabled = true,并加 loading 类(如旋转图标) - 动画结束后在
onfinish里恢复按钮状态:btn.disabled = false - 可选:点击瞬间播放短音效或震动(
navigator.vibrate?.(50)),增强反馈感
适配移动端点击区域与防误触
手机端容易误点两次,建议:
- 按钮使用
touchstart而非click,避免 300ms 延迟 - 添加
cursor: pointer和user-select: none防止文字选中干扰 - 转盘容器设
touch-action: none,避免 iOS 滑动冲突



















