GLB 3d文件在前端页面的展示
1. 选择方案
前端实现3D效果的选项有以下四点:
A. CSS 3D技术;
B. SVG;
C. WebGL技术;
D. Canvas或者图片模拟3D
其中最后一种是用其他技术或方法去模拟3D效果,前3种才是浏览器真正意义上支持的3D技术。而three.js直接支持前3种渲染方式。three.js是JavaScript编写的WebGL第三方库。提供了非常多的3D显示功能。使用此组件可以自己绘制3D图像或展示在线及本地的3D模型。
2. 引入
three.js可以使用模块化引入,也可以直接用script来引入。在本项目中使用npm引入。
注意事项:
A. 此组件在几年前由three.js更名为three.所以安装时的命令应为npm install three --save。
B. 引入后在应用中需要加载本地或在线的3d文件,需要用户能够在屏幕上交互,所以还需引入构建器。注意引入的路径,其中第一项为对应文件的构建器。
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
3. 引入后的必要配置
A. 基本配置
//指定区域
let container = document.getElementById('scene')
this.scene = new THREE.Scene()
//新建相机(参数意义:摄像机视锥体垂直视野角度, 摄像机视锥体长宽比,摄像机视锥体近端面, 摄像机视锥体远端面)
this.camera = new THREE.PerspectiveCamera(70, container.clientWidth / container.clientHeight, 0.01, 10)
this.camera.position.set(0,1,1)
// 添加灯光
this.ambientLight = new THREE.AmbientLight(0xffffff) // 环境光
this.scene.add(this.ambientLight)
// 加载模型
const loader = new GLTFLoader();
loader.load("../../static/3dtest.glb", (result) => {
console.log(result)
result.scene.position.set(0,0,0)
result.scene.scale.set(0.3,0.3,0.3)
result.scene.traverse( function ( child ) {
if ( child.isMesh ) {
// child.frustumCulled = false;
// //模型阴影
// child.castShadow = false;
// //模型自发光
child.material.emissive = child.material.color;
child.material.emissiveMap = child.material.map ;
}})
this.scene.add(result.scene);
});
// 设置渲染器
this.renderer = new THREE.WebGLRenderer({antialias: true})
this.renderer.setSize(container.clientWidth, container.clientHeight)
container.appendChild(this.renderer.domElement)
B. 挂载场景和相机
animate() {
this.renderer.render(this.scene, this.camera)
requestAnimationFrame(this.animate)
},
C. 设置控制项
initControls() {
//controls = new THREE.OrbitControls( camera, renderer.domElement );
this.controls = new OrbitControls(
this.camera,
this.renderer.domElement
);
// 如果使用animate方法时,将此函数删除
//controls.addEventListener( 'change', render );
// 使动画循环使用时阻尼或自转 意思是否有惯性
this.controls.enableDamping = false;
//动态阻尼系数 就是鼠标拖拽旋转灵敏度
//controls.dampingFactor = 0.25;
//是否可以缩放
this.controls.enableZoom = true;
//是否自动旋转
this.controls.autoRotate = true;
//设置相机距离原点的最远距离
this.controls.minDistance = 1;
//设置相机距离原点的最远距离
this.controls.maxDistance = 10;
//是否开启右键拖拽
this.controls.enablePan = false;
},
D. 设置视角重置
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.render(this.scene, this.camera)
},
E. 在vue的mounted周期中集合上述方法
this.init()
this.initControls()
this.animate()
window.onresize = this.onWindowResize;
4. 销毁实例
在项目中发现频繁的在3D场景的页面和其他页面切换会导致页面卡顿,是由于在切换路由时没有清除相关模型导致大量占用了内存;所以需要在离开3D场景销毁模型,并且释放相关的变量,例如renderer、scene、camera、controls。
beforeDestroy() {
this.scene.remove()
this.scene = null
this.camera = null
this.scene = null
this.renderer = null
this.ambientLight = null
this.controls = null
}
5. 实现效果