freshyo/apps/fallback-ui/src/components/3d/Flag.tsx
2026-02-01 13:56:03 +05:30

75 lines
2.2 KiB
TypeScript

import { useRef, useMemo } from 'react';
import { useFrame } from '@react-three/fiber';
import { TextureLoader, DoubleSide, Mesh } from 'three';
export default function Flag({ isCelebrating }: { isCelebrating: boolean }) {
const flagRef = useRef<Mesh>(null);
const poleRef = useRef<Mesh>(null);
// Create flag texture with text
const texture = useMemo(() => {
const canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 256;
const ctx = canvas.getContext('2d')!;
// Gradient background - Brand blue colors
const gradient = ctx.createLinearGradient(0, 0, 512, 0);
gradient.addColorStop(0, '#2E90FA');
gradient.addColorStop(1, '#84CAFF');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 512, 256);
// Add text
ctx.fillStyle = '#FFFFFF';
ctx.font = 'bold 40px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Freshyo for', 256, 100);
ctx.fillText('mahabubnagar', 256, 160);
// Add decorative border
ctx.strokeStyle = '#FFFFFF';
ctx.lineWidth = 4;
ctx.strokeRect(10, 10, 492, 236);
const texture = new TextureLoader().load(canvas.toDataURL());
return texture;
}, []);
useFrame((state) => {
if (flagRef.current) {
const time = state.clock.getElapsedTime();
// Wave animation
const waveIntensity = isCelebrating ? 0.3 : 0.1;
flagRef.current.rotation.y = Math.sin(time * 3) * waveIntensity;
flagRef.current.rotation.z = Math.sin(time * 2) * 0.05;
}
});
return (
<group position={[-1.5, 2.5, 0]}>
{/* Flag Pole */}
<mesh ref={poleRef} position={[0, 0, 0]}>
<cylinderGeometry args={[0.05, 0.05, 3, 16]} />
<meshStandardMaterial color="#8B4513" />
</mesh>
{/* Flag */}
<mesh ref={flagRef} position={[1.5, 1, 0]}>
<planeGeometry args={[3, 1.5, 10, 10]} />
<meshStandardMaterial
map={texture}
side={DoubleSide}
transparent
/>
</mesh>
{/* Pole Top */}
<mesh position={[0, 1.6, 0]}>
<sphereGeometry args={[0.1, 16, 16]} />
<meshStandardMaterial color="#53B1FD" emissive="#1570EF" emissiveIntensity={0.5} />
</mesh>
</group>
);
}