import React, { useState, useCallback, useRef, useEffect } from 'react'; import Map2D from './components/Map2D'; import Globe3D from './components/Globe3D'; import Controls from './components/Controls'; import AiTutor from './components/AiTutor'; import { MapSettings, ProjectionType, LatLng } from './types'; import { PROJECTION_CONFIGS } from './constants'; const App: React.FC = () => { const [settings, setSettings] = useState({ projection: ProjectionType.MERCATOR, rotate: [0, 0, 0], scale: 150, showGraticule: true, showTissot: false, showCountries: true, showCountryNames: false, showProjectionSurface: false, showLightSource: false, showTangent: false }); const [hoverPos, setHoverPos] = useState(null); const [isSidebarOpen, setIsSidebarOpen] = useState(true); // Professor AI 高度控制 const [tutorHeight, setTutorHeight] = useState(380); const [isResizing, setIsResizing] = useState(false); const sidebarRef = useRef(null); const startResizing = useCallback((e: React.MouseEvent) => { setIsResizing(true); e.preventDefault(); }, []); const stopResizing = useCallback(() => { setIsResizing(false); }, []); const resize = useCallback((e: MouseEvent) => { if (isResizing && sidebarRef.current) { const sidebarRect = sidebarRef.current.getBoundingClientRect(); const newHeight = sidebarRect.bottom - e.clientY; // 限制高度範圍 if (newHeight > 150 && newHeight < sidebarRect.height * 0.7) { setTutorHeight(newHeight); } } }, [isResizing]); useEffect(() => { window.addEventListener('mousemove', resize); window.addEventListener('mouseup', stopResizing); return () => { window.removeEventListener('mousemove', resize); window.removeEventListener('mouseup', stopResizing); }; }, [resize, stopResizing]); return (
{/* Sidebar */}
{/* Sidebar Header - Fixed */}
教學儀表板
{/* Top Section: Scrollable Controls */}
{/* Resize Handle */}
{/* Bottom Section: Resizable AiTutor */}
{/* Footer - Fixed */}
Projection Pro v1.6 Professor AI Ready
{/* Main Content */}
{!isSidebarOpen && ( )}

地理投影模擬器 實時連動教學版

); }; export default App;