Demo is included in this tweet
Last active
December 12, 2019 06:01
-
-
Save wachunei/79a576f9a80f135274c396d8d98e2f51 to your computer and use it in GitHub Desktop.
Replicating Twitter iOS splash screen animation on React Native during redux rehydration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import { Animated, Easing, StatusBar, MaskedViewIOS, View } from 'react-native'; | |
class AnimatedGate extends Component { | |
constructor(props) { | |
super(props); | |
this.beginAnimation = this.beginAnimation.bind(this); | |
this.state = { | |
animation: new Animated.Value(0), | |
}; | |
} | |
componentDidMount() { | |
StatusBar.setHidden(true); | |
} | |
componentWillReceiveProps(nextProps) { | |
if (!this.props.bootstraped && nextProps.bootstraped) { | |
setTimeout(() => this.beginAnimation(), 1000); | |
} | |
} | |
beginAnimation() { | |
const duration = 1300; | |
setTimeout(() => StatusBar.setHidden(false, 'fade'), 0.6 * duration); | |
Animated.timing(this.state.animation, { | |
toValue: 100, | |
duration, | |
easing: Easing.bezier(0.42, 0, 0.42, 1), | |
}).start(); | |
} | |
render() { | |
const { animation } = this.state; | |
const opacity = animation.interpolate({ | |
inputRange: [0, 30, 70], | |
outputRange: [0, 0, 1], | |
extrapolate: 'clamp', | |
}); | |
const MainApp = ( | |
<View style={styles.mainContainer}> | |
<Animated.View | |
style={{ | |
flex: 1, | |
opacity, | |
transform: [ | |
{ | |
scale: animation.interpolate({ | |
inputRange: [0, 50, 100], | |
outputRange: [1.05, 1.05, 1], | |
}), | |
}, | |
], | |
}} | |
> | |
{this.props.children} | |
</Animated.View> | |
</View> | |
); | |
const MaskElement = ( | |
<View style={styles.maskElementContainer}> | |
<Animated.Image | |
source={require('./twitter_logo.png')} | |
style={[ | |
styles.logo, | |
{ | |
transform: [ | |
{ | |
scale: animation.interpolate({ | |
inputRange: [0, 30, 100], | |
outputRange: [1, 0.8, 40], | |
extrapolate: 'clamp', | |
}), | |
}, | |
], | |
}, | |
]} | |
/> | |
</View> | |
); | |
return ( | |
<View style={styles.gateContainer}> | |
<MaskedViewIOS style={styles.maskedView} maskElement={MaskElement}> | |
{MainApp} | |
</MaskedViewIOS> | |
</View> | |
); | |
} | |
} | |
const styles = { | |
gateContainer: { | |
flex: 1, | |
backgroundColor: 'rgb(29, 161, 242)', | |
}, | |
mainContainer: { | |
flex: 1, | |
backgroundColor: 'white', | |
}, | |
maskedView: { | |
flex: 1, | |
}, | |
maskElementContainer: { | |
flex: 1, | |
backgroundColor: 'transparent', | |
justifyContent: 'center', | |
alignItems: 'center', | |
}, | |
logo: { | |
width: 62, | |
height: 62, | |
}, | |
}; | |
export default AnimatedGate; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# App is a regular redux app, but PersistGate | |
# takes a function as a child component. | |
# (see https://github.com/rt2zz/redux-persist/pull/718) | |
import React, { Component } from 'react'; | |
import { Provider } from 'react-redux'; | |
import { PersistGate } from 'redux-persist/src/integration/react'; | |
import Main from './Main'; | |
import AnimatedGate from './AnimatedGate'; | |
import configureStore from './configureStore'; | |
const { store, persistor } = configureStore(); | |
export default class App extends Component { | |
render() { | |
return ( | |
<Provider store={store}> | |
<PersistGate persistor={persistor}> | |
{bootstraped => ( | |
<AnimatedGate bootstraped={bootstraped}> | |
<Main /> | |
</AnimatedGate> | |
)} | |
</PersistGate> | |
</Provider> | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Twitter UI mockup (is an image) | |
import React from 'react'; | |
import { View, Image, StatusBar } from 'react-native'; | |
const Main = () => ( | |
<View style={styles.container}> | |
<StatusBar barStyle="light-content" /> | |
<Image | |
source={require('./twitterimage.jpeg')} | |
style={styles.image} | |
resizeMode="contain" | |
/> | |
</View> | |
); | |
const styles = { | |
container: { | |
flex: 1, | |
justifyContent: 'center', | |
alignItems: 'center', | |
}, | |
image: { | |
flex: 1, | |
}, | |
}; | |
export default Main; |
Please, you can share the 'configureStore' file and ours references?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to replicate this on android ?