H5转盘抽奖“先加速、再减速”动画应优先用CSS @keyframes配合cubic-bezier缓动(如0.2,0.7,0.3,1)分三段控制节奏,或用requestAnimationFrame结合easeOutCubic等JS缓动函数实现精准物理感减速。

在 H5 转盘抽奖中实现“先加速、再减速”的指针动画效果,核心不是靠多个 setTimeout 拼接,而是用 CSS 动画关键帧(@keyframes)配合缓动函数 或 JavaScript 动态控制 transform + requestAnimationFrame 实现更精准的物理感减速。下面分两种主流、实用的方式说明:
✅ 方式一:CSS @keyframes + 自定义 cubic-bezier 缓动
这是最轻量、兼容性好、推荐优先尝试的方法。关键在于把整个旋转过程拆成两段节奏,并用非线性贝塞尔曲线模拟“先快后慢”:
- 设定总动画时长(如 3s),但不要用 ease-in-out —— 它是匀称的,不符合“前段明显加速、后段拉长减速”的抽奖感
- 改用
cubic-bezier(0.3, 0.8, 0.2, 1)这类「先陡升、后缓落」的曲线(可到 cubic-bezier.com 可视化调试) - 关键帧中不写 0%→100%,而是用 0%→80%→100% 三段控制节奏:前 80% 时间快速转完大部分角度,最后 20% 时间拉长、缓慢到位
示例代码:
@keyframes spinSlowEnd {
0% { transform: rotate(0deg); }
80% { transform: rotate(1080deg); } /* 快速转3圈 */
100% { transform: rotate(1125deg); } /* 再微调45°停在目标扇区,耗时占整段20% */
}
.prize-pointer {
animation: spinSlowEnd 3s cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
}⚠️ 注意:最终停角(如 1125deg)需根据奖品位置动态计算,建议 JS 计算好后再加 class 触发动画。
✅ 方式二:requestAnimationFrame + easing 函数(更可控)
当需要精确控制停顿时机、支持中途取消、或要叠加惯性/回弹等效果时,JS 方案更灵活。核心是用缓动函数映射时间进度 t ∈ [0,1] 到旋转角度,选用「先快后慢」的 easing 公式:
- 推荐使用
easeOutCubic:f(t) = 1 - (1 - t)³—— 前半程增速快,后半程明显放缓 - 也可用
easeOutQuint(五次方)让减速更强烈,适合强调“悬念感” - 动画启动时记录开始时间,每帧用
performance.now()算出已过比例t,代入函数得当前旋转进度,再乘以总角度
简化逻辑示意:
const totalAngle = baseAngle + extraSpin; // 如 1080 + 45
const startTime = performance.now();
const duration = 3000;
<p>function animate(timestamp) {
const elapsed = timestamp - startTime;
const t = Math.min(elapsed / duration, 1);
const easedT = 1 - Math.pow(1 - t, 3); // easeOutCubic
const currentAngle = easedT * totalAngle;</p><p>pointer.style.transform = <code>rotate(${currentAngle}deg)</code>;</p><p>if (t < 1) requestAnimationFrame(animate);
}
requestAnimationFrame(animate);? 补充技巧:增强真实感
- 加轻微晃动:快停前(如 t > 0.9)在角度上叠加 ±2° 正弦扰动,模拟机械指针惯性抖动
- 声音同步:在 t ≈ 0.95 时播放“咔哒”声效,强化停顿反馈
- 禁用交互:动画开始即 disable 抽奖按钮,结束再恢复,避免重复触发
不复杂但容易忽略:CSS 方案快且稳,适合大多数场景;JS 方案自由度高,适合定制化强或需中断逻辑的业务。选哪个,取决于你是否需要“在转到 80% 时突然决定多加一圈”这类动态决策。


















