cesium(二) 加载影像图层

1,077 阅读5分钟

1. 前言

本文中将先调整下相机视角,经纬度可以在谷歌地图中先找到对应的位置,然后右击,就能看到对应的经纬度的值,点击进行复制。复制的值是纬度和经度,注意下面需要赋值的顺序是经度和纬度,需要调换下顺序。在修改或者添加属性前,申请ion必不可少。在已经具备ion token的基础上,了解下切换底图的流程。然后再看看加载来自arcGisOnline的栅格影像是如何实现的。

2. 相机视角

先将地图调整到合适的视角。viewer.camera.setView(options)将视图跳转到options定义的位置信息中,options是一个对象,可以包含以下属性:

  • destination: (必需)相机的新位置,可以是一个 Cartesian3 坐标,表示经度、纬度和高度。例如:Cesium.Cartesian3.fromDegrees(longitude, latitude, height)

  • orientation: (可选)相机的朝向设置,包括:

    • heading: 相机的航向(以弧度为单位)。
    • pitch: 相机的俯仰(以弧度为单位)。
    • roll: 相机的滚转(以弧度为单位)。
  viewer.camera.setView({
    // 目的地
    destination: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 2000),
    // 飞行结束时的视角方向
    orientation: {
      // 水平方向的角度,以弧度表示
      heading: Cesium.Math.toRadians(0.0),
      // 垂直方向的角度,以弧度表示
      pitch: Cesium.Math.toRadians(-90.0),
      // 围绕垂直轴的旋转角度,以弧度表示
      roll: 0.0,
    },
  });

如果需要从一个视角跟踪到另一个视角,可使用viewer.camera.flyTo(options),除了可以使用上述options选项之外,增加的可选项属性:

  • duration: (可选)相机移动到新位置所需的时间(以秒为单位),如果未指定,则相机立即跳转到新位置。
  • complete: (可选)一个回调函数,在相机移动完成后调用。
  • cancelable: (可选)布尔值,指示飞行是否可以被取消。默认为 true
  viewer.camera.flyTo({
    // 目的地
    destination: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 2000),
    // 视角方向
    orientation: {
      // 水平方向的角度,以弧度表示
      heading: Cesium.Math.toRadians(0.0),
      // 垂直方向的角度,以弧度表示
      pitch: Cesium.Math.toRadians(-40.0),
      // 围绕垂直轴的旋转角度,以弧度表示
      roll: 0.0,
    },
    duration: 4.0, // 飞行时间
    complete: () => {
      // 飞行完成后的回调函数
      console.log("相机📷已经到达目的地✈️");
    },
  });

viewer.camera.flyTo(options)通过设置目标位置、朝向、持续时间和回调函数,您可以灵活地控制相机的飞行行为,从而增强应用的交互性和用户体验。

3. 申请ion

在我们使用Cesium的过程中,如果没有申请ion,同时没有自己的数据源用的cesium提供的数据源,viewer的底部常常会提示一行小的英文字母。大意就是需要申请access token。 注册获取cesium-tocken入口

image.png 在创建Cesium Viewer的时候,将access token填为自己的access token即可。

Cesium.Ion.defaultAccessToken = '<YOUR ACCESS TOKEN HERE>';

4. 切换图层

Cesium应用程序中一个关键元素是Imagery(图层)。瓦片图集合根据不同的投影方式映射到虚拟的三维数字地球表面。依赖于相机指向地表的方向和距离,Cesium会去请求和渲染不同层级的图层详细信息。Cesium默认展示的底图是Bing Maps Aerial,这个图层被打包进Viewer中用于演示。如果要切换其他图层,需要完成ion的申请,并添加该图层的权限。

例如点开视图中地图切换控件按钮,选择Sentinel-2

image.png

提示报错信息:RequestErrorEvent {statusCode: 404, response: '{"code":"ResourceNotFound","message":"Resource Not…UjcyWX_Jd63Vx877udZE&assetRegion=ap-northeast-1"}', responseHeaders: {…}}

这是因为没有设置权限。需要到Cesium ion页面允许Sentinel-2图层的权限,找到该图层并点击添加。如下图所示:

image.png

添加成功后,在上述页面的My Assets中,可以看到权限添加成功的内容。查看对应的assetId,添加到展示的图层中。

const layer = viewer.imageryLayers.addImageryProvider(
    await Cesium.IonImageryProvider.fromAssetId(3954)
  );

视图打开后将展示Sentinel-2图层。

5. ArcGIS 服务器上的地图影像集成

5.1 常用的 ArcGIS Online 图层链接

这里我们使用ArcGIS Online平台上的地图服务。以下是一些常用的 ArcGIS Online 图层链接和服务类型。

  1. 世界影像图
https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer

2. 世界街道图

https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer

3. 世界地形图

https://services.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer

4. 世界灰度影像图

https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Gray/MapServer

5.2 ArcGisOnline影像加载

Cesium提供ArcGisMapServerImageryProvider类用于从ArcGIS Server获取影像数据,将服务器上的地图影像集成到cesium中,以便进行3D可视化和分析。cesium.com-ArcGisMapServerImageryProvider

官网上提供了示例代码如下:

// Create an imagery provider from the url directly
const esri = await Cesium.ArcGisMapServerImageryProvider.fromUrl(
  "https://ibasemaps-api.arcgis.com/arcgis/rest/services/World_Imagery/MapServer", {
    token: "<ArcGIS Access Token>"
});

使用 ArcGIS Online 服务时,是否需要 Access Token 取决于您访问的服务类型,以上提供的是公共的 ArcGIS Online 服务,不需要Access Token。

我们从其中挑选一个World_Street_Map作为案例来使用:

  const esri = await Cesium.ArcGisMapServerImageryProvider.fromUrl( "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"
  );

这里注意下,有些教程踩坑了,八青妹踩坑的demo案例如下:

var viewer = new Cesium.Viewer('cesiumContainer', {
    imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
        url : '//services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
    }),
    baseLayerPicker : false
});

如果使用这种老旧的方法,是显示不了地图影像的。显示的是一个水灵灵的蓝色球体。

image.png

在上述切换图层中的案例代码中是使用viewer.imageryLayers.addImageryProvider()来进行切换的,那我们打印下该imagerLayers看看,里面究竟是啥

 const viewer = new Cesium.Viewer("cesiumContainer", {
    infoBox: false,
  });
  const imageLayers = viewer.imageryLayers;
  console.log(imageLayers);

image.png

所以我们这里将这个默认展示的图层清空,然后添加arcgisOnline图层。代码如下:

import { onMounted } from "vue";
import * as Cesium from "cesium";
onMounted(async () => {
  Cesium.Ion.defaultAccessToken =
    "bulabulabulabula";//替换自己的ion token
  const esri = await Cesium.ArcGisMapServerImageryProvider.fromUrl(
    "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"
  );
  const viewer = new Cesium.Viewer("cesiumContainer", {
    infoBox: false,
  });
  const imageLayers = viewer.imageryLayers;
  imageLayers.remove(imageLayers.get(0));
  imageLayers.addImageryProvider(esri);
});

成功的效果图如下所示:

image.png

ps:如果不清空默认的图层,这个贴图覆盖不完整的。效果可以自行试试。

6. 总结

最后,我们将相机视角和arcGisOnline底图结合下看看。

image.png