|
@@ -1,4 +1,4 @@
|
|
|
-import React, { useEffect, useState, useMemo } from 'react';
|
|
|
|
|
|
|
+import React, { useEffect, useLayoutEffect, useState, useMemo, useRef, useCallback } from 'react';
|
|
|
import history from '@/utils/history';// 如果用 react-router 跳转
|
|
import history from '@/utils/history';// 如果用 react-router 跳转
|
|
|
import styles from './index.module.scss';
|
|
import styles from './index.module.scss';
|
|
|
import A0_home_1 from '@/assets/img/A0_home_1.jpg';
|
|
import A0_home_1 from '@/assets/img/A0_home_1.jpg';
|
|
@@ -6,15 +6,79 @@ import A0_home_2 from '@/assets/img/A0_home_2.jpg';
|
|
|
import A0_home_3 from '@/assets/img/A0_home_3.jpg';
|
|
import A0_home_3 from '@/assets/img/A0_home_3.jpg';
|
|
|
import homeLogo from '@/assets/img/A0_home_logo.png'; // 推荐直接 import 图片
|
|
import homeLogo from '@/assets/img/A0_home_logo.png'; // 推荐直接 import 图片
|
|
|
|
|
|
|
|
|
|
+/** 以「页面上真实 img」为准:load + decode + 双 rAF,避免与独立 new Image() 不同步 */
|
|
|
|
|
+function useDomImageReady(
|
|
|
|
|
+ ref: React.RefObject<HTMLImageElement | null>,
|
|
|
|
|
+ onReady: () => void,
|
|
|
|
|
+) {
|
|
|
|
|
+ const onReadyRef = useRef(onReady);
|
|
|
|
|
+ onReadyRef.current = onReady;
|
|
|
|
|
+ const firedRef = useRef(false);
|
|
|
|
|
+
|
|
|
|
|
+ useLayoutEffect(() => {
|
|
|
|
|
+ const el = ref.current;
|
|
|
|
|
+ if (!el) return;
|
|
|
|
|
+
|
|
|
|
|
+ const fire = () => {
|
|
|
|
|
+ if (firedRef.current) return;
|
|
|
|
|
+ firedRef.current = true;
|
|
|
|
|
+ void (async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (typeof el.decode === 'function') await el.decode();
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ /* ignore */
|
|
|
|
|
+ }
|
|
|
|
|
+ requestAnimationFrame(() => {
|
|
|
|
|
+ requestAnimationFrame(() => {
|
|
|
|
|
+ onReadyRef.current();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ })();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ if (el.complete && el.naturalWidth > 0) {
|
|
|
|
|
+ fire();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ el.addEventListener('load', fire, { once: true });
|
|
|
|
|
+ el.addEventListener('error', fire, { once: true });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ el.removeEventListener('load', fire);
|
|
|
|
|
+ el.removeEventListener('error', fire);
|
|
|
|
|
+ };
|
|
|
|
|
+ }, [ref]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function A0base() {
|
|
function A0base() {
|
|
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
|
const [progress, setProgress] = useState(0); // 进度 0 ~ 100
|
|
const [progress, setProgress] = useState(0); // 进度 0 ~ 100
|
|
|
|
|
+ const [assetsReady, setAssetsReady] = useState(false);
|
|
|
const images = useMemo(() => [A0_home_1, A0_home_2, A0_home_3], []);
|
|
const images = useMemo(() => [A0_home_1, A0_home_2, A0_home_3], []);
|
|
|
|
|
|
|
|
|
|
+ const slide0Ref = useRef<HTMLImageElement>(null);
|
|
|
|
|
+ const slide1Ref = useRef<HTMLImageElement>(null);
|
|
|
|
|
+ const slide2Ref = useRef<HTMLImageElement>(null);
|
|
|
|
|
+ const logoRef = useRef<HTMLImageElement>(null);
|
|
|
|
|
+ const pendingRef = useRef(4);
|
|
|
|
|
+
|
|
|
|
|
+ const markOneReady = useCallback(() => {
|
|
|
|
|
+ if (pendingRef.current <= 0) return;
|
|
|
|
|
+ pendingRef.current -= 1;
|
|
|
|
|
+ if (pendingRef.current <= 0) setAssetsReady(true);
|
|
|
|
|
+ }, []);
|
|
|
|
|
+
|
|
|
|
|
+ useDomImageReady(slide0Ref, markOneReady);
|
|
|
|
|
+ useDomImageReady(slide1Ref, markOneReady);
|
|
|
|
|
+ useDomImageReady(slide2Ref, markOneReady);
|
|
|
|
|
+ useDomImageReady(logoRef, markOneReady);
|
|
|
|
|
+
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
|
|
+ if (!assetsReady) return;
|
|
|
|
|
+
|
|
|
const interval = setInterval(() => {
|
|
const interval = setInterval(() => {
|
|
|
setProgress(prev => {
|
|
setProgress(prev => {
|
|
|
- const next = prev + 1;
|
|
|
|
|
|
|
+ const next = prev + 1;
|
|
|
if (next >= 100) {
|
|
if (next >= 100) {
|
|
|
clearInterval(interval);
|
|
clearInterval(interval);
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
@@ -27,7 +91,7 @@ function A0base() {
|
|
|
}, 50); // 每 50ms 增加 1%
|
|
}, 50); // 每 50ms 增加 1%
|
|
|
|
|
|
|
|
return () => clearInterval(interval);
|
|
return () => clearInterval(interval);
|
|
|
- }, []);
|
|
|
|
|
|
|
+ }, [assetsReady]);
|
|
|
|
|
|
|
|
// 根据进度切换图片
|
|
// 根据进度切换图片
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
@@ -45,6 +109,7 @@ function A0base() {
|
|
|
{images.map((src, index) => (
|
|
{images.map((src, index) => (
|
|
|
<img
|
|
<img
|
|
|
key={src}
|
|
key={src}
|
|
|
|
|
+ ref={index === 0 ? slide0Ref : index === 1 ? slide1Ref : slide2Ref}
|
|
|
src={src}
|
|
src={src}
|
|
|
alt={`slide ${index + 1}`}
|
|
alt={`slide ${index + 1}`}
|
|
|
className={`${styles.slide} ${index === currentIndex ? styles.active : ''}`}
|
|
className={`${styles.slide} ${index === currentIndex ? styles.active : ''}`}
|
|
@@ -52,7 +117,7 @@ function A0base() {
|
|
|
))}
|
|
))}
|
|
|
|
|
|
|
|
<div className={styles.homeLogo}>
|
|
<div className={styles.homeLogo}>
|
|
|
- <img src={homeLogo} alt="homeLogo" />
|
|
|
|
|
|
|
+ <img ref={logoRef} src={homeLogo} alt="homeLogo" />
|
|
|
<div className={'process'}>
|
|
<div className={'process'}>
|
|
|
{progress}%
|
|
{progress}%
|
|
|
</div>
|
|
</div>
|