一、多文件加载
通过revit将很多专业文件合并成一个文件,稍微大点的文件合并的过程也会很痛苦,然后导出的GLTF文件很大threejs加载往往会内存溢出,一般来说一个文件大于50M,THREEJS就不好加载进来,往往会内存溢出,对于互联网上的加载,超过30M的文件加载用户体验及其差。所以需要对多文件进行分部加载,使用load多个文件加载至场景渲染。
部分代码:
CsscModelCore.prototype.loadGitfDraco = function(instance){
let gLTFLoader = new THREE.GLTFLoader()
let dracoLoader = new THREE.DRACOLoader();
dracoLoader.setDecoderPath('/js/plugin/threejs/examples/js/libs/draco/gltf/');
dracoLoader.setDecoderConfig({ type: 'js' });
gLTFLoader.setDRACOLoader(dracoLoader);
loadCsscModel(instance.settings.urls[0],instance.settings.urls,gLTFLoader,instance);
}
function loadCsscModel(url,urls,gLTFLoader,instance){
let indexUrl = 0;
for (let i = 0; i < urls.length; i++) {
if(urls[i] == url){
indexUrl = i;
break;
}
}
$('#loadding_total').html('总计:'+urls.length+"个文件,当前:"+indexUrl+".");
gLTFLoader.load(url, function(obj) {
obj.scene.rotateY(Math.PI);
instance.scene.add(obj.scene);
instance.setCenter(instance);
if(indexUrl < urls.length -1){
//递归加载文件
loadCsscModel(urls[indexUrl+1],urls,gLTFLoader,instance);
}else{
instance.render();
$('#loading').hide();
}
}, onProgress);
}
- 通过数组和递归将模型加载至场景
- 加载时可以增加遮罩提示用户加载进度
效果如下:
二、缓存的使用
1.threejs的cache
新版的threejs支持了缓存的机制,load的数据文件会存储在本地
Cache 的结构:
var Cache = {
enabled: false,
files: {},
add: function ( key, file ) {
if ( this.enabled === false ) { return; }
// console.log( 'THREE.Cache', 'Adding key:', key );
this.files[ key ] = file;
},
get: function ( key ) {
if ( this.enabled === false ) { return; }
// console.log( 'THREE.Cache', 'Checking key:', key );
return this.files[ key ];
},
remove: function ( key ) {
delete this.files[ key ];
},
clear: function () {
this.files = {};
}
};
threejs在加载文件的时候会首先判断Cache中是否存在已加载的文件,如果已经加载直接从缓存中读取
代码片段(示例):
load: function ( url, onLoad, onProgress, onError ) {
if ( url === undefined ) { url = ''; }
if ( this.path !== undefined ) { url = this.path + url; }
url = this.manager.resolveURL( url );
var scope = this;
var cached = Cache.get( url );//判断是否存在加载数据
if ( cached !== undefined ) {
scope.manager.itemStart( url );
......
2.Cache与IndexedDB
每次刷新页面都会重新拉取模型文件,不能读取本地缓存,影响用户体验,所以需要将模型数据手动加载至浏览器缓存,对于比较大的数据存储在IndexedDB中是比较合适的,IndexedDB允许储存大量数据,能建立索引,这些都是 LocalStorage 所不具备的,更接近 NoSQL 数据库,可按照key,value的方式操作。
通过与threejs 的Cache结合,我们可以实现首次刷新页面从服务端拉取数据,再次刷新从IndexedDB获取模型数据,减少带宽的使用率,提高threejs加载速度。
代码片段:
function intThreejsCache(){
let request = window.indexedDB.open("modelDB", 1);
request.onupgradeneeded = (ev) => {
modelDb = ev.target.result;
if (!modelDb.objectStoreNames.contains('info')) {
modelDb.createObjectStore('info');
}
console.log("数据库创建成功");
}
request.onsuccess = (ev) => {
console.log("数据库打开成功");
modelDb=ev.target.result;
THREE.Cache.enabled = true;//开启缓存
let transaction = modelDb.transaction(["info"], "readwrite");
let objectStoreModelDB = transaction.objectStore("info");
objectStoreModelDB.openCursor().onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
if(viewer.settings.urls.indexOf(cursor.key)>-1){
console.log("indexdb加载模型:"+cursor.key);
//将文件存入到threejs 的cache中
THREE.Cache.add( cursor.key, cursor.value );
}
cursor.continue();
}
};
transaction.oncomplete=function(event)
{
viewer.Init();
}
}
request.onerror = (ev) => {
console.log("打开数据库失败:"+ev.target.message);
}
}
- 每次刷新页面判断IndexedDB中是否存在需要加载的URL文件资源,可根据版本号、名称等判断是否为最新资源,存在则直接加载至cache中
- 每次load完模型后,将url的文件资源更新至IndexedDB中