Cesium 速通

前言:cesium 是基于 WebGL 的 js 库,API 可以参考 cesium 官网,本文主要是讲 cesium 在 vue3 中的使用。创建 Vue3 + Vite 项目的流程就不做演示了,直接开搞。

1. 注册 cesium

要使用 cesium API 就需要 cesium Token,点击注册,可以使用谷歌或者 github 的账号注册。注册后到 Access Tokens 目录下,复制 token 备用。

2. 安装 

安装 cesium@1.99 版本的依赖,因为最新版本的 cesium ,可能文档没更新, API 对不上。 

npm install cesium@1.99 vite-plugin-cesium
# or
pnpm add cesium@1.99 vite-plugin-cesium
# or
yarn add cesium@1.99 vite-plugin-cesium

3. 引入

在 vite.config.js 中引入 cesium

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import cesium from "vite-plugin-cesium";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), cesium()],
});

4. 使用

4.1 基础小地球

编写 App.vue 默认是谷歌的影像图层。

<script setup>
  import { onMounted } from "vue";
  import * as Cesium from "cesium";

  let token = "your token";

  onMounted(() => {
    Cesium.Ion.defaultAccessToken = token;
    new Cesium.Viewer("contain");
  });
</script>

<template>
  <div id="contain"></div>
</template>

<style>
  body {
    margin: 0;
    padding: 0;
  }
  #contain {
    width: 100vw;
    height: 100vh;
  }
</style>

4.2 自定义影像图层

自定义 ArcGIS 影像图层

onMounted(() => {
  const esri = new Cesium.ArcGisMapServerImageryProvider({
    url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer", // 图层地址
    enablePickFeatures: false, // 无需与服务器通信
  });

  const viewer = new Cesium.Viewer("contain", {
    imageryProvider: esri, // 替换默认影像图层
    infoBox: false, // 右侧信息框
    selectionIndicator: false, // 选中状态隐藏
  });
});

4.3 地形图层

默认地图是平面的,没有地形图层。可以通过如下配置打开地图和水面特效。但是一般没必要可以不开,因为会损耗我们电脑 GPU,就像打游戏特效开满一样。 

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {
    // 地形特效
    terrainProvider: Cesium.createWorldTerrain({
      requestWaterMask: true, // 水面特效
    }),
  });
});

4.4 控件

隐藏界面的控件,使界面看着干净整洁,因为我们交付给客户的时候,也不会让客户看到这些控件。 

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {
    timeline: false, // 时间轴控件
    animation: false, // 动画控件
    geocoder: false, // 搜索按钮
    homeButton: false, // 主页按钮
    sceneModePicker: false, // 投影方式按钮
    baseLayerPicker: false, // 图层选择按钮
    navigationHelpButton: false, // 帮助手势按钮
    fullscreenButton: false, // 全屏按钮
  });
});

 4.5 坐标转换

在 Cesium 中,只对笛卡尔坐标有效,所以需要我们将经纬度转换为笛卡尔坐标。

4.5.1 经纬度转笛卡尔坐标

onMounted(() => {
  const cartesian = Cesium.Cartesian3.fromDegrees(110, 20, 20); // 经度 纬度 高度
});

4.5.2 笛卡尔坐标转弧度

onMounted(() => {
  const graphic = Cesium.Cartographic.fromCartesian(cartesian);
});

4.5.3 弧度转经纬度

onMounted(() => {
  const lon = Cesium.Math.toDegrees(graphic.longitude);
  const lat = Cesium.Math.toDegrees(graphic.latitude);
  const height = Cesium.Math.toDegrees(graphic.height);
});

4.6 相机

相当于我们视线的位置

4.6.1 设置目的地

视觉角度也就是相机位置

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const position = Cesium.Cartesian3.fromDegrees(110, 20, 100000);
  viewer.camera.setView({
    destination: position, // 目的地
    // 视角
    orientation: {
      heading: Cesium.Math.toRadians(0), // 左右
      pitch: Cesium.Math.toRadians(-90), // 上下
      roll: Cesium.Math.toRadians(0), // 倾斜
    },
  });
});

4.6.2 飞行动画 

