You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在map函数中实现随机动画 - Expo + Reanimated2

解决React Native随机单个View缩放动画问题

你的核心问题在于用了全局共享值控制所有View的动画,而且ref的存储方式有误,导致无法单独控制单个元素。下面是修复后的完整代码:

import { useRef, useEffect } from 'react'
import { View, StyleSheet, TouchableOpacity } from 'react-native'
import Animated, { useAnimatedStyle, useSharedValue, withTiming, withSpring, withRepeat } from 'react-native-reanimated'

const SIZE = 65.0

const RandomZoomInScreen = ({ navigation }) => {
  // 页面挂载时的全局缩放动画
  const scale = useSharedValue(0)
  // 给每个方块单独分配共享值,控制各自的弹跳动画
  const bounceValues = useRef([
    useSharedValue(1),
    useSharedValue(1),
    useSharedValue(1),
    useSharedValue(1),
  ]).current
  const itemEls = useRef([])

  // 全局初始缩放样式
  const reanimatedStyle = useAnimatedStyle(() => {
    return {
      transform: [{ scale: scale.value }]
    }
  })

  // 生成单个方块的弹跳动画样式
  const getBounceStyle = (index) => {
    return useAnimatedStyle(() => {
      return {
        transform: [{ scale: bounceValues[index].value }]
      }
    })
  }

  // 页面挂载时的全局缩放动画
  useEffect(() => {
    scale.value = withSpring(1, { stiffness: 200 })
    return () => {
      scale.value = 0
    }
  }, [])

  // 每4秒随机触发一个方块的弹跳动画
  useEffect(() => {
    const intervalId = setInterval(() => {
      // 随机选一个方块的索引
      const randomIndex = Math.floor(Math.random() * 4)
      // 只更新选中方块的共享值
      bounceValues[randomIndex].value = withRepeat(withTiming(1.3), 2, true)
    }, 4000)

    return () => clearInterval(intervalId)
  }, [])

  return (
    <View style={styles.container}>
      {[1, 2, 3, 4].map((square, index) => {
        return (
          <TouchableOpacity activeOpacity={0.7} key={index}>
            <Animated.View
              ref={(el) => (itemEls.current[index] = el)}
              style={[styles.square, reanimatedStyle, getBounceStyle(index)]}
            />
          </TouchableOpacity>
        )
      })}
    </View>
  )
}

export default RandomZoomInScreen

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'space-evenly',
    alignItems: 'center'
  },
  square: {
    width: SIZE * 2,
    height: SIZE,
    backgroundColor: 'green',
  }
})

关键改动说明:

  • 单个元素的共享值:把原来的单个bounce共享值改成数组bounceValues,每个元素对应一个方块的动画状态,这样就能单独控制每个方块的缩放。
  • 修正ref存储:原来的push会导致每次渲染都往数组里加元素,改成直接按索引赋值itemEls.current[index] = el,保证每个位置只存对应方块的引用。
  • 独立的动画样式:用getBounceStyle函数为每个方块生成专属的动画样式,绑定对应的共享值。
  • 随机触发逻辑:定时器里生成随机索引,只更新对应索引的共享值,实现单个方块的动画效果。

内容的提问来源于stack exchange,提问作者4aLifeTime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:05:16