【CesiumJS入门】(5)GooJSON的加载、更新、监听与销毁——GeoJsonDataSource应用

前言

本篇,我们将较完整得介绍Cesium中GeoJSON/TopoJSON相关的方法。

GeoJSON规范地址:RFC 7946: The GeoJSON Format (rfc-editor.org)
GeoJSON在线绘制:geojson.io

CesiumJS提供了一个名为DataSource的类,它主要是用来加载和展示矢量数据,包括但不限于 GeoJSON、KML、TopoJSON、CZML等格式的数据。而今天,我们将介绍DataSource的一个子类GeoJsonDataSource。让我们直入主题,写一个包括了GeoJSON数据的加载、更新、销毁、监听等方法的类。

一、准备

准备GeoJSON文件,你可以在我上面提供的在线绘制网站直接绘制,也可以从这个项目的代码仓库里下载:src/assets/geojson

// 将这些文件引入:
import pointSample from '@/assets/geojson/point.json' // 示例点要素
import lineSample from '@/assets/geojson/line.json' // 示例线要素
import polygonSample from '@/assets/geojson/polygon.json' // 示例面要素
import collectionSample from '@/assets/geojson/collection.json' // 示例要素集合

二、加载

把类的框架写出来,让后向里面加入第一个方法,load()

class CesiumGeoJSON {
  constructor(data, options, callback) {
    this.data = data;
    this.options = options;
    this.dataSource = null;

    // 初始化 GeoJSON 数据源
    this.init(callback);
  }

  // 初始化 GeoJSON 数据源
  init(callback) {
    Cesium.GeoJsonDataSource.load(this.data, this.options)
      .then((dataSource) => {
        this.dataSource = dataSource
        viewer.dataSources.add(this.dataSource);

        // this.dataSource.describe = ''
        // this.dataSource.credit = ''
        // dataSource.show = true // boolean - Whether to show
        // dataSource.name = '' // string - The name of the data source

        viewer.zoomTo(this.dataSource)

        callback && callback(this.dataSource) // 触发回调函数
      }).catch((error) => {
        console.error('矢量数据加载发生了一些错误:', error);
      })
  }
}

从上面的代码可以看出,我们在创建和初始化这个类的实例对象时,可以提供3个参数:

  • data —— GeoJSON或TopoJSON的数据源,可以是string、object或Cesium的Resource格式。
  • options —— 加载数据源时的可选项:GeoJsonDataSource.LoadOptions
  • callback —— 回调函数,将加载完成的矢量数据(dataSource)暴露出去供调用
// 调用:实例化然后就直接加载
const jsonInstance= new CesiumGeoJSON(collectionSample)

在这里插入图片描述

三、更新(重新加载)

在实际生产中,我们可能需要修改数据源,达到一个更新数据、重新加载的效果。那么就让我们向CesiumGeoJSON类中加入下述方法:

  // 更新(重新加载)数据源
  async update(newData, options) {
    if (this.dataSource == null) {
      throw new Error('矢量数据未加载或已被销毁');
    }

    if (typeof newData == 'object') {
      // 使用 Cesium.Resource 对象创建一个新的 GeoJSON 数据源,这么做才能触发changeEvent
      const resource = new Cesium.Resource({
        url: URL.createObjectURL(new Blob([JSON.stringify(newData)], { type: 'application/json' }))
      });
      return await this.dataSource.load(resource, options)
    } else {
      return await this.dataSource.load(newData, options)
    }
  }

调用:

// 实例化然后就直接加载
constjsonInstance = new CesiumGeoJSON(collectionSample)

// 调用:2秒后更新数据
setTimeout(() => {
  jsonInstance.update(pointSample)
}, 2000);

在这里插入图片描述

四、新增(不替换已有的数据)

如果我需要向数据集中额外添加新的矢量数据呢?那就添加这个方法:

   // 新增(不替换已有的数据)数据源
  async add(newData, options) {
    if (this.dataSource == null) {
      throw new Error('矢量数据未加载或已被销毁');
    }

    // 使用 Cesium.Resource 对象创建一个新的 GeoJSON 数据源,这么做才能触发changeEvent
    const resource = new Cesium.Resource({
      url: URL.createObjectURL(new Blob([JSON.stringify(newData)], { type: 'application/json' }))
    });

    // 重新加载数据源
    return await this.dataSource.process(resource, options);
  }

在上一步的基础上再调用,加入线数据:

// 实例化后加载
constjsonInstance = new CesiumGeoJSON(collectionSample)

