【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函数,更方便业务测使用。

再接再厉~

相关推荐
Surmon7 小时前
彻底搞懂大模型 Temperature、Top-p、Top-k 的区别!
前端·人工智能
木斯佳9 小时前
前端八股文面经大全:bilibili生态技术方向二面 (2026-03-25)·面经深度解析
前端·ai·ssd·sse·rag
不会写DN9 小时前
Gin 日志体系详解
前端·javascript·gin
冬夜戏雪10 小时前
实习面经记录(十)
java·前端·javascript
爱学习的程序媛11 小时前
【Web前端】JavaScript设计模式全解析
前端·javascript·设计模式·web
小码哥_常11 小时前
从SharedPreferences到DataStore:Android存储进化之路
前端
老黑11 小时前
开源工具 AIDA:给 AI 辅助开发加一个数据采集层,让 AI 从错误中自动学习(Glama 3A 认证)
前端·react.js·ai·nodejs·cursor·vibe coding·claude code
薛先生_09911 小时前
js学习语法第一天
开发语言·javascript·学习
jessecyj11 小时前
Spring boot整合quartz方法
java·前端·spring boot
苦瓜小生12 小时前
【前端】|【js手撕】经典高频面试题:手写实现function.call、apply、bind
java·前端·javascript