Created
December 7, 2019 18:56
-
-
Save mmazzarolo/4b65db01423546a8c12ed21b72b56412 to your computer and use it in GitHub Desktop.
Skipping the splash screen in Ordinary Puzzles
This file contains 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, { FC, useRef } from "react"; | |
import { StyleSheet, Animated, TouchableWithoutFeedback } from "react-native"; | |
import { Text } from "pg-common"; | |
import { useAnimation, useOnMount, scale, delay } from "pg-utils"; | |
import { animations, metrics, colors } from "pg-design"; | |
import { credits } from "pg-config"; | |
const asyncAnimationStart = (anim: Animated.CompositeAnimation) => | |
new Promise(resolve => anim.start(resolve)); | |
interface SplashProps { | |
onHide: () => void; | |
} | |
export const Splash: FC<SplashProps> = function({ onHide }) { | |
// Refs for keeping track of the skipping state of the screen | |
const skippingEnabledRef = useRef(true); | |
const hasSkippedRef = useRef(false); | |
// Animations setup | |
const fadeCreditsAnimDuration = 200; | |
const fadeCreditsStaggerDuration = 100; | |
const backgroundColorAnimDuration = 200; | |
const fadeCreditsAnims = credits.map(useAnimation); | |
const backgroundColorAnim = useAnimation(); | |
const splashDuration = 2000; | |
const showAnim = Animated.stagger( | |
fadeCreditsStaggerDuration, | |
fadeCreditsAnims.map(anim => | |
anim.setup({ duration: fadeCreditsAnimDuration }) | |
) | |
); | |
const hideAnim = Animated.sequence([ | |
Animated.stagger( | |
fadeCreditsStaggerDuration, | |
fadeCreditsAnims.map(anim => | |
anim.setup({ duration: fadeCreditsAnimDuration, toValue: 0 }) | |
) | |
), | |
backgroundColorAnim.setup({ | |
duration: backgroundColorAnimDuration, | |
useNativeDriver: false | |
}) | |
]); | |
// Animate the screen in and then out on mount | |
// If the screen has been tapped while the delay is | |
// running, don't animate-out (the out animation has been | |
// already triggered by the tap). | |
const animate = async () => { | |
await asyncAnimationStart(showAnim); | |
await delay(splashDuration); | |
skippingEnabledRef.current = false; | |
if (!hasSkippedRef.current) { | |
await asyncAnimationStart(hideAnim); | |
onHide(); | |
} | |
}; | |
useOnMount(() => { | |
animate(); | |
}); | |
const rootAnimStyle = { | |
backgroundColor: backgroundColorAnim.value.interpolate({ | |
inputRange: [0, 1], | |
outputRange: [colors.splash, colors.primary[9]] | |
}) | |
}; | |
// If the user touches the screen, end the animation early | |
const handlePress = () => { | |
if (!skippingEnabledRef.current || hasSkippedRef.current) return; | |
hasSkippedRef.current = true; | |
hideAnim.start(onHide); | |
}; | |
return ( | |
<TouchableWithoutFeedback onPress={handlePress}> | |
<Animated.View style={[styles.root, rootAnimStyle]}> | |
{credits.map((credit, index) => ( | |
<Text | |
key={credit} | |
weight="bold" | |
style={[ | |
styles.credit, | |
animations.fadeSlideBottom(fadeCreditsAnims[index].value) | |
]} | |
> | |
{credit} | |
</Text> | |
))} | |
</Animated.View> | |
</TouchableWithoutFeedback> | |
); | |
}; | |
const styles = StyleSheet.create({ | |
root: { | |
padding: metrics.screenMargin, | |
flex: 1, | |
flexDirection: "column", | |
justifyContent: "center", | |
backgroundColor: colors.splash | |
}, | |
credit: { | |
color: "white", | |
fontSize: scale(28), | |
marginVertical: scale(12) | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment