Files
prism/frontend/src/components/BackgroundDesign.tsx
albivkt 020682854d 1212
2025-08-06 06:04:23 +03:00

252 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import { View, StyleSheet, Dimensions } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import Animated, {
useSharedValue,
useAnimatedStyle,
withRepeat,
withTiming,
withSequence,
interpolate,
Easing,
} from 'react-native-reanimated';
const { width, height } = Dimensions.get('window');
interface BackgroundDesignProps {
variant?: 'default' | 'login' | 'chat';
children?: React.ReactNode;
}
export const BackgroundDesign: React.FC<BackgroundDesignProps> = ({
variant = 'default',
children
}) => {
const floatAnimation = useSharedValue(0);
const rotateAnimation = useSharedValue(0);
const pulseAnimation = useSharedValue(0);
React.useEffect(() => {
// Плавное движение вверх-вниз
floatAnimation.value = withRepeat(
withSequence(
withTiming(1, { duration: 4000, easing: Easing.inOut(Easing.ease) }),
withTiming(0, { duration: 4000, easing: Easing.inOut(Easing.ease) })
),
-1,
false
);
// Вращение элементов
rotateAnimation.value = withRepeat(
withTiming(360, { duration: 30000, easing: Easing.linear }),
-1,
false
);
// Пульсация
pulseAnimation.value = withRepeat(
withSequence(
withTiming(1, { duration: 2000, easing: Easing.inOut(Easing.ease) }),
withTiming(0, { duration: 2000, easing: Easing.inOut(Easing.ease) })
),
-1,
false
);
}, []);
const floatingStyle = useAnimatedStyle(() => {
const translateY = interpolate(floatAnimation.value, [0, 1], [0, -30]);
return {
transform: [{ translateY }],
};
});
const rotatingStyle = useAnimatedStyle(() => {
return {
transform: [{ rotate: `${rotateAnimation.value}deg` }],
};
});
const pulsingStyle = useAnimatedStyle(() => {
const scale = interpolate(pulseAnimation.value, [0, 1], [1, 1.1]);
const opacity = interpolate(pulseAnimation.value, [0, 1], [0.3, 0.6]);
return {
transform: [{ scale }],
opacity,
};
});
return (
<View style={styles.container}>
{/* Основной градиентный фон */}
<LinearGradient
colors={['#0a0a0a', '#1a1a1a', '#0f0f0f']}
style={StyleSheet.absoluteFillObject}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
/>
{/* Декоративные элементы */}
<View style={styles.decorativeElements}>
{/* Большой круг с градиентом слева вверху */}
<Animated.View style={[styles.circle1, pulsingStyle]}>
<LinearGradient
colors={['rgba(255,255,255,0.03)', 'rgba(255,255,255,0.01)']}
style={styles.circleGradient}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
/>
</Animated.View>
{/* Плавающий элемент справа */}
<Animated.View style={[styles.floatingElement1, floatingStyle]}>
<LinearGradient
colors={['rgba(255,255,255,0.05)', 'rgba(255,255,255,0.02)']}
style={styles.elementGradient}
/>
</Animated.View>
{/* Вращающийся квадрат */}
<Animated.View style={[styles.rotatingSquare, rotatingStyle]}>
<View style={styles.squareInner} />
</Animated.View>
{/* Сетка точек для login варианта */}
{variant === 'login' && (
<View style={styles.dotsGrid}>
{Array.from({ length: 10 }).map((_, i) =>
Array.from({ length: 15 }).map((_, j) => (
<View
key={`${i}-${j}`}
style={[
styles.dot,
{
left: i * (width / 9),
top: j * (height / 14),
opacity: 0.05 + Math.random() * 0.05,
}
]}
/>
))
)}
</View>
)}
{/* Градиентные блики */}
<View style={styles.glowContainer}>
<LinearGradient
colors={['rgba(255,255,255,0.1)', 'transparent']}
style={[styles.glow1]}
start={{ x: 0.5, y: 0 }}
end={{ x: 0.5, y: 1 }}
/>
<LinearGradient
colors={['rgba(255,255,255,0.08)', 'transparent']}
style={[styles.glow2]}
start={{ x: 0, y: 0.5 }}
end={{ x: 1, y: 0.5 }}
/>
</View>
</View>
{/* Контент поверх фона */}
<View style={styles.contentContainer}>
{children}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0a0a0a',
},
decorativeElements: {
...StyleSheet.absoluteFillObject,
overflow: 'hidden',
},
contentContainer: {
flex: 1,
zIndex: 1,
},
circle1: {
position: 'absolute',
top: -width * 0.2,
left: -width * 0.2,
width: width * 0.6,
height: width * 0.6,
borderRadius: width * 0.3,
overflow: 'hidden',
},
circleGradient: {
flex: 1,
},
floatingElement1: {
position: 'absolute',
top: height * 0.2,
right: width * 0.1,
width: 80,
height: 80,
borderRadius: 40,
backgroundColor: 'rgba(255,255,255,0.02)',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.05)',
overflow: 'hidden',
},
elementGradient: {
flex: 1,
},
rotatingSquare: {
position: 'absolute',
bottom: height * 0.15,
left: width * 0.15,
width: 60,
height: 60,
backgroundColor: 'transparent',
borderWidth: 2,
borderColor: 'rgba(255,255,255,0.1)',
transform: [{ rotate: '45deg' }],
},
squareInner: {
flex: 1,
margin: 10,
backgroundColor: 'transparent',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.05)',
},
dotsGrid: {
position: 'absolute',
top: 0,
left: 0,
width: width,
height: height,
},
dot: {
position: 'absolute',
width: 2,
height: 2,
borderRadius: 1,
backgroundColor: '#666666',
},
glowContainer: {
...StyleSheet.absoluteFillObject,
},
glow1: {
position: 'absolute',
top: height * 0.1,
right: -width * 0.2,
width: width * 0.8,
height: width * 0.8,
borderRadius: width * 0.4,
},
glow2: {
position: 'absolute',
bottom: -height * 0.1,
left: -width * 0.1,
width: width * 0.7,
height: width * 0.7,
borderRadius: width * 0.35,
},
});