function HomePageIntro({ onComplete }) { const [animations, setAnimations] = useState<Animated.ValueXY[]>([]); const [opacityAnimations, setOpacityAnimations] = useState<Animated.Value[]>([]); const [fadeInScale, setFadeInScale] = useState(new Animated.Value(0)); const { width, height } = Dimensions.get('window'); const centerX = width / 2 - 200; const centerY = height / 2 - 420; const images = Array.from({ length: 6 }).flatMap(() => [ 'https://i.ibb.co/GVMYqR7/1.png', 'https://i.ibb.co/1njfvWp/2.png', 'https://i.ibb.co/YdpVhrf/3.png', 'https://i.ibb.co/f4f2Cb8/4.png', 'https://i.ibb.co/Yt7SCwr/5.png', 'https://i.ibb.co/BVZzDwJ/6.png', 'https://i.ibb.co/WgsPnh9/7.png', 'https://i.ibb.co/YWhRb3b/8.png', 'https://i.ibb.co/g6XRPqw/9.png', 'https://i.ibb.co/PF7Dqw0/10.png', ]); const clockPositions = Array.from({ length: 60 }, (_, i) => { const angle = (i * (360 / 60)) * (Math.PI / 180); const x = centerX + Math.cos(angle) * 400; const y = centerY + Math.sin(angle) * 600; return { x, y }; }); useEffect(() => { const shuffledPositions = clockPositions.sort(() => Math.random() - 0.5); const initialAnimations = images.map((_, index) => { const position = shuffledPositions[index % shuffledPositions.length]; return new Animated.ValueXY(position); }); const opacityValues = images.map(() => new Animated.Value(1)); setAnimations(initialAnimations); setOpacityAnimations(opacityValues); animateImagesSequentially(initialAnimations, opacityValues); Animated.timing(fadeInScale, { toValue: 1, duration: 2000, useNativeDriver: true, }).start(() => { Animated.parallel([ Animated.timing(fadeInScale, { toValue: 10, duration: 1000, useNativeDriver: true, }), Animated.timing(fadeInScale, { toValue: 0, duration: 1000, useNativeDriver: true, }), ]).start(onComplete); }); }, []); const animateImagesSequentially = async (animationValues, opacityValues) => { const animationDuration = 850; const overlapDuration = 12; const promises = animationValues.map((anim, i) => { const startDelay = i * overlapDuration; return new Promise<void>((resolve) => { setTimeout(() => { Animated.parallel([ Animated.timing(anim, { toValue: { x: centerX, y: centerY }, duration: animationDuration, useNativeDriver: true, }), Animated.timing(opacityValues[i], { toValue: 0, duration: animationDuration, useNativeDriver: true, }), ]).start(() => resolve()); }, startDelay); }); }); await Promise.all(promises); }; return ( <View style={styles.container}> {images.map((image, index) => ( <Animated.Image key={index} source={{ uri: image }} style={[ styles.image, { transform: animations[index] ? animations[index].getTranslateTransform() : [], opacity: opacityAnimations[index] || 1, }, ]} /> ))} <Animated.Image source={{ uri: 'https://i.postimg.cc/gkwzvMYP/1-copy.png' }} style={[ styles.centerImage, { transform: [{ scale: fadeInScale }], }, ]} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#BFDEF8', justifyContent: 'center', alignItems: 'center', }, image: { position: 'absolute', width: 200, height: 200, resizeMode: 'contain', }, centerImage: { position: 'absolute', width: 350, height: 350, resizeMode: 'contain', }, });
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter