纯 CSS rotate() 在 uni-app 小程序端无法实现真实抽奖,必须用 uni.createAnimation() 配合 JS 精确计算目标角度并维护 currentAngle 状态,而非依赖 transform 字符串解析或 animation。
transform: rotate() 做转盘动画行不通?直接说结论:纯 CSS rotate() 在 uni-app(尤其是小程序端)无法实现“真实抽奖”逻辑,因为旋转只是视觉效果,不带状态反馈、无法精确控制结束角度、且 H5 和小程序渲染行为不一致。你看到的“转完停在某一项”,大概率是靠 JS 算出目标角度后硬设的——但这个“硬设”本身就有坑。
animation + @keyframes 转不动或转不准小程序平台(如微信、支付宝)对 CSS 动画支持有限:animation 不能动态修改 @keyframes 的关键帧;也不能在动画运行中读取实时 transform 值;更麻烦的是,不同端对 ease-out、cubic-bezier 的插值计算有偏差,导致同一段代码在 H5 上转 8 圈,在小程序里只转 7.2 圈,最终停偏。
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(3600deg); } } 然后靠 class 切换触发——这无法控制终点animation-fill-mode: forwards 保最后状态,小程序里它经常失效或延迟生效transition + 实时 style.transform,而非声明式 animation
uni.createAnimation() 是唯一靠谱的起点小程序端真正可控的旋转 API 是 uni.createAnimation(),它绕过 CSS 渲染管线,走的是原生视图层动画通道,精度高、可中断、能监听完成回调。H5 端虽然也支持,但得 fallback 到 requestAnimationFrame 手动驱动,否则会卡顿。
{ duration: 3000, timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' } —— 这个贝塞尔曲线模拟“先快后慢再微调”的抽奖惯性感rotate(1234deg),得算:假设奖品共 8 份,每份 45°,抽中第 3 项(索引 2),则基础角 = 2 * 45 + 22.5(加半格居中),再加 n * 360(比如 5 圈 = 1800°),最终目标角 = 1800 + 2 * 45 + 22.5
animation.rotate(0).step() 重置,否则连续抽奖时角度会累加错乱transform 字符串解析很多人想从 element.style.transform 里正则提取 rotate(XXXdeg),这在小程序里根本拿不到实时值——它返回空字符串或旧值。正确做法是:自己记下起始角、目标角、当前动画进度(通过 animation.onFrameCallback 或 requestAnimationFrame 时间戳推算),在 animation.export().actions 完成后,直接用你预设的目标角反查奖品索引。
立即学习“前端免费学习笔记(深入)”;
currentAngle 变量,随动画帧更新,而不是去 DOM 里抓isSpinning = false 后,立刻根据目标角计算中奖项,别等 DOM 回馈uni.createSelectorQuery() 查元素位置做校验,注意它异步且有延迟,仅适合兜底,不能作主逻辑复杂点不在怎么转,而在怎么让“转”和“结果”彻底脱钩又严丝合缝——角度是算出来的,不是看出来的。这点容易被忽略,一上来就盯着 CSS 动画调参,反而越调越偏。