当前位置: 代码网 > it编程>编程语言>Javascript > 如何threejs利用indexeddb缓存加载glb模型

如何threejs利用indexeddb缓存加载glb模型

2024年05月26日 Javascript 我要评论
threejs利用indexeddb缓存加载glb模型有个坑,时不时的下载文件会遇到206错误。用axios的时候啊 responsetype: 'blob’下载不一定会成功。与文

threejs利用indexeddb缓存加载glb模型

有个坑,时不时的下载文件会遇到206错误。

用axios的时候啊 responsetype: 'blob’下载不一定会成功。

与文件的格式与编码有关系。

后面我就换成fetch方式了,但fetch的blob()争对所有文件下载也不是都成功,比如json文件得用json(),还有一些编码为gbk格式的用blob()也不一定回成功,用arraybuffer();

1、加载工具类 indexeddb.js

使用 indexeddb

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;
                // 假如已经有缓存了 直接用缓存
                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数据添加成功');
                resolve(obj.blob);
            };
            inputrequest.onerror = function(evt) {
                console.log('glb数据添加失败', 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转成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
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com