THREE项目搭建
简介
three.js 是一个 是基于WebGL 封装的一个易于使用且轻量级的 3D 库,ThreeJS 对 WebGL 提供的接口进行了非常好的封装,简化了很多细节,大大降低了学习成本,同时也极大地提高了性能。用户不需要详细地学习 WebGL,就能轻松创作出三维图形,是前端开发者研发 3D WEB 应用的主要工具
学习文档推荐
- WebGl中文档:可以了解到three.js最基础的知识点,可以对相机,场景,控制器有初步的认识与了解
- 3D查看器:查看3D模型的在线网站
搭建
1.下载three.js
npm install --save three
npm install three-obj-mtl-loader
:mtl模型加载
npm install three-orbit-controls
:控制器
npm install three-stats
:性能检测器
2.新建3DWorkShop.vue文件
用于3D车间最外层文件
3.创建utils/three/tool.js
将所有模型文件类型的获取方法写在一个js文件中
import { MTLLoader } from 'three-obj-mtl-loader'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
// 加载obj,mtl文件
export function objloader(path) {
return new Promise(resolve => {
var mtlLoader = new MTLLoader()
// 初始化obj
var objLoader = new OBJLoader()
// 加载mtl文件
mtlLoader.load(`three/${path}.mtl`, (mtl) => {
// 初始化
mtl.preload()
// 加载贴图
objLoader.setMaterials(mtl)
objLoader.load(`three/${path}.obj`, (obj) => {
resolve({
mtl,
obj
})
})
})
})
}
// 加载fbx文件
export function fbxloader(path) {
return new Promise(resolve => {
var loader = new FBXLoader()
loader.load(`three/${path}.fbx`, (fbx) => {
resolve(fbx)
}, function (xhr) {
// 控制台查看加载进度xhr
// 通过加载进度xhr可以控制前端进度条进度 Math.floor:小数加载进度取整
console.log('加载进度' + Math.floor(xhr.loaded / xhr.total * 100) + '%');
})
})
}
// 加载gtlf文件
export function gltfloader(path) {
return new Promise(resolve => {
var loader = new GLTFLoader()
loader.load(`three/${path}.gltf`, (gltf) => {
resolve(gltf)
})
})
}
4.创建components/three/draw.vue[重点]
创建html
<div class="draw" ref="draw">
<div id="webgl" v-if="isShowWebgl"></div>
</div>
注意点:要将three相关的参数定义到vue之外,不可以放到vue的data里
(会导致卡顿问题)
具体原因是:three的相关参数会经常变动,而vue又会对data里面的变量进行变化追踪,所以就会卡
例如:
4.1 引入文件
import * as THREE from "three"; // 三维
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; // 控制器
4.2 初始化场景
initScene(){
scene = new THREE.Scene(); // 场景对象Scene
}
4.3 初始化渲染器
initRenderer(){
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
// 设置渲染区域尺寸
renderer.setSize(this.$refs.draw.offsetWidth, this.$refs.draw.offsetHeight);
// 开启渲染阴影
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.hadowMapEnabled = true;
// body元素中插入canvas对象
this.$refs.draw.appendChild(renderer.domElement);
}
4.4 初始化光源
// 初始化光源
initLight() {
//增加环境光(环境光颜色,环境光强度)
const ambientLight = new THREE.AmbientLight(0xffffff, 2);
ambientLight.name = "ambientLight";
scene.add(ambientLight);
//增加太阳光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.name = "directionalLight";
directionalLight.position.set(8000, 8000, -2000);
},
4.5 初始化相机(人眼模式)
sightline = {
scale: 45, // 视线比例
type: "PerspectiveCamera", // 相机的类型
posiy: [-5000, 7000, 16000], // 相机位置
};
// 初始化相机
initCamera() {
const k = this.$refs.draw.offsetWidth / this.$refs.draw.offsetHeight; // 窗口宽高比
camera = new THREE.PerspectiveCamera(this.sightline.scale, k, 1, 100000);
camera.position.set(this.sightline.posiy[0], this.sightline.posiy[1], this.sightline.posiy[2]);
camera.up.set(0, 1000, 0);
camera.lookAt(0, 0, 1);
},
4.6 初始化控制器
// 初始化控制
initOrbitControls() {
controls = new OrbitControls(camera, renderer.domElement); // 创建控件对象
controls.target.set(0, 0.5, 0); //控制器轴的方向,Y轴向上
controls.update(); //控制器更新
},
4.7 初始化动画
// 设置动画
animate() {
if (!renderer) {
return;
}
if (this.count < 2) {
this.count++;
renderer.render(scene, camera);
controls.update();
}
if (animateId) cancelAnimationFrame(animateId);
animateId = requestAnimationFrame(this.animate);
},
4.8 添加全局方法
// 添加全局方法
addmeth() {
// 监听窗口尺寸变化
window.addEventListener("resize", this.changeSize, false);
},
// 监听尺寸变化
changeSize() {
// 重置渲染器输出画布canvas尺寸
renderer.setSize(this.$refs.draw.offsetWidth, this.$refs.draw.offsetHeight);
const k = this.$refs.draw.offsetWidth / this.$refs.draw.offsetHeight; // 窗口宽高比
// 重置相机投影的相关参数
camera.aspect = k;
// 需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
camera.updateProjectionMatrix();
},
4.9 加载模型
<draw ref="draw" :initLoader="initLoader" :eqpList="eqpList" />
在3DWorkShop的methods里:
import { fbxloader } from "@/utils/three/tool";
// 引入模型文件
initLoader() {
//sip 是文件名[文件必须存放到public里,我放的位置是public/three/sip.fbx]
fbxloader(sip).then(obj=>{
this.$refs.draw.addScene(fbx);
})
},
4.10 执行方法
mounted(){
this.init();//初始化渲染
this.animate();//添加动画
this.addmeth();//添加事件
},
init(){
//初始化场景
this.initScene();
// 初始化渲染对象
this.initRenderer();
// 初始化模型
this.initLoader();
// 初始化光源
this.initLight();
// 初始化相机
this.initCamera();
// 初始化控制
this.initOrbitControls();
}