RN Animated做个多张图渐隐渐显切换的动画效果

本文介绍了一种使用React Native实现的图片淡入淡出动画效果,通过Animated组件和定时器控制图片的透明度和层级,实现了平滑过渡的动画效果。详细展示了动画参数配置和组件封装过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RN小白

/**
 *   duration: 1400, // 动画执行时间
 *   delay: 2000,   // 动画间隔时间
 *   easing: Easing.linear,    // 缓动函数
 *   startOpacity: 0,       // 动画初始透明度
 *   endOpacity: 1,     // 动画结束透明度
 *   startScale: 0.95,       // 动画初始放大比例
 *   endScale: 1,    // 动画结束放大比例
 *   cardStyle: {}        // 每个图片的样式
 *  list: [ {type:'',src:' '} ]  数据列表
 */
class ImageFade extends Component {

  constructor(props) {
    super(props)
    let list = this.props.list
    let row = list.length
    this.state = {
      // 第一个index
      zindex: new Animated.Value(row),
    }
    this.duration = this.props.duration || 1400;
    this.delay = this.props.delay || 2000;
    this.easing = this.props.easing || Easing.linear;
    this.startOpacity = this.props.startOpacity || 0;
    this.endOpacity = this.props.startOpacity || 1;
    this.startScale = this.props.startScale || 1;
    this.endScale = this.props.endScale || 1;
  }
  componentWillMount () {
    let list = this.props.list
    let row = list.length
    for (let index = 1; index <= row; index++) {
      let key = `opacity${index}`
      this.setState({
        [key]: new Animated.Value(index === 1 ? 1 : 0)
      })
    }
  }

  startAnimated = () => {
    let list = this.props.list
    let row = list.length
    let sequence = []
    for (let i = 1; i <= row; i++) {
      if (i === row) {
        // 最后一张
        sequence.push(
          // 第一张改变z-index
          Animated.timing(this.state.zindex, {
            toValue: 0,
            duration: 0,
            delay: 0,
            easing: this.easing // 缓动函数
          })
        )
        sequence.push(
          // 第一张显示
          Animated.timing(this.state.opacity1, {
            toValue: 1,
            duration: 0,
            delay: 0,
            easing: this.easing // 缓动函数
          })
        )
        sequence.push(
          // 最后一张隐藏
          Animated.timing(this.state[`opacity${i}`], {
            toValue: this.startOpacity,
            duration: this.duration,
            delay: this.delay,
            easing: this.easing // 缓动函数
          }))
        sequence.push(// 第一张改变z-index
          Animated.timing(this.state.zindex, {
            toValue: row,
            duration: 0,
            delay: 0,
            easing: this.easing // 缓动函数
          })
        )
      } else {
        sequence.push(
          // 第x张显示
          Animated.timing(this.state[`opacity${i + 1}`], {
            toValue: this.endOpacity,
            duration: 0,
            delay: 0,
            easing: this.easing // 缓动函数
          })
        )
        sequence.push(
          // 第x张隐藏
          Animated.timing(this.state[`opacity${i}`], {
            toValue: this.startOpacity,
            duration: this.duration,
            delay: this.delay,
            easing: this.easing // 缓动函数
          })
        )
      }
    }
    const animation = Animated.sequence(sequence)
    // const animation = Animated.sequence([
    //   // 第二张显示
    //   Animated.timing(this.state.opacity2, {
    //     toValue: this.endOpacity,
    //     duration: 0,
    //     delay: 0,
    //     easing: this.easing // 缓动函数
    //   }),
    //   // 第一张隐藏
    //   Animated.timing(this.state.opacity1, {
    //     toValue: this.startOpacity,
    //     duration: this.duration,
    //     delay: this.delay,
    //     easing: this.easing // 缓动函数
    //   }),

    //   // 第三张显示
    //   Animated.timing(this.state.opacity3, {
    //     toValue: this.endOpacity,
    //     duration: 0,
    //     delay: 0,
    //     easing: this.easing // 缓动函数
    //   }),
    //   // 第二张隐藏
    //   Animated.timing(this.state.opacity2, {
    //     toValue: this.startOpacity,
    //     duration: this.duration,
    //     delay: this.delay,
    //     easing: this.easing // 缓动函数
    //   }),

    //   // 第四张显示
    //   Animated.timing(this.state.opacity4, {
    //     toValue: this.endOpacity,
    //     duration: 0,
    //     delay: 0,
    //     easing: this.easing // 缓动函数
    //   }),
    //   // 第三张隐藏
    //   Animated.timing(this.state.opacity3, {
    //     toValue: this.startOpacity,
    //     duration: this.duration,
    //     delay: this.delay,
    //     easing: this.easing // 缓动函数
    //   }),

    //   // 第一张改变z-index
    //   Animated.timing(this.state.zindex, {
    //     toValue: 0,
    //     duration: 0,
    //     delay: 0,
    //     easing: this.easing // 缓动函数
    //   }),
    //   // 第一张显示
    //   Animated.timing(this.state.opacity1, {
    //     toValue: 1,
    //     duration: 0,
    //     delay: 0,
    //     easing: this.easing // 缓动函数
    //   }),
    //   // 第四张隐藏
    //   Animated.timing(this.state.opacity4, {
    //     toValue: this.startOpacity,
    //     duration: this.duration,
    //     delay: this.delay,
    //     easing: this.easing // 缓动函数
    //   }),

    //   // 第一张改变z-index
    //   Animated.timing(this.state.zindex, {
    //     toValue: 4,
    //     duration: 0,
    //     delay: 0,
    //     easing: this.easing // 缓动函数
    //   }),
    // ]);
    // animation.start()
    // 必须大于1才启动动画
    row > 1 && Animated.loop(animation, {
      useNativeDriver: true
    }).start();
  }

  render () {
    const imageAddStyle = {
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
    }
    const imageStyle = {
      width: '100%',
      height: '100%'
    }
    return (
      <View style={this.props.style}>
        {
          this.props.list.map((v, index) => {
            return (
              <Animated.View
                key={index}
                style={[
                  {
                    // 索引
                    zIndex: index === 0 ? this.state.zindex : this.props.list.length - index,
                    opacity: this.state[`opacity${index + 1}`],
                    transform: [
                      {
                        scale: this.state[`opacity${index + 1}`].interpolate({
                          inputRange: [0, 1],
                          outputRange: [this.startScale, this.endScale],
                        })
                      },
                    ],
                  },
                  imageAddStyle
                ]}
              >
                <Image
                  style={imageStyle}
                  source={{ uri: v.src }}
                />
              </Animated.View>
            )
          })
        }
      </View>
    );
  }

  componentDidMount () {
    this.startAnimated()
  }
}

做个简单的封装,使用如下:

<ImageFade
         duration={800}
         delay={5000}
         list={{ type: 'image', 'src': 'xxx.jpg' },{ type: 'image', 'src': 'xxx.jpg' }}
         style={{ height: 300, borderBottomColor: 'transparent', borderBottomWidth: 0, borderStyle: 'solid',  position: 'relative'}}
 />

参考原文简单修改
原文:https://blog.youkuaiyun.com/weixin_37695006/article/details/82664003

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值