如何通过更改React-Native中的状态从一个图像过渡到另一个图像

时间:2019-07-04 07:06:31

标签: reactjs react-native react-native-android

我有两张图像,它们之间几乎没有什么区别,每张图像都对应一个特定的状态。更改状态时,我需要从一个平滑过渡到另一个,以使效果感觉像只有两个图像中不同的部分都经过了动画处理,其余图像保持原样。 First

Second

我希望它能正常工作,以便在stateChange上渲染第二张图像时,只有第二张图像中的杆状部分看起来会淡入,其余部分保持静止。

我认为无需使用react-transition-group这样的动画库就可以实现这一点,这可能是通过使用React中的某些生命周期方法以及很明显的AnimatedAPI实现的。我面临的主要问题是,当我更新状态时,我无法控制先前渲染的图像。我希望以某种方式保留先前渲染的图像,直到出现新渲染的Component并对其进行动画处理为止。这是我尝试做的。我有这个ImageLoader组件,它可以在提供淡入淡出动画的同时渲染图像。

class ImageLoader extends React.Component {
  constructor(){
    super()
    this.opacity= new Animated.Value(0)
   }

    componentDidUpdate(){
   {this.onLoad()}

   } 

    onLoad = () => {
      this.opacity.setValue(0);
      Animated.timing(this.opacity, {
          toValue: 1,
          duration: 500,
          useNativeDriver: true,
      }).start();
   }

  render() {
    return (
      <Animated.Image onLoad={this.onLoad}{...this.props}style={[
          {opacity: this.opacity,}, this.props.style,
       ]} 
     />
    );
  }
 }



export default class App extends React.Component {
 state={
 no:1,
}

  render() {
  let Dun=()=>{return this.state.no==1?
   <ImageLoader source={require('./assets/img1.PNG')}/>: <ImageLoader 

     source={require('./assets/img2.PNG')}/>
    }
   const calc=()=>{
   this.setState((state)=>({no:Math.abs(state.no-1)}));
}
return (
  <View style={styles.container}>
    <View style={{height:100,marginLeft:50}}>

    {Dun()}

    <Button onPress={()=>{calc()}}> Press</Button>
    </View>
  </View>
);
}
}

1 个答案:

答案 0 :(得分:0)

您可以使用2张动画图像来给人一种印象,即它们正在逐渐淡入另一幅。这是根据您的示例提供的解决方案:

import React from 'react';
import { Animated, StyleSheet, Text, TouchableOpacity, View } from 'react-native';

import images from 'src/images';

const styles = StyleSheet.create({
  image: {
    position: 'absolute',
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
  }
});

class ImageSwitcher extends React.Component {
  fadeInOpacity = new Animated.Value(0);

  fadeOutOpacity = new Animated.Value(1);

  state = {
    prevSource: null
  };

  componentDidMount() {
    this.onLoad();
  }

  componentDidUpdate() {
    this.onLoad();
  }

  componentWillReceiveProps({ source: newSource }) {
    const { source } = this.props;
    if (newSource !== source) {
      this.setState({ prevSource: source });
    }
  }

  onLoad = () => {
    this.fadeInOpacity.setValue(0);
    this.fadeOutOpacity.setValue(1);

    Animated.timing(this.fadeInOpacity, {
      toValue: 1,
      duration: 500,
      useNativeDriver: true
    }).start();
    Animated.timing(this.fadeOutOpacity, {
      toValue: 0,
      duration: 500,
      useNativeDriver: true
    }).start();
  };

  render() {
    const { prevSource } = this.state;

    return (
      <View
        style={{
          width: 200,
          height: 200
        }}
      >
        <Animated.Image {...this.props} style={[styles.image, { opacity: this.fadeInOpacity }]} resizeMode="cover" />
        {prevSource && (
          <Animated.Image {...this.props} style={[styles.image, { opacity: this.fadeOutOpacity }]} resizeMode="cover" source={prevSource} />
        )}
      </View>
    );
  }
}

export default class App extends React.Component {
  state = {
    source: images.first
  };

  handleToggle = () => this.setState(({ source }) => ({ source: source === images.first ? images.second : images.first }));

  render() {
    const { source } = this.state;

    return (
      <View style={{ flex: 1 }}>
        <ImageSwitcher source={source} />
        <TouchableOpacity onPress={this.handleToggle}>
          <Text>Toggle Image</Text>
        </TouchableOpacity>
      </View>
    );
  }
}