setTimeout(() => {
  jsonInstance.update(pointSample)
  jsonInstance.add(lineSample) // 调用:添加数据
}, 2000);

在这里插入图片描述

五、监听

  // 监听数据源的变化
  watch() {
    if (this.dataSource == null) {
      throw new Error('矢量数据未加载或已被销毁');
    }

    // 监听数据源变化事件
    this.dataSource.changedEvent.addEventListener(this._changedEvent);
    // 监听错误事件
    this.dataSource.errorEvent.addEventListener(this._errorEvent);
  }

  // 数据源变化的事件
  _changedEvent(dataSource) {
    console.log('矢量数据源已被修改:', dataSource);
  }

  // 数据错误的事件
  _errorEvent(err) {
    console.error('矢量数据加载发生了一些错误:', err);
  }

六、销毁

  // 销毁数据源和监听器
  destroy() {
    if (this.dataSource == null) {
      throw new Error('矢量数据未加载或已被销毁');
    }

    // 取消所有监听器
    this.dataSource.changedEvent.removeEventListener(this.changedEvent);
    this.dataSource.errorEvent.removeEventListener(this.errorEvent)

    // 移除数据源
    viewer.dataSources.remove(this.dataSource);
    this.dataSource = null;
    console.log('CesiumGeoJSON has been destroyed.');
  }

0. 最后

代码提交记录:
feat: 新增GeoJSON相关方法 · 0f31b7e · ReBeX/cesium-tyro-blog - Gitee.com
fix: 优化数据源更新方法 · 411ab3f · ReBeX/cesium-tyro-blog - Gitee.com

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个使用Cesium和Three.js加载3D模型的示例代码: ```javascript // 创建Cesium Viewer var viewer = new Cesium.Viewer("cesiumContainer"); // 创建Three.js场景 var scene = new THREE.Scene(); // 创建Three.js渲染器 var renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true, }); renderer.setSize(viewer.canvas.clientWidth, viewer.canvas.clientHeight); renderer.setPixelRatio(window.devicePixelRatio); renderer.gammaInput = true; renderer.gammaOutput = true; renderer.gammaFactor = 2.2; renderer.shadowMap.enabled = true; // 将Three.js渲染器添加到Cesium场景中 var csRenderer = new THREE.CSS3DRenderer(); csRenderer.setSize(viewer.canvas.clientWidth, viewer.canvas.clientHeight); csRenderer.domElement.style.position = "absolute"; csRenderer.domElement.style.top = 0; document.getElementById("cesiumContainer").appendChild(csRenderer.domElement); // 创建Three.js相机并将其添加到Cesium场景中 var camera = new THREE.PerspectiveCamera( 45, viewer.canvas.clientWidth / viewer.canvas.clientHeight, 0.1, 1000 ); var csCamera = new THREE.PerspectiveCamera( 45, viewer.canvas.clientWidth / viewer.canvas.clientHeight, 0.1, 1000 ); viewer.scene.primitives.add(new Cesium.Primitive({})); // 创建Three.js灯光并将其添加到Cesium场景中 var light = new THREE.DirectionalLight(0xffffff, 1); light.position.set(0, 1, 1); scene.add(light); // 加载模型 var loader = new THREE.GLTFLoader(); loader.load( "models/model.gltf", function (gltf) { // 获取模型并将其添加到Three.js场景中 var model = gltf.scene; model.scale.set(0.5, 0.5, 0.5); scene.add(model); // 将模型添加到Cesium场景中 var csModel = new THREE.CSS3DObject(model); csModel.position.set(0, 0, 0); csRenderer.render(scene, camera); viewer.scene.primitives.add(csModel); // 监听Cesium相机变化并更新Three.js相机 viewer.camera.changed.addEventListener(function () { camera.position.copy(viewer.camera.position); camera.position.y += 15; camera.lookAt(scene.position); renderer.render(scene, camera); csCamera.position.copy(viewer.camera.position); csCamera.position.y += 15; csCamera.lookAt(scene.position); csRenderer.render(scene, csCamera); }); }, undefined, function (error) { console.error(error); } ); ``` 这段代码首先创建了一个Cesium Viewer,然后创建了一个Three.js场景和一个Three.js渲染器。接着将Three.js渲染器添加到Cesium场景中,并创建了一个Three.js相机并将其添加到Cesium场景中。然后创建了一个Three.js灯光并将其添加到Cesium场景中。最后加载了一个模型,并将其添加到Three.js场景中和Cesium场景中。监听Cesium相机的变化,并更新了Three.js相机的位置和方向。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值