视线到达目的地有个过渡动画

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const position = Cesium.Cartesian3.fromDegrees(110, 20, 100000);
  viewer.camera.flyTo({
    destination: position, // 目的地
    duration: 3, // 飞行时长 3 秒
    // 视角
    orientation: {
      heading: Cesium.Math.toRadians(0), // 左右
      pitch: Cesium.Math.toRadians(-90), // 上下
      roll: Cesium.Math.toRadians(0), // 倾斜
    },
  });
});

cesium 视角过渡

4.6.3 视角锁定

无论怎么转动地球,视角中心在固定位置

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const position = Cesium.Cartesian3.fromDegrees(110, 20);
  viewer.camera.lookAt(
    position,
    new Cesium.HeadingPitchRange(
      Cesium.Math.toRadians(0),
      Cesium.Math.toRadians(-90),
      20000
    )
  );
});

4.7 entity 实体

4.7.1 设置点

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});
  const point = viewer.entities.add({
    id: "point",
    position: Cesium.Cartesian3.fromDegrees(121, 30), // 位置
    point: {
      pixelSize: 20, // 像素大小
      color: Cesium.Color.BLUE, // 颜色
    },
  });
  viewer.zoomTo(point); // 跳转到点位置
});

4.7.2 设置标注

也是广告牌,是图片地址

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const point = viewer.entities.add({
    id: "billboard",
    position: Cesium.Cartesian3.fromDegrees(120, 30, 10),
    billboard: {
      image: "/src/assets/cricel.png", // 图片地址
      scale: 1.2, // 缩放
      color: Cesium.Color.YELLOW, // 改变图片颜色
    },
  });
  viewer.zoomTo(point);
});

 

4.7.3 设置文字 

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const label = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(120, 30),
    label: {
      text: "Cesium", // 内容
      fillColor: Cesium.Color.YELLOWGREEN, // 字体颜色
      showBackground: true, // 是否有背景颜色
      backgroundColor: new Cesium.Color(255, 255, 0), // 背景颜色
    },
  });
  viewer.zoomTo(label);
});

4.7.4 设置线 

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const polyline = viewer.entities.add({
    polyline: {
      positions: Cesium.Cartesian3.fromDegreesArray([
        120, 20, 121, 20, 121, 20.5,
      ]), // 线由点构成
      width: 10, // 线宽度
      material: Cesium.Color.BLACK, // 线颜色
    },
  });
  viewer.zoomTo(polyline);
});

4.7.5 设置面

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const polygon = viewer.entities.add({
    polygon: {
      // 面由点构成
      hierarchy: {
        positions: Cesium.Cartesian3.fromDegreesArray([
          100, 20, 101, 20, 101, 20.5,
        ]),
      },
      material: Cesium.Color.BLUE, // 面颜色
      height: 10000, // 面距离地球高度
      extrudedHeight: 20000, // 面被拉升的高度
      outline: true, // 是否由外边线
      outlineColor: Cesium.Color.YELLOW, // 外边线颜色
      fill: true, // 是否填充立体颜色
    },
  });
  viewer.zoomTo(polygon);
});

4.7.6 设置立方体

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const box = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(119, 30, 3000), // 经度 维度 高度
    box: {
      dimensions: new Cesium.Cartesian3(2000, 1000, 3000), // 长 宽 高
      material: Cesium.Color.BLUEVIOLET,
    },
  });
  viewer.zoomTo(box);
});

4.7.7 椭圆

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const ellipse = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(118, 30),
    ellipse: {
      semiMajorAxis: 500, // 半长轴
      semiMinorAxis: 300, // 半短轴
      material: Cesium.Color.BLUE, // 填充颜色
      rotation: Math.PI / 2,
    },
  });
  viewer.zoomTo(ellipse);
});

4.7.8 矩形/立方体

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const rectangle = viewer.entities.add({
    rectangle: {
      coordinates: Cesium.Rectangle.fromDegrees(120, 40, 123, 45), // 左下和右上的坐标
      extrudedHeight: 30000, // 拉伸高度
      material: "/src/assets/img.jpg", // 立方体上图片
    },
  });
  viewer.zoomTo(rectangle);
});

4.7.9 组合

