需求:
threeJS加载在线的obj/stl模型,模型最大可达200-300兆,模型加载时因文件较大网络传输慢,模型更新保存崩溃,需进行优化处理。
解决方案:
获取在线的压缩文件链接,采用JSzip进行在线解压和在线压缩更新,提高性能。优化后经测试模型压缩率可达90%以上,模型加载速度大大提升,由原来的几分钟加载提升到几秒。
具体方法:
1. 获取服务器上的模型压缩文件的文件流,构造文件对象和加载地址,加载模型文件
(注:涉及到二进制流读取、文件解压和文件构造,文件类型需全部设为arraybuffer,否则会出现压缩文件损坏,文件字节长度不一致的错误,在这个坑里爬了好久,特此记录)
let loader = new THREE.STLLoader();
axios.get(zipUrl, {responseType: "arraybuffer"}).then(resp=>{
let files = new window.File([resp.data], 'zipFile', {type: 'zip'})
var new_zip = new JSZip();
// 解压缩文件对象
new_zip.loadAsync(files)
.then(function(result) {
// 压缩包的模型文件列表
let fileList = result.files
for(let key in fileList){
// 读取模型文件内容
new_zip.file(key).async("arraybuffer").then(content=>{
// Blob构造文件地址,通过url加载模型
let blob = new Blob([content])
let modelUrl = URL.creatObjectURL(blob)
loader.load(modelUrl).then(geometry=>{
// model加载,参考threeJS/example/webgl_loader_stl.html
})
})
}
});
})
2. 模型导出,压缩后更新到服务器
(注:JSZip只接收文件对象,new Blob的文件类型与STLExporter的导出类型需一致)
// 导出stl模型,输出结果为二进制流
let exporter = new STLExporter();
const content = exporter.parse( mesh, { binary: true } );
// 二进制流转为blob文件对象 (JSZip只接收文件对象)
let fileBlob = new Blob([content], { type: 'application/octet-stream' } )
var zip = new JSZip();
// 向zip文件中添加模型文件
zip.file("modelZip", fileBlob);
zip.generateAsync({
type: "blob", // 压缩类型
compression: "DEFLATE", // STORE:默认不压缩 DEFLATE:需要压缩
compressionOptions: {
level: 9 // 压缩等级1~9 1压缩速度最快,9最优压缩方式
}
}).then(function (zipBlob) { // 压缩的结果为blob类型(二进制流),可用作文件上传
let form = new FormData()
form.append("file", zipBlob)
form.append("name", "stlModel")
// 更新模型文件...
});
参考资料:
JSzip: https://stuk.github.io/jszip/
主要API参数:
二进制相关:Blob、arraybuffer、buffer的区别和用法参考:https://zhuanlan.zhihu.com/p/97768916
STL模型的导入导出参考:https://threejs.org/examples/#