我把gltf文件放在了public/static下面了。其他地方还没适用。因为之前想导入obj一直没成功,就跟着官网和各种例子成功导入了gltf格式的
然后其他的没啥。看代码吧。大部分我都写了备注
components组件
import React, { useEffect, useRef } from "react";
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
function ThreeContainer({ style }) {
const defaultStyle = {
height: "50vh",
width: "50vw",
backgroundColor: "transparent",
margin: "0 auto",
};
const isContainerRunning = useRef(false);
const containerRef = useRef(null);
useEffect(() => {
console.log(isContainerRunning, "====>", containerRef);
if (!isContainerRunning.current && containerRef.current) {
isContainerRunning.current = true;
const containerWidth = containerRef.current.offsetWidth;
const containerHeight = containerRef.current.offsetHeight;
const loader = new GLTFLoader();
//创建场景
const scene = new THREE.Scene();
//创建相机
const camera = new THREE.PerspectiveCamera(
75, // 视野角度,视野角值越大,场景中的物体越小
containerWidth / containerHeight, //宽高比
0.1, // 近裁剪面
1000 // 远裁剪面
);
camera.position.set(-280, 290, -10);
// 生成渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true, // 抗锯齿
alpha: true, //用于设置透明度
});
renderer.setSize(containerWidth * 0.9995, containerHeight * 0.9995);
containerRef.current.appendChild(renderer.domElement);
renderer.outputColorSpace = THREE.SRGBColorSpace; //设置为SRGB颜色空间
// 设置背景颜色,透明("rgb()", 0)
renderer.setClearColor(0x000000, 0);
//添加光源
const ambientLight = new THREE.AmbientLight("#FF9D6E", 20); // 环境光
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight("#fff", 5); // 方向光颜色和强度
directionalLight.position.set(1, 1, 1); // 光源位置
scene.add(directionalLight);
//创建控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 允许阻尼效果,使动画更平滑
controls.dampingFactor = 0.05; // 阻尼系数
controls.rotateSpeed = 0.1; // 旋转速度
// 加载模型
loadModel(loader, scene);
// 渲染场景
// animate(isContainerRunning, camera, renderer, scene);
function animate(runningFlag, camera, renderer, scene) {
// console.log(runningFlag, "ruim==>");
if (!runningFlag.current) {
controls.autoRotate = true; //是否自动旋转
//旋转
// const radius = 140;
// const angle = Date.now() * 0.0005;
// const x = Math.cos(angle) * radius;
// const z = Math.sin(angle) * radius;
// camera.position.set(x, 200, z);
// camera.lookAt(0, 50, 0);
// console.log('controls.target====', controls.target);
}
controls.target.set(0, 50, 0); //与lookAt参数保持一致
requestAnimationFrame(() =>
animate(runningFlag, camera, renderer, scene)
);
controls.update(); //更新控制器状态update()函数内会执行camera.lookAt(controls.target)
renderer.render(scene, camera);
}
function loadModel(loader, scene) {
loader.load(
"static/test-glt.gltf",
function (gltf) {
isContainerRunning.current = false;
gltf.scene.traverse(function (child) {
console.log(child, "child=====>", camera);
if (child.isMesh) {
child.frustumCulled = false;
//模型阴影
child.castShadow = false;
//模型自发光(模型自己的颜色)
// child.material.emissive = child.material.color;
// child.material.emissiveMap = child.material.map;
}
});
scene.add(gltf.scene);
animate(isContainerRunning, camera, renderer, scene);
// 添加点击事件监听器
// containerRef.current.addEventListener("mousedown", onm ouseDown, false)
// 滚轮事件
containerRef.current.addEventListener(
"mousewheel",
mousewheel,
false
);
function mousewheel(e) {
// var animationId = ''
// cancelAnimationFrame(animationId);
e.preventDefault();
if (e.deltaY < 0) {
// 当滚轮向上滚动时
camera.position.z -= 1; // 向前移动相机
} else {
// 当滚轮向下滚动时
camera.position.z += 1; // 向后移动相机
}
console.log(e.deltaY, "====>", camera, scene);
renderer.render(scene, camera);
}
// 窗口大小改变事件
window.addEventListener("resize", (e) => {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
});
},
// called while loading is progressing
function (xhr) {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
// called when loading has errors
function (error) {
console.log("An error happened");
}
);
}
}
}, []);
return (
<div>
<div
ref={containerRef}
id="container"
style={{ ...defaultStyle, ...style }}
/>
{/* <div onClick={() => { isContainerRunning.current = true }}>
开始旋转
</div>
<div onClick={() => { isContainerRunning.current = false }}>
停止旋转
</div> */}
</div>
);
}
export default ThreeContainer;
view/indexGltf/index.js
// import "./App.css";
import ThreeContainer from "../../components/ThreeContainer.jsx";
function IndexGltf() {
return (
<div>
<ThreeContainer />
</div>
);
}
export default IndexGltf;
App.js文件
import './App.css';
import IndexGltf from './view/indexGltf/index.js';
function App() {
return (
<div className="App">
<IndexGltf />
</div>
);
}
export default App;
然后就是文件夹的一个截图吧