【发布时间】:2022-09-30 22:14:47
【问题描述】:
我正在将 Chakra-UI 与 next-js 一起使用
我只想加载一次模型。
我多次浏览所有代码,但我没有在代码中找到错误。所以任何人都可以帮助我找出代码中的错误。以及为什么会这样。
index.js 文件:
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 文件:
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 文件:
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;
当它运行时加载两个模型
标签: reactjs three.js next.js 3d-model