可视化项目中经常会加载进模型,我的业务中,有个大楼的3D模型,一共有3个FBX模型,加起来30兆左右,使用公司之前的加载
组件加载一共耗费了将近20多秒。而且浏览器会卡顿
优化前:
模型显示花了10多秒,显示完后到能操作又消耗了10多秒,并且加载期间导致我的首屏动画无法逐帧显示,严重影响了效果的展
示,后来推测可能是js阻塞造成的,查看了之前FBX加载源码后发现了问题所在,解析FBX二进制,加上解析树的数据,工程量非常
之大。于是想到了利用worker解决这个问题。把所有的解析代码抽出来所谓独立的线程执行
核心的优化代码:
import setData from './setData.js'
/**
* 将arraybuffer解析成fbx信息树
* @private
*/
async function fbxParse(FBXBuffer,sourceDire){
if ( !isFbxFormatBinary( FBXBuffer ) ){
console.error("the arraybuffer of parse is not Fbx Format Binary");
return;
}
let fbxTree;
if(window.Worker){
// 创建脚本URL,内嵌worker或者可以使用相对路径
let blob = new Blob([setData,'setData()']);
let myWorker = new Worker (window.URL.createObjectURL(blob));
// 第二个参数使用可转让对象进行ArrayBuffer数据传递,提高性性能,不过会清除当前FBXBuffer
myWorker.postMessage(FBXBuffer,[FBXBuffer]);
await new Promise ((resolve,reject)=>{
myWorker.onmessage = (event) => {
fbxTree = event.data
resolve()
}
})
} else {
fbxTree = new BinaryParser().parse( FBXBuffer ); //fbx信息树
}
return new FBXTreeParser(sourceDire,fbxTree).parse(); //解析FBX树数据
}
setData.js
export default `function setData(){
.........
this.addEventListener('message', function (e) {
this.postMessage(new BinaryParser().parse(e.data))
}, false)
}`
这里setData中都是字符串,之前使用(function(){}).toString()发现使用Class类babel转码后window.URL.createObjectURL会报错,暂时没有时间研究,后续有空再解决
来看看对性能的提升:
优化前:
优化后:
而且加载完后,间隔1S左右就可以操作 比之前的性能提升了15倍左右
优化后(而且还是只优化的一半的结果):
二次加载可以利用indexDB缓存,就不用再解析