在three项目中需要加载很多的模型 而且在很多地方需要使用loader加载模型回调的gltf 上一个项目中遇到了 初学three的我 留下笔记
简单版
`
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
let model = new THREE.Group();
export const loaderModel = function (path) {
return new Promise(resolve => {
loader.load(path, function (gltf) {
// 遍历模型中的每个object
gltf.scene.traverse((object) => {
if (object.isMesh) {
//可以在这里做一些基础操作
}
});
if(model.children.length){
model.children.forEach(item=>{
model.remove(item)
})
}
model.add(gltf.scene);
resolve(gltf)
});
})
}
export { model };
`
后面根据别人的案例 做了一个完整的版本 支持使用indexDB 对模型缓存功能的
完整版
`
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
import utils from "utils";
import * as THREE from "three";
import DBUtils from "@/common/_/threejs/DBUtils";
var serverAddress = window.location.host; // 获取服务器地址
//params 为引入的模型地址或者地址集合 handleProgress 为 回调函数 用于计算加载进度
export default function loader(params, handleProgress) {
// 批量加载资源
// lodash 中的 isArray 方法
if (utils.isArray(params)) {
let funcarr = [];
let progressEvent = {
loaded: {},
total: {}
}
// lodash 中的 throttle 节流 方法
let update = utils.throttle(() => {
let loaded = 0, total = 0;
// lodash 中的 each 方法
utils.each(progressEvent.loaded, (v) => {
loaded += v;
});
utils.each(progressEvent.total, (v) => {
total += v;
});
// console.log(loaded, total);
handleProgress({
loaded,
total
})
}, 100);
let func = (i) => {
// console.log('func', progressEvent);
return (o) => {
progressEvent.loaded[i] = o.loaded;
progressEvent.total[i] = o.total;
update();
}
};
params.forEach((p, i) => {
funcarr.push(loader(p, func(i)))
});
return Promise.all(funcarr);
}
return new Promise(resolve => {
let path = params.path;
let ext = utils.getFileType(path);
let loader;
switch (ext) {
case 'glb':
case 'gltf':
if (params.decoderPath) {
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath(params.decoderPath);
loader = new GLTFLoader();
loader.setDRACOLoader(dracoLoader);
}
else {
loader = new GLTFLoader();
}
break;
case 'obj':
if (params.mtl) {
return new Promise(resolve => {
var mtlLoader = new MTLLoader();
// 初始化obj
var objLoader = new OBJLoader();
// 加载mtl文件
mtlLoader.load(params.mtl, (mtl) => {
// 初始化
mtl.preload();
// 加载贴图
objLoader.setMaterials(mtl);
objLoader.load(path, (obj) => {
resolve({ mtl, obj })
}, handleProgress);
})
});
}
else {
loader = new OBJLoader();
}
break;
case 'mtl':
loader = new MTLLoader();
break;
case "fbx":
loader = new FBXLoader();
break;
}
if (loader) {
if (path == 'models/swfq/zt1/shengwei.gltf') {
const indexDB = new DBUtils("gltf", "shengwei");
// 此处拼 服务器地址
indexDB.get('http://'+serverAddress + '/' + path)
.then((blob) => {
path = URL.createObjectURL(new Blob([blob]));
loader.load(path, (res) => {
resolve(res);
}, handleProgress)
});
} else {
loader.load(path, (res) => {
resolve(res);
}, handleProgress)
}
}
});
}
`
DBUtils 缓存的代码
export default class DBUtils { constructor(dbName, storeName, dbVersion = 1) { this.dbName = dbName; this.storeName = storeName; this.dbVersion = dbVersion; this.db = null; } async get(url) { this.db = await this.initDataBase(this.dbName, this.storeName, this.dbVersion); const request = this.db .transaction([this.storeName], 'readwrite') .objectStore(this.storeName) .get(url); return new Promise((resolve, reject) => { request.onsuccess = evt => { const modelFile = evt.target.result; console.log(modelFile); // 如果缓存中有,直接从缓存中获取 if (modelFile) { console.log("使用缓存"); resolve(modelFile.blob); } else { console.log("请求资源"); // 如果缓存中没有,则请求资源 this.addData(url).then(blob => { resolve(blob); }).catch(() => { reject(); }); } }; request.onerror = evt => { console.log('error', evt); reject(); }; }); }
utils 中全是引用 lodash 的方法 完整版是借鉴的大佬的代码
使用 完整版
`
loader(option.load, (progressEvent) => {
this.percentage = +(progressEvent.loaded * 99 / progressEvent.total).toFixed(2);
}).then(res => {
this.loading = false;
this.init();
if (!this.on.load) {
console.error("option.on.load方法不存在");
}
else {
this.on.load(this, res);
}
});
`
完整版有部分代码是复制的 欢迎大家一起讨论进步
标签:resolve,封装,import,three,loader,path,new From: https://www.cnblogs.com/babybearcq/p/18079975