【WebGis开发 - Cesium】如何确保Cesium场景加载完毕

目录

引言

本篇为Cesium开发的一些小技巧。

判断Cesium场景是否加载完毕这件事是非常有意义的。

  • 加载场景本身是个异步过程,然而我们经常会遇到一些业务场景是需要基于某一个模型加载完毕后再进行初始化操作,然后对模型进行操作。
  • 包含三维场景的页面和日常浏览的网页在加载效率上是不同的,人们往往对包含三维场景页面加载时长的容忍度会比较高。我们需要给出一个直观的加载过程用于安慰用户耐心等待较长的加载过程。
  • Cesium的模型加载策略是由粗到细分片加载,我们需要用户可以直接看到一个已经加载完毕的场景,而不是一点点细化的过程。

一、监听场景加载进度

这个功能要用到 CeiusmEventHelper 子类,监听 tileLoadProgressEvent 方法

1. 基础代码

javascript 复制代码
  const helper = new Cesium.EventHelper();
  helper.add(viewer.scene.globe.tileLoadProgressEvent, (e) => {
	console.log(e);
  });

解释下代码,这里初始化了一个EventHelper实例,并监听tileLoadProgressEvent方法,他会监听每帧场景中切片加载队列的长度。回调函数入参 e 为int类型数字,代表当前场景中剩余未加载的切片数量。

2. 加工代码

javascript 复制代码
  const helper = new Cesium.EventHelper();
  let maxTile = 0;
  let isLoaded = false;
  helper.add(viewer.scene.globe.tileLoadProgressEvent, (e) => {
    maxTile = Math.max(maxTile, e);
    const progress = Math.floor(((maxTile - e) / maxTile) * 100);
    isLoaded = viewer.scene.globe.tilesLoaded;
    console.log("progress", progress);
    console.log("tilesLoaded", isLoaded);

解释下代码,这里在基础代码上做了一点点加工,在外部设置个最大切片数量的变量,使用Math.max赋予最大的切片数量值,通过最大值和当前值的计算可得一个百分比进度值。此外 viewer.scene.globe.tilesLoaded 是一个Boolean值,更直观的表达了切片是否加载完成。此时我们得到了加载进度和加载完成的标志。


二、进一步封装代码

1. 已知存在的弊端

我们已经知道了如何监听场景切片的加载进度,但是它会在每一次拖动地球转动时同样监听到这个微调的过程。我们希望只有在页面初始化时、加载模型时调用一次监听事件提供进度提示,其他时候不监听。

2. 封装hooks函数

想象一下函数的使用场景,我们需要监听场景中切片的进度和完成标志,我们还需要它只监听一次就清理监听事件,额外提供销毁方法不要继续占用资源,最后需要它能够实时输出进度值和加载完成标志。

利用vue3的响应式变量方法ref,将progress 、isLoaded 包装为响应式变量。

javascript 复制代码
import { ref } from "vue";

export const useTileloadProgress = () => {
  const helper = new Cesium.EventHelper();

  let isLoaded = ref(false);
  let progress = ref(0);

  /**
   * @description: 触发监听事件
   * @return {*}
   */
  const _onLoad = () => {
    let maxTile = 0;
    helper.add(viewer.scene.globe.tileLoadProgressEvent, (e) => {
      maxTile = Math.max(maxTile, e);
      progress.value = Math.floor(((maxTile - e) / maxTile) * 100);
      isLoaded.value = viewer.scene.globe.tilesLoaded;
      //   当一次加载完成后移除监听事件
      if (isLoaded.value) {
        _onRemove();
      }
    });
  };

  /**
   * @description: 移除监听事件
   * @return {*}
   */
  const _onRemove = () => {
    helper.removeAll();
  };

  /**
   * @description: 移除监听事件,清理EventHelper实例,初始化变量值。
   * @return {*}
   */
  const _onDestroy = () => {
    remove();
    helper = null;
    isLoaded.value = false;
    progress.value = 0;
  };

  return {
    progress,
    isLoaded,
    _onLoad,
    _onRemove,
    _onDestroy,
  };
};

三、使用hooks方法

1. 先看下效果

基础场景加载有点快,加载模型或者地图时,效果应该更明显些。

2. 如何使用该hooks方法

初始化场景请参考:【WebGis开发 - Cesium】三维可视化项目教程---初始化场景

在获取了progress和isLoaded两个变量后,可以进一步使用项目UI框架做提示,或者美化一个进度加载的界面。自由发挥

javascript 复制代码
<script setup>
import { onMounted } from "vue";
import { initCesiumMap } from "@/utils/cesium/index.js";
import { useTileloadProgress } from "@/hooks/useTileloadProgress.js";
const { progress, isLoaded, _onLoad, _onRemove, _onDestroy } =
  useTileloadProgress();
onMounted(() => {
// 初始化地球场景
  initCesiumMap();
// 监听加载进度
  _onLoad();
});
</script>

三、总结

本篇主要介绍了如何利用 EventHelpertileLoadProgressEvent 来判断一个Cesium场景是否加载完成。解决了Cesium场景无法感知加载进度的问题,给业务场景开发提供了明确完成标志。

利用vue3.0的新特性,将以上方法封装为hooks函数,更方便业务测使用。

再接再厉~

相关推荐
web守墓人33 分钟前
【前端】ikun-markdown: 纯js实现markdown到富文本html的转换库
前端·javascript·html
Savior`L39 分钟前
CSS知识复习5
前端·css
许白掰39 分钟前
Linux入门篇学习——Linux 工具之 make 工具和 makefile 文件
linux·运维·服务器·前端·学习·编辑器
中微子5 小时前
🔥 React Context 面试必考!从源码到实战的完整攻略 | 99%的人都不知道的性能陷阱
前端·react.js
秋田君6 小时前
深入理解JavaScript设计模式之命令模式
javascript·设计模式·命令模式
中微子6 小时前
React 状态管理 源码深度解析
前端·react.js
风吹落叶花飘荡7 小时前
2025 Next.js项目提前编译并在服务器
服务器·开发语言·javascript
加减法原则7 小时前
Vue3 组合式函数:让你的代码复用如丝般顺滑
前端·vue.js
yanlele8 小时前
我用爬虫抓取了 25 年 6 月掘金热门面试文章
前端·javascript·面试
lichenyang4538 小时前
React移动端开发项目优化
前端·react.js·前端框架