应使用 lucky-canvas 或 almost-lottery 而非手写 CSS transform: rotate() 动画,因后者在小程序中不支持、H5 中易卡死;lucky-canvas 基于 Canvas 全平台兼容,内置概率加权、缓动动画等能力。
直接用 lucky-canvas 或 almost-lottery,别手写 css transform: rotate() 动画 —— 后者在小程序里根本不会动,h5 上第二次点击大概率卡死。
为什么 transform: rotate() 在 uni-app 里经常失效
浏览器对连续设置相同 transform 值会跳过重绘,尤其在 v-bind:style 动态绑定时;uni-app 编译到小程序后,view 组件根本不支持 CSS transform 动画,CSS transition 被静默忽略。
- 常见错误现象:
rotate(360deg)第一次有效,第二次点不动、转半圈就停、或角度突变 - 强制重排也不稳定:先设
rotate(0deg)再requestAnimationFrame设目标角,在 iOS WebView 和部分安卓微信里仍掉帧 - 真机卡顿根源:很多教程推荐的
will-change: transform在小程序渲染层反而引发撕裂,应改用transform: translateZ(0)
小程序平台必须走 uni.createAnimation API
微信/支付宝/抖音小程序只认原生动画 API,CSS 方案完全不可靠。H5 可 fallback,但多端项目必须以小程序逻辑为基准。
-
angle是累计总角度(例如:转 5 圈 + 停在第 2 格 →5 * 360 + 45),不是单次增量 - 必须等
this.$nextTick()后再调用animation.export(),否则动画不触发 - 动画 duration 至少设为
4000,搭配cubic-bezier(0.25, 0.46, 0.45, 0.94)模拟惯性减速,避免视觉误判 - 九宫格“格子数”和“扇区角度”不是简单除法:中奖落点要校准到扇区中心,即
targetAngle = baseAngle + (index * 360 / prizeCount) + (180 / prizeCount)
用 lucky-canvas 是当前最省心的跨端方案
它底层用 Canvas 渲染,绕过所有 CSS 兼容问题,H5、小程序、App 全平台表现一致,且已内置概率加权、动画缓动、生命周期钩子等生产级能力。
- 安装方式优先走 HBuilderX 插件市场,路径为
/uni_modules/lucky-canvas,比 npm 更稳 - 奖品数组必须用新引用赋值(如
this.prizes = [...newPrizes]),否则 Canvas 不重绘 - 若需服务端控制中奖结果,应在
@start钩子里发请求,拿到结果后再调用play()并传入index,不要依赖前端随机 - 文字反向旋转层级易错:Canvas 中奖品文字需手动 rotate(-angle),否则随转盘一起转,看起来是倒的
真正难的不是让转盘转起来,而是让「中奖结果」和「视觉落点」严丝合缝对上 —— 这需要统一校准起点(图片 0° 对齐第一个奖品中心)、统一计算偏移(+20° 而非 +0°)、统一处理多圈叠加(baseAngle 必须是 360 的整数倍)。这些细节一旦错一位,用户就会觉得“明明指到 iPhone 却弹出谢谢参与”。











