前言

使用webgl开发三维应用的时候,经常会发现三维场景加载比较慢,往往需要等待挺长时间,这样用户的体验就很不友好。 造成加载慢的原因,主要是三维应用涉及到的资源文件会特别多,这些资源文件主要是模型及其图片,往往这些模型和图片都会比较大。

为了加快三维场景的加快速度,可以使用IndexedDB在客户端进行资源缓存。IndexedDB,即客户端持久化数据库!使用本缓存技术,在初次访问后,3D场景中的文件级别数据将写入访问设备本地缓存数据库,在客户端实现永久的生命周期,清除浏览器缓存也不影响已缓存的3D模型文件。

IndexedDB介绍

IndexedDB 是一个前端数据持久化解决方案(即前端缓存),由浏览器实现。

IndexedDB又如下特点

  • 基于文件存储。意味着其容量可达到硬盘可用空间上限
  • 非关系型数据库。意味着扩展或收缩字段一般无须修改数据库和表结构(除非新增字段用做索引)
  • 键值对存储。意味着存取无须字符串转换过程
  • 存储类型丰富。意味着浏览器缓存中不再是只能存字符串了
  • 异步: 意味着所有操作都要在回调中进行

本地浏览器拥有三种永久存储数据技术,分别为Web Storage、IndexedDB、Web SQL。IndexedDB具备查询高效、存储空间大和异步操作等技术特征,有巨大的优势。

存储空间大。IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。在HTML5本地存储中,IndexedDB存储的数据则是最多的。

查询高效。IndexedDB是一种轻量级NOSQL数据库,是由浏览器自带。相比Web Sql更加高效,包括索引、事务处理和查询功能。

异步操作。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。

与此同时,IndexedDB 内部采用对象仓库存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象,满足了三维场景的存储需要。

因此 使用IndexedDB缓存是一种最为优异的前端缓存方案。像Babylon.js,其引擎层面已经支持了IndexedDB缓存。可以参考如下文档:

https://doc.babylonjs.com/divingDeeper/scene/optimizeCached。

three.js使用IndexedDB的思路

有关具体如何使用IndexedDB,有很多资料进行介绍,此文不在赘述。

使用IndexedDB缓存模型资源,首先需要获取模型相关的资源,这些模型资源包括模型文件以及相关的图片文件。 比如对于GLTF模型而言,其资源包括.gltf的模型主文件,.bin格式的文件,纹理贴图文件等等。 首次加载加一个模型的时候,肯定是加载网络上的资源文件,通过threejs的LoadingMananger可以收集一个gltf模型的各种资源文件。 代码如下:

    const resourceCollector = [];
const loadingManager = new LoadingManager();
loadingManager.setURLModifier( (url,path) => {
console.log(url);
if(url.startsWith("data:") || url.startsWith("blob:")) {
return url;
}
resourceCollector.push(url);
return url;
});

上述代码resourceCollector收集了加载模型过程中所有的模型资源的地址。 收集之后把所有资源存储到IndexedDB中:

saveGltfModel:async function(options,resourceCollector){
const gltfUrl = options.gltfPath;
const blobs = {};
for(let i = 0;i < resourceCollector.length;i ++) {
let url = resourceCollector[i];
let blob = await loadAsBlob(url);
blobs[url] = blob;
await addToDatabase("model",{key:url,blob})
}
await addToDatabase("model_info",{key:gltfUrl,content:resourceCollector});
},

其中loadAsBlob是把一个资源加载成为blob对象,代码如下:

  const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "blob";
xhr.onerror = function() {reject("Network error.")};
xhr.onload = function() {
if (xhr.status === 200) {resolve(xhr.response)}
else {reject("Loading error:" + xhr.statusText)}
};
xhr.send();

而addToDatabase方法把资源添加到IndexedDB数据库。

function addToDatabase(storename, data) {
const promise = new Promise( (resolve,reject) => {
let store = database.transaction(storename, 'readwrite').objectStore(storename);
let countReq = store.count(data.key);
countReq.onsuccess = function(event) {
console.log("count:",event.target.result);
let count = event.target.result;
if(count == 0) {
let request = store.add(data);
request.onerror = function (event) {
console.error('add添加数据库中已有该数据')
reject(event);
};
request.onsuccess = function (event) {
console.log('add添加数据已存入数据库')
resolve(event);
};
}
};
});
}

下一次获取模型的时候,可以先判断是否以及本地存储,如果已经本地存储,就可以直接从本地获取模型资源:

 if(this.indexDbCache && indexedDB) {
if(database == null) {
database = await initialDB();
}
const storeObject = await findInDatabase("model_info",key);
if(storeObject) {
return this.loadGltfInDb(options);
}
}

缓存效果测评

通过测试可以发现对于比较大的场景,模型加载的速度可以提高几倍,十几倍甚至几十倍。 由此可见,IndexedDB缓存效果很明显。

如果对可视化感兴趣,可以和我交流,微信541002349。

关注公号“ITMan彪叔” 可以及时收到更多有价值的文章。

