记录一下使用Taro.createAnimation(微信小程序Animation api)实现动画效果
效果

素材

代码实现
import { useEffect, useState } from 'react'
import Taro from '@tarojs/taro'
import { View, Image } from '@tarojs/components'
import a from './a.png'
import b from './b.png'
import c from './c.png'
import d from './d.png'
import e from './e.png'
import f from './f.png'
import g from './g.png'
const SHOW_UP_DURATION = 1000
const SHOWING_DURATION = 300
interface AnimationData {
actions: TaroGeneral.IAnyObject[]
}
function getAnimationData (): AnimationData {
return {
actions: []
}
}
export default function TestAnimate () {
const [wrapAnimationData, setWrapAnimationData] = useState<AnimationData>(getAnimationData())
const [upAnimationData, setUpAnimationData] = useState<AnimationData>(getAnimationData())
const [downAnimationData, setDownAnimationData] = useState<AnimationData>(getAnimationData())
const [rotateLeftAnimationData, setLeftRotateAnimationData] = useState<AnimationData>(getAnimationData())
const [rotateRightAnimationData, setRightRotateAnimationData] = useState<AnimationData>(getAnimationData())
const startWrapAnimation = () => {
const animation = Taro.createAnimation({
duration: SHOW_UP_DURATION,
timingFunction: 'ease-out'
})
// 同时旋转和放大
animation.scale(1).rotateY(0).step()
setWrapAnimationData(animation.export())
}
const startUpAnimation = () => {
const animation = Taro.createAnimation({
duration: SHOWING_DURATION,
timingFunction: 'ease-out'
})
animation.translateY(0).step({ duration: 0, delay: SHOW_UP_DURATION })
// 向上移动
animation.translateY(-6).step({ timingFunction: 'ease-in-out' })
// 回到原位
animation.translateY(0).step({ timingFunction: 'ease-in-out' })
setUpAnimationData(animation.export())
}
const startDownAnimation = () => {
const animation = Taro.createAnimation({
duration: SHOWING_DURATION,
timingFunction: 'ease-out'
})
animation.translateY(0).step({ duration: 0, delay: SHOW_UP_DURATION })
// 向下移动
animation.translateY(6).step({ timingFunction: 'ease-in-out' })
// 回到原位
animation.translateY(0).step({ timingFunction: 'ease-in-out' })
setDownAnimationData(animation.export())
}
const startLeftRotateAnimation = () => {
const animation = Taro.createAnimation({
duration: SHOWING_DURATION,
timingFunction: 'ease-in-out',
transformOrigin: '100% 100%'
})
animation.rotateZ(0).step({ duration: 0, delay: SHOW_UP_DURATION })
// 逆时针旋转5度
animation.rotateZ(-5).step()
// 回到原位
animation.rotateZ(0).step()
setLeftRotateAnimationData(animation.export())
}
const startRightRotateAnimation = () => {
const animation = Taro.createAnimation({
duration: SHOWING_DURATION,
timingFunction: 'ease-in-out',
transformOrigin: '0% 100%'
})
animation.rotateZ(0).step({ duration: 0, delay: SHOW_UP_DURATION })
// 顺时针旋转5度
animation.rotateZ(5).step()
// 回到原位
animation.rotateZ(0).step()
setRightRotateAnimationData(animation.export())
}
useEffect(() => {
startWrapAnimation()
startUpAnimation()
startDownAnimation()
startLeftRotateAnimation()
startRightRotateAnimation()
}, [])
return (
<View
animation={wrapAnimationData}
style={{
width: '300rpx',
height: '300rpx',
position: 'absolute',
top: '50%',
left: '50%',
marginTop: '-150rpx',
marginLeft: '-150rpx',
transform: 'scale(0.3) rotateY(-180deg)'
}}
>
<View animation={upAnimationData} style={{ position: 'absolute', top: '0', left: '0' }}>
<Image src={a} mode="widthFix" style={{ width: '100rpx' }} />
</View>
<View animation={downAnimationData} style={{ position: 'absolute', top: '0', right: '0' }}>
<Image src={b} mode="widthFix" style={{ width: '100rpx' }} />
</View>
<View animation={downAnimationData} style={{ position: 'absolute', top: '80rpx', left: '0' }}>
<Image src={c} mode="widthFix" style={{ width: '100rpx' }} />
</View>
<View animation={upAnimationData} style={{ position: 'absolute', top: '80rpx', right: '0' }}>
<Image src={d} mode="widthFix" style={{ width: '100rpx' }} />
</View>
<View animation={rotateLeftAnimationData} style={{ position: 'absolute', top: '170rpx', left: '14rpx' }}>
<Image src={e} mode="widthFix" style={{ width: '100rpx' }} />
</View>
<View animation={rotateRightAnimationData} style={{ position: 'absolute', top: '168rpx', right: '20rpx' }}>
<Image src={f} mode="widthFix" style={{ width: '100rpx' }} />
</View>
<Image src={g} mode="widthFix" style={{ width: '100%' }} />
</View>
)
}
注意点
- 初始化
animation的值时,不能用undefined(useState<AnimationData>())或者null(useState<AnimationData>(null)),必须要是一个对象才行 - animation加在Image上不起作用, 貌似必须加在View上才能生效
"Knowledge isn't free. You have to pay attention."

浙公网安备 33010602011771号