对于使用Taro实现红包摇一摇的效果
在 Taro 中实现红包摇一摇的效果可以按照以下步骤操作:
- 通过
Taro.startAccelerometer()打开手机的加速计功能。 - 在页面渲染完成后,监听手机加速计数值的变化,当手机在三个方向(x、y、z)上的加速度偏差较大时,认为手机进行了震动或摇晃的动作。
- 根据触发条件,触发摇一摇红包雨的效果。这里可以使用 Taro 自带的动画组件以及 setTimeout 定时器来实现一个简单的红包雨下落效果。
- 在摇一摇过程中可以通过
Taro.stopAccelerometer()方法来关闭加速计功能。
实现红包摇一摇的代码如下所示:
import Taro, { Component } from '@tarojs/taro'
import { View, Image, Text, Button } from '@tarojs/components'
import './index.less'
class Shake extends Component {
config = {
navigationBarTitleText: '摇一摇',
backgroundColor: '#ffffff'
}
state = {
shaking: false,
redEnvelopeList: []
}
shakeRedEnvelope = () => {
const { shaking, redEnvelopeList } = this.state
if (shaking || redEnvelopeList.length > 0) return
let x, y, z, lastX, lastY, lastZ, diff // 定义加速度数据变量
let waitTime = 0 // 定义等待时间变量,用于控制重力感应采集频率
const INTERVAL = 200 // 重力感应数据采集频率,单位毫秒
const SHAKE_THRESHOLD = 700 // 触发摇一摇的加速度差值阈值
Taro.startAccelerometer() // 开启手机加速计数据监听
let shakeInterval = setInterval(() => {
waitTime += INTERVAL
if (waitTime < 2000) return // 等待两秒后才开始检测摇一摇事件,避免误操作
Taro.onAccelerometerChange(({ x, y, z }) => {
if (!lastX) {
lastX = x
lastY = y
lastZ = z
return
}
diff = Math.abs(x + y + z - lastX - lastY - lastZ)
if (diff >= SHAKE_THRESHOLD) {
this.triggerRedEnvelopeRain()
}
lastX = x
lastY = y
lastZ = z
})
}, INTERVAL)
this.setState({ shaking: true, shakeInterval })
setTimeout(() => {
clearInterval(shakeInterval)
Taro.stopAccelerometer()
this.setState({ shaking: false })
}, 5000)
}
triggerRedEnvelopeRain = () => {
const redEnvelopeList = []
for (let i = 0; i < 10; i++) {
redEnvelopeList.push({
id: Date.now().toString() + Math.random(),
left: Math.floor(Math.random() * 250),
top: -50,
scale: Math.random() * 2 + 1
})
}
this.setState({ redEnvelopeList }, () => {
setTimeout(() => {
this.setState({ redEnvelopeList: [] })
}, 3000)
})
}
render() {
const { shaking, redEnvelopeList } = this.state
const redEnvelopeRain = redEnvelopeList.map(redEnvelope => {
return (
<View
key={redEnvelope.id}
className='red-envelope-item'
style={{ left: `${redEnvelope.left}px`, top: `${redEnvelope.top}px` }}
animation={[
{
className: 'move',
duration: 2000,
timingFunction: 'linear',
delay: 0
},
{
className: 'fall',
duration: 1500,
timingFunction: 'ease-in-out',
delay: 500
}
]}
>
<Image src='https://cdn.jsdelivr.net/gh/lin-xin/wxapp/red-envelope.png' mode='widthFix' style={{ width: `${36 * redEnvelope.scale}px` }} />
</View>
)
})
return (
<View className='shake'>
<View className='tishi-text'>{shaking ? '红包可下雨!' : '摇一摇获取红包'}</View>
<View className='shake-content'>
<Button className='shake-btn' onClick={this.shakeRedEnvelope}>摇一摇</Button>
<View className='shake-image-container' animation={shaking ? 'ani-shake' : ''}>
<Image className='shake-image' src='https://cdn.jsdelivr.net/gh/lin-xin/wxapp/shake.png' mode='widthFix' />
</View>
</View>
{redEnvelopeRain}
</View>
)
}
}
export default Shake