1import { BlurTint, BlurView, BlurViewProps } from 'expo-blur'; 2import React, { useCallback, useRef, memo, useEffect } from 'react'; 3import { View, StyleSheet, Text, Image } from 'react-native'; 4import Animated, { 5 useAnimatedProps, 6 useSharedValue, 7 withRepeat, 8 withSequence, 9 withTiming, 10} from 'react-native-reanimated'; 11 12import useResettingState from '../../utilities/useResettingState'; 13import Slider from './Slider'; 14 15const AnimatedBlurView = Animated.createAnimatedComponent(BlurView); 16 17export default memo((props: { tint: BlurTint }) => { 18 const blurViewRef = useRef<View>(null); 19 const animatedIntensity = useSharedValue(0); 20 const manualIntensity = useSharedValue(0); 21 const [manualIntensityIsActive, setManualIntensityIsActive] = useResettingState(false, 3000); 22 23 const handleSliderChange = useCallback((value: number) => { 24 setManualIntensityIsActive(true); 25 manualIntensity.value = value; 26 }, []); 27 28 useEffect(() => { 29 // Use two with timing animations to make sure the animation always runs from 0 to 100 30 animatedIntensity.value = withRepeat( 31 withSequence(withTiming(100, { duration: 2000 }), withTiming(0, { duration: 2000 })), 32 -1, 33 true 34 ); 35 }, []); 36 37 const animatedProps = useAnimatedProps(() => { 38 return { 39 proxiedProperties: { 40 intensity: manualIntensityIsActive ? manualIntensity.value : animatedIntensity.value, 41 tint: props.tint, 42 }, 43 } as BlurViewProps; 44 }); 45 46 return ( 47 <View style={styles.container}> 48 <View style={styles.innerContainer}> 49 <Image style={styles.image} source={{ uri: 'https://source.unsplash.com/300x300' }} /> 50 <Text style={styles.blurredText}>This text is blurred</Text> 51 <AnimatedBlurView ref={blurViewRef} style={styles.blurView} animatedProps={animatedProps}> 52 <Text style={styles.nonBlurredText}>{props.tint}</Text> 53 <Slider 54 title="Manual intensity:" 55 onChange={handleSliderChange} 56 active={!!manualIntensityIsActive} 57 value={manualIntensity.value} 58 style={styles.slider} 59 /> 60 </AnimatedBlurView> 61 </View> 62 </View> 63 ); 64}); 65 66const styles = StyleSheet.create({ 67 container: { 68 alignItems: 'center', 69 justifyContent: 'center', 70 padding: 6, 71 }, 72 innerContainer: { 73 alignItems: 'center', 74 justifyContent: 'center', 75 }, 76 image: { 77 width: 250, 78 height: 250, 79 }, 80 blurredText: { 81 position: 'absolute', 82 padding: 10, 83 backgroundColor: 'rgb(120,20,20)', 84 color: 'white', 85 fontWeight: 'bold', 86 fontSize: 20, 87 borderRadius: 5, 88 }, 89 blurView: { 90 ...StyleSheet.absoluteFillObject, 91 alignItems: 'center', 92 paddingTop: 20, 93 }, 94 nonBlurredText: { 95 paddingHorizontal: 10, 96 paddingVertical: 4, 97 backgroundColor: 'rgb(120,20,20)', 98 color: 'white', 99 fontWeight: 'bold', 100 fontSize: 18, 101 }, 102 slider: { 103 position: 'absolute', 104 bottom: 10, 105 }, 106}); 107