'use client'; import React, { useState, useEffect, useMemo, useRef } from 'react'; // --- Constants & Config --- const VIEW_WIDTH = 800; const VIEW_HEIGHT = 600; const UNIT = 40; // Pixel size of one grid unit const A_VAL = 5; // Units for a const B_VAL = 3; // Units for b const COLORS = { bg: '#0f172a', // Slate 900 grid: '#1e293b', // Slate 800 gridLine: '#334155', // Slate 700 a: '#06b6d4', // Cyan 500 (a component) b: '#d946ef', // Fuchsia 500 (b component) ab: '#8b5cf6', // Violet 500 (ab component) textMain: '#e2e8f0', // Slate 200 textSub: '#94a3b8', // Slate 400 accent: '#f59e0b', // Amber 500 success: '#10b981', // Emerald 500 }; // Center the geometry const TOTAL_SIZE = (A_VAL + B_VAL) * UNIT; const ORIGIN_X = (VIEW_WIDTH - TOTAL_SIZE) / 2; const ORIGIN_Y = (VIEW_HEIGHT - TOTAL_SIZE) / 2; // --- Helper Types --- interface Particle { id: number; x: number; y: number; vx: number; vy: number; life: number; } export const PerfectSquareFormulaTech = () => { // Phase Control // 0: Init / System Scan // 1: Draw Outer Frame (Length a + b) // 2: Partition / Cut (Grid lines) // 3: Materialize Regions (Fill colors) // 4: Labeling (Dimensions) // 5: Explosion / Separation (Visualizing components) // 6: Equation Derivation (Text sync) // 7: Merge & Complete const [phase, setPhase] = useState(0); const [resetKey, setResetKey] = useState(0); // Animation Loop Ref for Particles (Visual Flair) const requestRef = useRef(); const [particles, setParticles] = useState([]); // Calculate Geometry Regions // Region 1: a^2 (Top-Left) // Region 2: ab (Top-Right) // Region 3: ab (Bottom-Left) // Region 4: b^2 (Bottom-Right) const regions = useMemo(() => { return { a2: { x: 0, y: 0, w: A_VAL * UNIT, h: A_VAL * UNIT, color: COLORS.a, label: 'a²' }, ab1: { x: A_VAL * UNIT, y: 0, w: B_VAL * UNIT, h: A_VAL * UNIT, color: COLORS.ab, label: 'ab' }, ab2: { x: 0, y: A_VAL * UNIT, w: A_VAL * UNIT, h: B_VAL * UNIT, color: COLORS.ab, label: 'ab' }, b2: { x: A_VAL * UNIT, y: A_VAL * UNIT, w: B_VAL * UNIT, h: B_VAL * UNIT, color: COLORS.b, label: 'b²' }, }; }, []); // Main Sequence Controller useEffect(() => { let timer: NodeJS.Timeout; const runSequence = async () => { setPhase(0); await wait(1000); // Scan setPhase(1); // Frame await wait(1500); setPhase(2); // Grid await wait(1000); setPhase(3); // Fill await wait(1500); setPhase(4); // Labels await wait(2000); setPhase(5); // Explode await wait(3000); setPhase(6); // Equation await wait(4000); setPhase(7); // Merge await wait(3000); setResetKey(k => k + 1); // Loop }; runSequence(); return () => clearTimeout(timer); }, [resetKey]); const wait = (ms: number) => new Promise(r => setTimeout(r, ms)); // Particle System for "Data Flow" effect useEffect(() => { const animate = () => { // Very simple particle update logic to avoid heavy state churn // In a real app, might use a canvas overlay, but here we keep SVG strict // We'll just oscillate a time variable for shader-like effects via CSS variables // instead of full particle physics to maintain 60fps React performance. requestRef.current = requestAnimationFrame(animate); }; requestRef.current = requestAnimationFrame(animate); return () => cancelAnimationFrame(requestRef.current!); }, []); // Calculate Explosion Offsets (Gap between blocks in Phase 5) const gap = phase === 5 || phase === 6 ? 20 : 0; // Dynamic Opacities const gridOpacity = phase >= 2 ? 0.3 : 0; const fillOpacity = phase >= 3 ? 0.8 : 0; return (
{/* Main SVG Canvas */} {/* --- Background Elements --- */} {/* Scanning Line (Cyberpunk feel) */} {/* --- Main Geometry Group --- */} {/* Phase 1: Outer Brackets showing (a + b) */} = 1 ? 1 : 0} style={{ transition: 'opacity 1s' }}> {/* Top Bracket */} (a + b) {/* Left Bracket */} (a + b) {/* Phase 2: Detailed Length Markers (a and b separation) */} = 2 ? 1 : 0} style={{ transition: 'opacity 1s' }}> {/* Top Markers */} a b {/* Left Markers */} a b {/* --- The Four Blocks --- */} {/* Using CSS transforms for the explosion effect */} {/* Block a² */} = 2 ? 2 : 0} style={{ transition: 'all 0.8s' }} /> {/* Internal Grid for a² */} = 3 ? 0.2 : 0} /> = 4 ? 1 : 0} style={{ transition: 'opacity 0.5s', filter: 'url(#neon-glow)' }} > a² {/* Block ab (Top Right) */} = 2 ? 2 : 0} style={{ transition: 'all 0.8s' }} /> = 4 ? 1 : 0} style={{ transition: 'opacity 0.5s' }} > ab {/* Block ab (Bottom Left) */} = 2 ? 2 : 0} style={{ transition: 'all 0.8s' }} /> = 4 ? 1 : 0} style={{ transition: 'opacity 0.5s' }} > ab {/* Block b² */} = 2 ? 2 : 0} style={{ transition: 'all 0.8s' }} /> = 3 ? 0.2 : 0} /> = 4 ? 1 : 0} style={{ transition: 'opacity 0.5s', filter: 'url(#neon-glow)' }} > b² {/* Area Summary Overlay (Appears during Explosion) */} {/* Connector lines to center */} {/* --- UI / HUD Layer --- */} {/* Header */} 完全平方公式 PERFECT SQUARE FORMULA {/* Phase Indicator */} STATUS: {phase === 0 ? "INIT" : phase < 5 ? "CONSTRUCT" : phase < 7 ? "ANALYSIS" : "COMPLETE"} {/* Formula Display (Bottom) */} {/* Background Panel */} {/* Left Side: (a+b)^2 */} = 1 ? 1 : 0}> (a + b)² {/* Equals Sign */} = 2 ? 1 : 0}> = {/* Right Side Components */} {/* a^2 */} = 4 ? 1 : 0} style={{ transition: 'opacity 0.5s' }}> a² {/* + 2ab */} = 4 ? 1 : 0} style={{ transition: 'opacity 0.5s 0.2s' }}> + 2ab {/* + b^2 */} = 4 ? 1 : 0} style={{ transition: 'opacity 0.5s 0.4s' }}> + b² {/* Scanning underline for equation */} = 6 ? 480 : 0} height="2" fill={COLORS.success}> {/* Helper Text for "Geometry Proof" */} = 5 ? 1 : 0} style={{ transition: 'opacity 1s' }}> Area (Total) = Sum of Parts
); };