Next.js和Trix.js模型(GLTF模型)加载两次
我正在使用Next-js
使用脉轮 我只想一次加载模型。
我多次浏览所有代码,但没有在代码中找到错误。因此,任何人都可以帮助我找出代码中的错误。以及为什么会发生这种情况。
index.js file:
import { Container } from "@chakra-ui/react";
import dynamic from "next/dynamic";
import PavanLogo from "../components/PavanLogo";
import PavanLogoLoader from "../components/PavanLogoLoader";
const LazyPavanLogo = dynamic(() => import("../components/PavanLogo"), {
ssr: false,
loading: () => <PavanLogoLoader />,
});
export default function Home() {
return (
<>
<LazyPavanLogo />
</>
);
}
PavanLogo.js file:
import { useState, useEffect, useRef, useCallback } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { loadGLTFModel } from "../lib/model";
import { PavanSpinner, PavanContainer } from "./PavanLogoLoader";
function easeOutCirc(x) {
return Math.sqrt(1 - Math.pow(x - 1, 4));
}
const PavanLogo = () => {
const refContainer = useRef();
const [loading, setLoading] = useState(true);
const [renderer, setRenderer] = useState();
const [_camera, setCamera] = useState();
const [target] = useState(new THREE.Vector3(-0.5, 1.2, 0));
const [initialCameraPosition] = useState(
new THREE.Vector3(
20 * Math.sin(0.2 * Math.PI),
10,
20 * Math.cos(0.2 * Math.PI)
)
);
const [scene] = useState(new THREE.Scene());
const [_controls, setControls] = useState();
const handleWindowResize = useCallback(() => {
const { current: container } = refContainer;
if (container && renderer) {
const scW = container.clientWidth;
const scH = container.clientHeight;
renderer.setSize(scW, scH);
}
}, [renderer]);
/* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
const { current: container } = refContainer;
if (container && !renderer) {
const scW = container.clientWidth;
const scH = container.clientHeight;
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(scW, scH);
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild(renderer.domElement);
setRenderer(renderer);
// 640 -> 240
// 8 -> 6
const scale = scH * 0.005 + 4.8;
const camera = new THREE.OrthographicCamera(
-scale,
scale,
scale,
-scale,
0.01,
50000
);
camera.position.copy(initialCameraPosition);
camera.lookAt(target);
setCamera(camera);
const ambientLight = new THREE.AmbientLight(0xcccccc, 1);
scene.add(ambientLight);
const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.target = target;
setControls(controls);
loadGLTFModel(scene, "/Model/pavan.gltf", {
receiveShadow: false,
castShadow: false,
}).then(() => {
animate();
setLoading(false);
});
let req = null;
let frame = 0;
const animate = () => {
req = requestAnimationFrame(animate);
frame = frame <= 100 ? frame + 1 : frame;
if (frame <= 100) {
const p = initialCameraPosition;
const rotSpeed = -easeOutCirc(frame / 120) * Math.PI * 20;
camera.position.y = 10;
camera.position.x =
p.x * Math.cos(rotSpeed) + p.z * Math.sin(rotSpeed);
camera.position.z =
p.z * Math.cos(rotSpeed) - p.x * Math.sin(rotSpeed);
camera.lookAt(target);
} else {
controls.update();
}
renderer.render(scene, camera);
};
return () => {
console.log("unmount");
cancelAnimationFrame(req);
renderer.dispose();
};
}
}, []);
useEffect(() => {
window.addEventListener("resize", handleWindowResize, false);
return () => {
window.removeEventListener("resize", handleWindowResize, false);
};
}, [renderer, handleWindowResize]);
return (
<PavanContainer ref={refContainer}>
{loading && <PavanSpinner />}
</PavanContainer>
);
};
export default PavanLogo;
PavanLogoLoader.js file:
import { forwardRef } from "react";
import { Box, Spinner } from "@chakra-ui/react";
export const PavanSpinner = () => (
<Spinner
size="xl"
position="absolute"
left="50%"
top="50%"
ml="calc(0px - var(--spinner-size) / 2)"
mt="calc(0px - var(--spinner-size))"
/>
);
export const PavanContainer = forwardRef(({ children }, ref) => (
<Box
ref={ref}
className="pavan"
m="auto"
mt={["-20px", "-60px", "-120px"]}
mb={["-40px", "-140px", "-200px"]}
w={[280, 480, 640]}
h={[280, 480, 640]}
position="relative"
>
{children}
</Box>
));
const Loader = () => {
return (
<PavanContainer>
<PavanSpinner />
</PavanContainer>
);
};
export default Loader;
when it runs load two model
I am using Chakra-UI with next-js
I only want to load the model one time.
I go through all code many times but I did not find the error in the code. so anyone can help me to find out the error in the code. and why this happening.
index.js file:
import { Container } from "@chakra-ui/react";
import dynamic from "next/dynamic";
import PavanLogo from "../components/PavanLogo";
import PavanLogoLoader from "../components/PavanLogoLoader";
const LazyPavanLogo = dynamic(() => import("../components/PavanLogo"), {
ssr: false,
loading: () => <PavanLogoLoader />,
});
export default function Home() {
return (
<>
<LazyPavanLogo />
</>
);
}
PavanLogo.js file:
import { useState, useEffect, useRef, useCallback } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { loadGLTFModel } from "../lib/model";
import { PavanSpinner, PavanContainer } from "./PavanLogoLoader";
function easeOutCirc(x) {
return Math.sqrt(1 - Math.pow(x - 1, 4));
}
const PavanLogo = () => {
const refContainer = useRef();
const [loading, setLoading] = useState(true);
const [renderer, setRenderer] = useState();
const [_camera, setCamera] = useState();
const [target] = useState(new THREE.Vector3(-0.5, 1.2, 0));
const [initialCameraPosition] = useState(
new THREE.Vector3(
20 * Math.sin(0.2 * Math.PI),
10,
20 * Math.cos(0.2 * Math.PI)
)
);
const [scene] = useState(new THREE.Scene());
const [_controls, setControls] = useState();
const handleWindowResize = useCallback(() => {
const { current: container } = refContainer;
if (container && renderer) {
const scW = container.clientWidth;
const scH = container.clientHeight;
renderer.setSize(scW, scH);
}
}, [renderer]);
/* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
const { current: container } = refContainer;
if (container && !renderer) {
const scW = container.clientWidth;
const scH = container.clientHeight;
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(scW, scH);
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild(renderer.domElement);
setRenderer(renderer);
// 640 -> 240
// 8 -> 6
const scale = scH * 0.005 + 4.8;
const camera = new THREE.OrthographicCamera(
-scale,
scale,
scale,
-scale,
0.01,
50000
);
camera.position.copy(initialCameraPosition);
camera.lookAt(target);
setCamera(camera);
const ambientLight = new THREE.AmbientLight(0xcccccc, 1);
scene.add(ambientLight);
const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.target = target;
setControls(controls);
loadGLTFModel(scene, "/Model/pavan.gltf", {
receiveShadow: false,
castShadow: false,
}).then(() => {
animate();
setLoading(false);
});
let req = null;
let frame = 0;
const animate = () => {
req = requestAnimationFrame(animate);
frame = frame <= 100 ? frame + 1 : frame;
if (frame <= 100) {
const p = initialCameraPosition;
const rotSpeed = -easeOutCirc(frame / 120) * Math.PI * 20;
camera.position.y = 10;
camera.position.x =
p.x * Math.cos(rotSpeed) + p.z * Math.sin(rotSpeed);
camera.position.z =
p.z * Math.cos(rotSpeed) - p.x * Math.sin(rotSpeed);
camera.lookAt(target);
} else {
controls.update();
}
renderer.render(scene, camera);
};
return () => {
console.log("unmount");
cancelAnimationFrame(req);
renderer.dispose();
};
}
}, []);
useEffect(() => {
window.addEventListener("resize", handleWindowResize, false);
return () => {
window.removeEventListener("resize", handleWindowResize, false);
};
}, [renderer, handleWindowResize]);
return (
<PavanContainer ref={refContainer}>
{loading && <PavanSpinner />}
</PavanContainer>
);
};
export default PavanLogo;
PavanLogoLoader.js file:
import { forwardRef } from "react";
import { Box, Spinner } from "@chakra-ui/react";
export const PavanSpinner = () => (
<Spinner
size="xl"
position="absolute"
left="50%"
top="50%"
ml="calc(0px - var(--spinner-size) / 2)"
mt="calc(0px - var(--spinner-size))"
/>
);
export const PavanContainer = forwardRef(({ children }, ref) => (
<Box
ref={ref}
className="pavan"
m="auto"
mt={["-20px", "-60px", "-120px"]}
mb={["-40px", "-140px", "-200px"]}
w={[280, 480, 640]}
h={[280, 480, 640]}
position="relative"
>
{children}
</Box>
));
const Loader = () => {
return (
<PavanContainer>
<PavanSpinner />
</PavanContainer>
);
};
export default Loader;
when it runs load two model
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
React.StrictMode 使加载徽标的 useEffect 运行两次。解决方案是在 next.config.js 中禁用它。
React.StrictMode makes useEffect which loads the logo run twice. The solution is to disable it in next.config.js.