抽奖转盘需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">)加上过渡和初始样式:
<font size="2">
<pre class="brush:php;toolbar:false;">.wheel {
transition: transform 0.1s ease-out;
transform-origin: center;
}</pre>
</font>
<h3>JS 控制旋转:先加速/匀速,再减速停准</h3>
<p>真实抽奖不能靠预设动画播完——得动态算出目标角度,让转盘“自然停住”。常用做法是:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2900" title="Markdown to HTML"><img
src="https://img.php.cn/upload/skill/000/000/081/178938727468962.jpg" alt="Markdown to HTML" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill2900" title="Markdown to HTML" class="overflowclass">Markdown to HTML</a>
<p class="overflowclass">{"answer":"将 Markdown 转换为内嵌 CSS、样式精美的独立 HTML。完美适用于新闻简报、文档、报告及邮件模板。"}</p>
</div>
<a rel="nofollow" href="/xiazai/skill2900" title="Markdown to HTML" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>随机生成一个基础圈数(如 5~8 圈),再加一个 0~360° 的偏移量,确保每次停的位置不同</li>
<li>总旋转角度 = 圈数 × 360 + 偏移角;例如 6.72 圈 → 6×360 + 259.2° = 2419.2°</li>
<li>用 <code>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 滑动冲突










