Three.js 实现模型文件加载进度条 和total为0 lengthComputable为false 情况处理

three.js GLTFLoader ,FBXLoader,GLTFLoader,OBJLoader的load 方法提供了获取当前文件进度的方法函数

在上一篇 Three.js加载外部glb,fbx,gltf,obj 模型文件 的文章基础上新增一个 onModelProgress(获取模型加载进度条方法)

  onModelProgress(progressEvent ){
    
    
      const {
    
     loaded ,total ,lengthComputable } = progressEvent 
        //lengthComputable  true 可以获取到当前文件的总字节大小
       if(lengthComputable ){
    
    
        const progress = loaded / total * 100
        console.log( progress + '% loaded' )
        }else{
    
    
            console.log('已加载'+loaded+'字节' )
      }
   }

进度条关键参数:

1.loaded: 表示已加载的字节数。
2.total: 表示需要加载的总字节数。
3.lengthComputable: 一个布尔值,指示是否能够确定要加载的总字节数。

注意:lengthComputable 为false 表示无法获取到 当前文件的总字节(total)大小

可能原因有以下几种:

1.文件资源在项目本地文件夹public(vue项目)
2.服务器未提供 Content-Length: 服务器在响应头中未提供正确的 Content-Length 字段,或者提供的值无效。在这种情况下,浏览器无法确定要加载的总字节数,因此 lengthComputable 被设置为 false
3.流式传输: 一些加载场景中,数据是通过流式传输的方式加载的,因此无法预先知道要加载的总字节数。例如,通过 WebSocket 或 SSE (Server-Sent Events) 加载数据时,通常无法确定总字节数。

完整代码如下:

import * as THREE from 'three' //导入整个 three.js核心库
import {
    
     GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' 
import {
    
     DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import {
    
     OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import {
    
     FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
// 定义一个 class类
class renderModel {
    
    
    	constructor(selector) {
    
    
    	    this.container = document.querySelector(selector)
		    // 相机
	    	this.camera
		    // 场景
		    this.scene
		    //渲染器
		    this.renderer
		    // 控制器
		    this.controls
		    // 模型
		    this.model    
		     //文件加载器类型
		    this.fileLoaderMap = {
    
    
			'glb': new GLTFLoader(),
			'fbx': new FBXLoader(),
			'gltf': new GLTFLoader(),
			'obj': new OBJLoader(),
		}
         }
         // 初始化加载模型方法
        init(){
    
    
         	return new Promise(async (reslove, reject) => {
    
    
			//初始化场景
			this.initScene()
			//初始化相机
			this.initCamera()
			//初始化渲染器
			this.initRender()
			// 添加物体模型 TODO:初始化时需要默认一个  filePath:'threeFile/glb/glb-3.glb' 放在 vue项目中的public/threeFile文件下
			const load = await this.setModel({
    
     filePath: 'threeFile/glb/glb-3.glb', fileType: 'glb',scale:0.5})
			//监听场景大小改变,跳转渲染尺寸
			window.addEventListener("resize", this.onWindowResize.bind(this))
			//场景渲染
			this.sceneAnimation()
			reslove(load)
	   	  })
        }
        //创建场景
	initScene() {
    
    
        this.scene = new THREE.Scene()
		const texture = new THREE.TextureLoader().load(require('@/assets/image/view-4.png'))
		texture.mapping = THREE.EquirectangularReflectionMapping
		// texture.colorSpace = THREE.SRGBColorSpace
		this.scene.background = texture
		this.scene.environment = texture

	}
		// 创建相机
	initCamera() {
    
    
		const {
    
     clientHeight, clientWidth } = this.container
		this.camera = new THREE.PerspectiveCamera(45, clientWidth / clientHeight, 0.25, 100)
	}
	 // 创建渲染器
	initRender() {
    
    
		this.renderer = new THREE.WebGLRenderer({
    
     antialias: true, alpha: true }) //设置抗锯齿
		//设置屏幕像素比
		this.renderer.setPixelRatio(window.devicePixelRatio)
		//渲染的尺寸大小
		const {
    
     clientHeight, clientWidth } = this.container
		this.renderer.setSize(clientWidth, clientHeight)
		//色调映射
		this.renderer.toneMapping = THREE.ACESFilmicToneMapping
		//曝光
		this.renderer.toneMappingExposure = 3
		this.renderer.shadowMap.enabled = true
		this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
		this.container.appendChild(this.renderer.domElement)
	}
	// 使用动画器不断更新场景
	 sceneAnimation() {
    
    
		this.renderer.setAnimationLoop(this.render.bind(this))
	 }
     //渲染场景
	render(){
    
    
	  this.renderer.render(this.scene, this.camera)
	}
	//加载模型
	setModel({
     
      filePath, fileType, scale,  position }) {
    
    
		return new Promise((resolve, reject) => {
    
    
			const loader = this.fileLoaderMap[fileType]
			loader.load(filePath, (result) => {
    
    
			  //加载不同类型的文件
				switch (fileType) {
    
    
					case 'glb':
						this.model = result.scene		
						break;
					case 'fbx':
						this.model = result
						break;
					case 'gltf':
						this.model = result.scene
						break;
					case 'obj':
						this.model = result
						break;
					default:
						break;
				}
				// 设置模型大小
				if (scale) {
    
    
					this.model.scale.set(scale, scale, scale);
				}
				// 设置模型位置 
				if (position) {
    
    
					const {
    
     x, y, z } = position
					this.model.position.set(x, y, z)
				}
				// 设置相机位置
				this.camera.position.set(0, 2, 6)
				// 设置相机坐标系
				this.camera.lookAt(0, 0, 0)
	             // 将模型添加到场景中去   
				this.scene.add(this.model)
				resolve(true)
			}, this.onModelProgress, (err) => {
    
    
				console.log(err)
				reject()
			})
		})
	}
   onModelProgress(progressEvent ){
    
    
      const {
    
     loaded ,total ,lengthComputable } = progressEvent 
        //lengthComputable  true 可以获取到当前文件的总字节大小
       if(lengthComputable ){
    
    
        const progress = loaded / total * 100
        console.log( progress + '% loaded' )
        }else{
    
    
            console.log('已加载'+loaded+'字节' )
      }
   }
}

完整的代码可参考:https://gitee.com/ZHANG_6666/Three.js3D

界面效果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43835425/article/details/132859274