diff --git a/src/App.tsx b/src/App.tsx index f2ba570..b328b46 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,6 +18,7 @@ import { useChessEngine } from './hooks/useChessEngine'; import { useDepth } from './hooks/useDepth'; import { DepthControl } from './components/DepthControl'; import { WelcomeModal } from './components/WelcomeModal'; +import { Spinner } from './components/Spinner'; export function App() { const [overlayImageSrc, setOverlayImageSrc] = useState(''); @@ -35,7 +36,7 @@ export function App() { height: number; }>(); - const { templates } = useOpenCV(); + const { templates, isLoading: isOpenCVLoading } = useOpenCV(); const { bestMove, loading, error, fetchBestMove, setBestMove } = useChessEngine(); const { depth, setDepth } = useDepth(); @@ -145,6 +146,15 @@ export function App() { processImage(img); }; + if (isOpenCVLoading) { + return ( +
+ +

正在加载必要组件,请稍候...

+
+ ); + } + return ( <>
diff --git a/src/app.css b/src/app.css index a66e99c..df48629 100644 --- a/src/app.css +++ b/src/app.css @@ -506,4 +506,44 @@ dialog button:hover { padding: 8px 16px; font-size: 0.9rem; } +} + +/* 在文件末尾添加以下样式 */ + +.loading-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(255, 255, 255, 0.8); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + z-index: 9999; +} + +.loading-overlay p { + margin-top: 20px; + font-size: 1.2rem; + color: #333; +} + +.spinner { + border: 4px solid rgba(0, 0, 0, 0.1); + width: 36px; + height: 36px; + border-radius: 50%; + border-left-color: #09f; + animation: spin 1s ease infinite; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } } \ No newline at end of file diff --git a/src/components/Spinner.tsx b/src/components/Spinner.tsx new file mode 100644 index 0000000..cfbead2 --- /dev/null +++ b/src/components/Spinner.tsx @@ -0,0 +1,5 @@ +import { h } from 'preact'; + +export const Spinner = () => ( +
+); \ No newline at end of file diff --git a/src/hooks/useOpenCV.ts b/src/hooks/useOpenCV.ts index dadff93..e6cd975 100644 --- a/src/hooks/useOpenCV.ts +++ b/src/hooks/useOpenCV.ts @@ -5,6 +5,7 @@ import { preprocessAllTemplates } from '../chessboard/templateMatching'; export function useOpenCV() { const [templates, setTemplates] = useState | null>(null); + const [isLoading, setIsLoading] = useState(true); // Add isLoading state useEffect(() => { const initialize = async () => { @@ -21,11 +22,13 @@ export function useOpenCV() { setTemplates(loadedTemplates); } catch (error) { console.error('Error loading templates:', error); + } finally { + setIsLoading(false); // Set isLoading to false after initialization } }; initialize(); }, []); - return { templates }; + return { templates, isLoading }; // Return isLoading } \ No newline at end of file