使用IndexedDB缓存给WebGL三维程序加速的更多相关文章

  1. WebGL之绘制三维地球

    通过Three.js也许可以很方便的展示出3D模型,但是你知道它是怎么一步一步从构建网格到贴图到最终渲染出3D模型的吗?现在我们直接使用底层的webgl加上一点点的数学知识就可以实现它. 本节实现的效 ...

  2. Redis 分布式缓存 Java 框架

    为什么要在 Java 分布式应用程序中使用缓存? 在提高应用程序速度和性能上,每一毫秒都很重要.根据谷歌的一项研究,假如一个网站在3秒钟或更短时间内没有加载成功,会有 53% 的手机用户会离开. 缓存 ...

  3. 使用ArcGIS Pro编辑在线三维服务图层

    ArcGIS Pro 从2.2版本起,提供了编辑在线三维服务图层的功能.通过该功能,我们可以直接在Pro中编辑发布的三维服务图层Web Scene Layer. 我们知道三维场景服务支持包含多种类型的 ...

  4. 渐进式web应用开发---使用indexedDB实现ajax本地数据存储(四)

    在前几篇文章中,我们使用service worker一步步优化了我们的页面,现在我们学习使用我们之前的indexedDB, 来缓存我们的ajax请求,第一次访问页面的时候,我们请求ajax,当我们继续 ...

  5. 使用Three.js网页引擎创建酷炫的3D效果的标签墙

    使用Three.js引擎(这是开源的webgl三维引擎,gitgub)进行一个简单应用. 做一个酷炫的3d效果的标签墙(已经放在我的博客首页,大屏幕可见), 去我的博客首页看看实际效果 www.son ...

  6. 探究 CSS 混合模式\滤镜导致 CSS 3D 失效问题

    今天在写一个小的 CSS Demo,一个关于 3d 球的旋转动画,关于 CSS 3D,少不了会使用下面这几个属性: { transform-style: preserve-3d; perspectiv ...

  7. 卸载重装ArcGIS Enterprise 注意事项

    ArcGIS Enterprise ,通俗的讲,即“ArcGIS Server 10.5+ 版本” 强烈建议参考文档: windows环境安装ArcGIS Enterprise ,http://zhi ...

  8. 有趣的 Mysql 存储引擎

    Mysql 提供了一套统一的应用开发模型和核心 API,因此,尽管不同的存储引擎拥有不同的特性,不过对于开发人员,应用操作都是完全透明的.应用层的连接并不直接访问存储引擎层,而是访问 Mysql 提供 ...

  9. Autocad2017破解版下载|Autodesk Autocad 2017中文破解版下载 64位(附注册机/序列号)

    Autocad2017是Autodesk公司开发的自动计算机辅助设计软件,可用于二维绘图.详细绘制.设计文档和基本三维设计,它具有良好的用户界面,允许用户通过交互菜单或命令行方式来进行各种操作,包括图 ...

随机推荐

  1. idea使用教程-安装

    [1]将安装包进行解压-->选择固态盘符 [2]发送到桌面快捷方式,生成一个快捷方式 [3]打开: 选择主题: 先进入再说,免费试用: 创建一个项目: 选择JDK: 找到jetbrains-ag ...

  2. Xcode导入IQKeyboardManager库

    下载IQKeyboardManager库 下载链接:https://github.com/hackiftekhar/IQKeyboardManager 将IQKeyboardManager文件夹拖入工 ...

  3. Java初学者作业——编写Java程序, 实现根据用户购买商品总金额, 计算实际支付的金额及所获得的购物券金额。

    返回本章节 返回作业目录 需求说明: 编写Java程序, 实现根据用户购买商品总金额, 计算实际支付的金额及所获得的购物券金额. 购买总金额达到或超过 1000元,按 8折优惠,送 200元的购物券: ...

  4. localstorage的浏览器支持情况

    localStorage的兼容性不错,就国内的情况,已经基本没有问题了.localStorage的原理很简单,浏览器为每个域名划出一块本地存储空间,用户网页可以通过localStorage命名空间进行 ...

  5. 美和易思 · 「云农职互联网技术学院」HTML+CSS 做西普尼金表官网

    假期作业,好久没碰了,代码写得很烂......写博客纯属记录! 源代码下载地址:https://download.csdn.net/download/weixin_44893902/12805555 ...

  6. Sentry 企业级数据安全解决方案 - Relay 入门

    内容整理自官方开发文档 Sentry Relay 通过提供作为应用程序和 sentry.io 之间中间层的独立服务来提供企业级数据安全性. Relay 专门设计用于: 在将个人身份信息 (PII) 发 ...

  7. SpringBoot中JPA使用动态SQL查询

    https://www.jianshu.com/p/f72d82e90948 可以重点关注方法二,把原生sql传入数据库去查询 好处是:更加灵活坏处是:拼接sql比较痛苦,也容易出问题,比如拼接的sq ...

  8. GitForWindows工具集(GitBash命令行)

    1.Git For Windows工具集 Git For Windows专注于提供一套轻量级的本地工具集, 它将Git SCM的完整功能集引入Windows, 同时为Git用户提供适当的用户界面, 方 ...

  9. Java 获取客户端浏览器中的语言设置

    获取客户端的首选语言 javax.servlet.ServletRequest.getLocale() 根据Accept-Language请求头返回客户端的首选语言.如果客户端请求没有Accept-L ...

  10. CSS基础6之盒子模型1

    盒子概述 以下是盒子模型的一个图形解释 一.内边距(填充) 属性有: (1) padding  设置所有内边距 (2) padding-top  设置上边距 (3) padding-left 设置左边 ...