如何threejs利用indexeddb緩存加載glb模型
threejs利用indexeddb緩存加載glb模型
有個坑,時不時的下載文件會遇到206錯誤。
用axios的時候啊 responseType: 'blob’下載不一定會成功。
與文件的格式與編碼有關(guān)系。
后面我就換成fetch方式了,但fetch的blob()爭對所有文件下載也不是都成功,比如json文件得用json(),還有一些編碼為gbk格式的用Blob()也不一定回成功,用arraybuffer();
1、加載工具類 indexeddb.js
const DB_NAME = 'daxue1'; const DB_VERSION = 1; // Use a long long for this value (don't use a float) const DB_STORE_NAME = 'model_glb'; export class DBUtil { async get(url, onProgress) { this.db = await this.initDataBase(); let getRequest = this.db .transaction([DB_STORE_NAME], "readwrite").objectStore(DB_STORE_NAME).get(url); let that = this; return new Promise((resolve, reject) => { getRequest.onsuccess = function (event) { let modelFile = event.target.result; // 假如已經(jīng)有緩存了 直接用緩存 if (modelFile) { if (onProgress) { onProgress(100); } resolve(modelFile.blob) } else { // 假如沒有緩存 請求新的模型存入 that.put(url, onProgress).then((blob) => { resolve(blob) }).catch(() => { reject() }); } }; getRequest.onerror = function (event) { console.log('error', event) reject() } }) } async put(url, onProgress) { const response = await fetch(url); if (response.status !== 200) { throw new Error('Request failed'); } const contentLength = response.headers.get('Content-Length'); console.log(contentLength) const totalBytes = parseInt(contentLength, 10); let downloadedBytes = 0; const readableStream = response.body; const { readable, writable } = new TransformStream(); const writer = writable.getWriter(); const reader = readableStream.getReader(); const pump = async () => { const { done, value } = await reader.read(); if (done) { writer.close(); return; } writer.write(value); downloadedBytes += value.length; if (onProgress) { const progress = (downloadedBytes / totalBytes) * 100; console.log(progress.toFixed(2)) onProgress(progress.toFixed(2)); } return pump(); }; await pump(); let blob = null; try { blob = await new Response(readable).arrayBuffer(); } catch (e) { console.log('請求arrayBuffer失敗,用blob方式') blob = await new Response(readable).blob(); } let obj = { ssn: url } obj.blob = new Blob([blob]) const inputRequest = this.db .transaction([DB_STORE_NAME], "readwrite") .objectStore(DB_STORE_NAME) .add(obj); return new Promise((resolve, reject) => { inputRequest.onsuccess = function() { console.log('glb數(shù)據(jù)添加成功'); resolve(obj.blob); }; inputRequest.onerror = function(evt) { console.log('glb數(shù)據(jù)添加失敗', evt); reject(); }; }); } initDataBase() { if (!window.indexedDB) { console.log("Your browser doesn't support a stable version of IndexedDB.") return; } let request = indexedDB.open(DB_NAME, DB_VERSION); return new Promise((resolve, reject) => { request.onerror = function () { console.log("error: create db error"); reject() }; request.onupgradeneeded = function (evt) { evt.currentTarget.result.createObjectStore( DB_STORE_NAME, {keyPath: 'ssn'}); }; request.onsuccess = function (evt) { console.log("onsuccess: create db success "); resolve(evt.target.result) }; }) } }
2、加載模型
let url = URL.createObjectURL(new Blob([blob]))
利用URL.createObjectURL把blob轉(zhuǎn)成load可加載的url
import * as THREE from 'three/build/three.module.js'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import {DBUtil} from "../util/DBUtil"; let model = new THREE.Group(); new DBUtil().get('/droc_model/changsharelease.glb',(progress) => { console.log(progress) }).then((blob) => { console.log('getModel獲取成功', blob); let loader = new GLTFLoader(); let url = URL.createObjectURL(new Blob([blob])); loader.load(url, function (gltf) { model.add(gltf.scene); }, function ( xhr ) { console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' ); }) }) export { model }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Javascript實現(xiàn)顏色rgb與16進制轉(zhuǎn)換的方法
這篇文章主要介紹了Javascript實現(xiàn)顏色rgb與16進制轉(zhuǎn)換的方法,實例分析了顏色值轉(zhuǎn)換的常用技巧與使用方法,非常具有實用價值,需要的朋友可以參考下2015-04-04ExtJs的Ext.Ajax.request實現(xiàn)waitMsg等待提示效果
這篇文章主要介紹了ExtJs的Ext.Ajax.request實現(xiàn)waitMsg等待提示效果,需要的朋友可以參考下2017-06-06Bootstrap 網(wǎng)站實例之單頁營銷網(wǎng)站
這篇文章主要介紹了Bootstrap 網(wǎng)站實例之單頁營銷網(wǎng)站的相關(guān)資料,本文給大家介紹的非常詳細具有一定的參考借鑒價值,需要的朋友可以參考下2016-10-10javascript實現(xiàn)了照片拖拽點擊置頂?shù)恼掌瑝Υa
這篇文章主要介紹了javascript實現(xiàn)了照片拖拽點擊置頂?shù)恼掌瑝Υa,效果非常不錯,這里推薦給大家,有需要的小伙伴可以參考下。2015-04-04javascript用rem來做響應(yīng)式開發(fā)
這篇文章主要介紹了javascript用rem來做響應(yīng)式開發(fā),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01實用又漂亮的BootstrapValidator表單驗證插件
這篇文章主要為大家詳細介紹了好用又漂亮的BootstrapValidator表單驗證插件,感興趣的小伙伴們可以參考一下2016-05-05