lanxin 2 هفته پیش
والد
کامیت
758e22d910
4فایلهای تغییر یافته به همراه32 افزوده شده و 25 حذف شده
  1. BIN
      public/138.fbx
  2. 25 2
      src/App.jsx
  3. 7 22
      src/scene.jsx
  4. 0 1
      src/util.js

BIN
public/138.fbx


+ 25 - 2
src/App.jsx

@@ -27,6 +27,14 @@ export default function App() {
   const fetchState = useFetchLoader(src);
   const [isModelReady, setIsModelReady] = useState(false);
 
+  const fileType = useMemo(() => {
+    if (!src) return "gltf";
+    const lower = src.toLowerCase().split("?")[0];
+    if (lower.endsWith(".fbx")) return "fbx";
+    if (lower.endsWith(".usdz")) return "usdz";
+    return "gltf";
+  }, [src]);
+
   useEffect(() => {
     console.log("%c╔════════════════════════════════════════════", "color: #ff6b6b; font-weight: bold; font-size: 12px;");
     console.log("%c示例链接:http://localhost:5173/?src=https://houseoss.4dkankan.com/project/DEMO/usdz/static/yw2-196-high.glb&progressColor=yellow&min=0.1&max=20", "color: #ff6b6b; font-weight: bold; font-size: 12px;");
@@ -40,9 +48,24 @@ export default function App() {
   return (
     <div style={{ width: "100vw", height: "100vh" }}>
       <OverlayLoader fetchState={fetchState} isModelReady={isModelReady} color={progressColor} active={!!src} />
-      <Canvas dpr={[1, 2]} gl={{ antialias: true }} style={{ touchAction: "none" }}>
+      <Canvas
+        dpr={[1, 2]}
+        gl={{ antialias: true }}
+        style={{
+          touchAction: "none",
+          opacity: isModelReady ? 1 : 0,
+          transition: "opacity 1s ease-in-out", // 添加过渡效果
+        }}
+      >
         {fetchState.blobUrl ? (
-          <Scene blobUrl={fetchState.blobUrl} zoomMin={zoomMin} zoomMax={zoomMax} progressColor={progressColor} onModelReady={() => setIsModelReady(true)} />
+          <Scene
+            blobUrl={fetchState.blobUrl}
+            fileType={fileType}
+            zoomMin={zoomMin}
+            zoomMax={zoomMax}
+            progressColor={progressColor}
+            onModelReady={() => setIsModelReady(true)}
+          />
         ) : (
           !src && (
             <Html center style={{ width: "200px", color: "#222", fontSize: 14 }}>

+ 7 - 22
src/scene.jsx

@@ -110,7 +110,7 @@ export function OverlayLoader({ fetchState, isModelReady, color, active }) {
         left: 0,
         width: "100%",
         height: "100%",
-        background: "#ffffff",
+        // background: "#ffffff", // 移除白色背景
         display: "flex",
         alignItems: "center",
         justifyContent: "center",
@@ -138,8 +138,7 @@ export function OverlayLoader({ fetchState, isModelReady, color, active }) {
             transform: `scaleX(${progress / 100})`,
             transformOrigin: "left",
             height: "100%",
-            background: color || "#4C7F7A",
-            transition: "transform 0.2s linear",
+            background: color || "#4C7F7A"
           }}
         />
       </div>
@@ -235,9 +234,9 @@ function FitWatcher({ controlsRef, onFitReady, zoomMin }) {
   useFrame(() => {
     if (!controlsRef.current || isFitted.current) return;
 
-    // 强制等待至少 1000ms,确保 Bounds 有足够时间启动动画,且避免缓存加载时 Loader 闪现
+    // 强制等待至少 300ms,确保 Bounds 有足够时间启动动画,且避免缓存加载时 Loader 闪现
     // 这段时间内,Loader 会一直遮挡屏幕
-    if (Date.now() - startTime.current < 1000) return;
+    if (Date.now() - startTime.current < 300) return;
 
     const controls = controlsRef.current;
     const currentPos = camera.position;
@@ -539,14 +538,6 @@ function SceneContent({ url, zoomMin, zoomMax, fileType, onReady }) {
           const newPos = calculateZoomPos(f, true); // true = zoomIn
           if (newPos) {
             animateCamera(newPos, () => {
-              // 关键修改:缩放完成后,更新 initialState,这样后续复位就会回到这个新位置
-              if (initialState.current) {
-                initialState.current.position.copy(newPos);
-                // target 通常不变,但为了保险也同步一下当前 target
-                if (controlsRef.current) {
-                  initialState.current.target.copy(controlsRef.current.target);
-                }
-              }
               if (onDone) onDone();
             });
           } else if (onDone) {
@@ -575,13 +566,6 @@ function SceneContent({ url, zoomMin, zoomMax, fileType, onReady }) {
           const newPos = calculateZoomPos(f, false); // false = zoomOut
           if (newPos) {
             animateCamera(newPos, () => {
-              // 关键修改:更新 initialState
-              if (initialState.current) {
-                initialState.current.position.copy(newPos);
-                if (controlsRef.current) {
-                  initialState.current.target.copy(controlsRef.current.target);
-                }
-              }
               if (onDone) onDone();
             });
           } else if (onDone) {
@@ -643,12 +627,13 @@ function SceneContent({ url, zoomMin, zoomMax, fileType, onReady }) {
   );
 }
 
-export default function Scene({ blobUrl, zoomMin, zoomMax, onModelReady }) {
+export default function Scene({ blobUrl, zoomMin, zoomMax, onModelReady, fileType: externalFileType }) {
   // 推断文件类型,传递给 ModelLoader
   const fileType = useMemo(() => {
+    if (externalFileType) return externalFileType;
     if (!blobUrl) return null;
     return "gltf"; // 默认
-  }, [blobUrl]);
+  }, [blobUrl, externalFileType]);
 
   // 为了保持兼容,我们还是需要真实的 URL 来推断类型,或者修改 App 传 fileType
   // 这里暂时简化,假设都是 gltf,如果需要支持 fbx,App 需要传 fileType

+ 0 - 1
src/util.js

@@ -1 +0,0 @@
-export function name(params) {}