可以对点、线、面等进行组合

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const eneity = viewer.entities.add({
    position: new Cesium.Cartesian3.fromDegrees(120, 30, 100), // 经度 维度 高度
    billboard: {
      image: "/src/assets/cricel.png",
      scale: 1.2,
      color: Cesium.Color.ORANGE,
    },
    label: {
      text: "皇冠小区",
      font: "13px",
      fillColor: Cesium.Color.WHITE,
      pixelOffset: new Cesium.Cartesian2(0, -40), // 水平/垂直 偏移量
    },
    polyline: {
      positions: Cesium.Cartesian3.fromDegreesArrayHeights([
        120, 30, 0, 120, 30, 100,
      ]), // 垂直线是由3D点构成
      material: Cesium.Color.AQUA,
    },
  });
  viewer.zoomTo(eneity);
});

4.7.10 删除实体

entityName 为复制的实体变量,entityId 为设置的实体 ID

viewer.entities.remove(entityName); // 删除指定实体

viewer.entities.removeAll(); // 删除全部实体

viewer.entities.removeById(entityId); // 删除指定ID的实体

4.8 动态实线

通过 Cesium.CallbackProperty (callback, isConstant) 函数视线,isConstant 为 false 有动态效果。

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const moveLine = viewer.entities.add({
    polyline: {
      positions: new Cesium.CallbackProperty(() => {
        num += 0.005;
        lon = 120 + num;
        lat = 30 + num;
        if (lon < 125) {
          return Cesium.Cartesian3.fromDegreesArray([120, 30, lon, lat]);
        } else {
          moveLine.polyline.positions = Cesium.Cartesian3.fromDegreesArray([
            120, 30, 125, 35,
          ]);
        }
      }, false),
      width: 5,
      material: Cesium.Color.AQUA,
    },
  });
});

cesium

5. DataSources 数据加载

加载 GeoJson 数据,参考 Turf.js 中文网

5.1 安装 turf

npm install @turf/turf
# or
yarn add @turf/turf
# or
pnpm add @turf/turf

5.2 在组件使用

import { onMounted } from "vue";
import * as turf from "@turf/turf";

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const linestring = turf.lineString([
    [-24, 63],
    [-23, 60],
    [-25, 65],
    [-20, 69],
  ]); // 线由点构成
  const pro = Cesium.GeoJsonDataSource.load(linestring); // 将 linestring 加到 Cesium
  pro.then((res) => {
    const entity = res.entities.values[0]; // 在回调函数中拿到 entity
    viewer.entities.add(entity);
    viewer.zoomTo(entity);
  });
});

5.3 多条线

可以直接通过 dataSources 加入 Cesium

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const multiLine = turf.multiLineString([
    [
      [0, 0],
      [3, 3],
    ],
    [
      [5, 5],
      [10, 10],
    ],
  ]); // 多条线由线数组构成
  Cesium.GeoJsonDataSource.load(multiLine).then((res) => {
    viewer.dataSources.add(res);
  });

  // viewer.dataSources.remove() // 清除 dataSources
});

5.4 多边形

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const polygon = turf.polygon([
    [
      [-5, 52],
      [-4, 56],
      [-2, 51],
      [-7, 54],
      [-5, 52],
    ],
  ]); // polygon 首尾坐标要一致

  const pro = Cesium.GeoJsonDataSource.load(polygon);
  viewer.dataSources.add(pro);
  viewer.zoomTo(pro);
});

5.5 topoJson 数据

是 GeoJson 数据的一种

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  // 加载本地 topojson 数据
  const pro = Cesium.GeoJsonDataSource.load("/src/assets/topo.topojson");
  viewer.dataSources.add(pro);
  viewer.zoomTo(pro);
});

5.6 kml 数据

拿到 .kmz 数据,使用 KmlDataSource 加入数据

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const pro = Cesium.KmlDataSource.load("/src/assets/kmz.kmz");
  viewer.dataSources.add(pro);
  viewer.zoomTo(pro);
});

5.7 czml 数据

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const pro = Cesium.CzmlDataSource.load("/src/assets/czml.czml");
  viewer.dataSources.add(pro);
  viewer.zoomTo(pro);
});

6. 3D 瓦片

去资源库添加资源,在已添加资源处,可以查看用法。

加载 New York City 3D Buildings 

onMounted(() => {
  const viewer = new Cesium.Viewer("contain", {});

  const tileset = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
      url: Cesium.IonResource.fromAssetId(75343),
    })
  );
  viewer.flyTo(tileset);
});

  • 85
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yqcoder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值