React中使用Keyframes实现图片随机起始位置无限旋转
问题原因
CSS动画运行期间,@keyframes中定义的属性会覆盖元素上直接设置的同属性样式。原有代码在内联style中写入的transform: rotate(随机角度)优先级低于动画帧内的transform声明,会被直接忽略,因此动画始终从keyframes定义的0度位置启动,不符合预期。
实现方案
通过CSS变量传参即可实现需求,不需要动态生成@keyframes规则,同时支持随机起始角度、随机旋转方向,运行性能更好。
1. 组件代码调整
在组件中生成随机初始角度、随机旋转步长,作为CSS变量传给img元素:
import { useMemo } from 'react' // 组件内部逻辑 // 空数组依赖保证随机值仅在组件挂载时生成一次,不会随重渲染跳变 const { initRotate, rotateStep } = useMemo(() => { const randomAngle = Math.floor(Math.random() * 361) // 随机生成正负360度,正值顺时针旋转,负值逆时针旋转 const step = Math.random() > 0.5 ? 360 : -360 return { initRotate: `${randomAngle}deg`, rotateStep: `${step}deg` } }, []) return <img className={props.className} style={{ '--init-rotate': initRotate, '--rotate-step': rotateStep, animation: 'spin 5s linear infinite' } as React.CSSProperties} src={image} alt="img" />
2. 动画样式调整
修改spin关键帧,读取元素上的CSS变量计算旋转值:
@keyframes spin { from { transform: rotate(var(--init-rotate)); } to { transform: rotate(calc(var(--init-rotate) + var(--rotate-step))); } }
效果说明
- 每个图片实例挂载时会随机生成0-360度的初始角度,动画直接从该角度开始旋转,不会出现从0度跳变的问题
- 旋转方向完全随机,50%概率顺时针无限循环旋转,50%概率逆时针无限循环旋转
- 动画全程线性匀速,旋转满360度后无缝衔接循环,没有停顿或跳变
注意事项
- 上述TypeScript类型断言仅用于消除TS校验提示,JavaScript项目可直接删除
- 如果需要组件重渲染时重新随机旋转起点和方向,可以去掉useMemo包裹,直接在组件函数顶层生成随机值即可
- 该方案兼容所有现代浏览器,不需要额外引入polyfill
内容的提问来源于stack exchange,提问作者zalanshah64
相关产品推荐
相关产品推荐

