Cesium三维地图开发入门:从零构建你的第一个WebGIS应用

1次阅读
没有评论

共计 4835 个字符,预计需要花费 13 分钟才能阅读完成。

image.webp

技术背景

Cesium 是一个开源的 JavaScript 库,专门用于构建高性能的三维地理可视化应用。它基于 WebGL 技术,可以在浏览器中流畅渲染大规模的三维地形、影像和矢量数据。Cesium 的优势在于:

Cesium 三维地图开发入门:从零构建你的第一个 WebGIS 应用

  • 支持全球范围的高精度地形和影像数据
  • 提供丰富的 API 用于创建和操作三维实体
  • 跨平台,无需插件,纯浏览器运行
  • 开源且社区活跃,文档完善

典型应用场景包括:

  • 智慧城市数字孪生
  • 军事模拟与演练
  • 气象数据可视化
  • 自然资源管理

环境准备

  1. 安装 Node.js(建议使用 LTS 版本)

    # 检查安装是否成功
    node -v
    npm -v

  2. 创建项目目录并初始化

    mkdir cesium-demo && cd cesium-demo
    npm init -y

  3. 安装 Cesium

    npm install cesium

  4. 创建基础 HTML 结构

    <!-- index.html -->
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8">
      <title>Cesium Demo</title>
      <script src="node_modules/cesium/Build/Cesium/Cesium.js"></script>
      <link href="node_modules/cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
      <style>
        html, body, #cesiumContainer { 
          width: 100%; 
          height: 100%; 
          margin: 0; 
          padding: 0; 
          overflow: hidden; 
        }
      </style>
    </head>
    <body>
      <div id="cesiumContainer"></div>
      <script src="app.js"></script>
    </body>
    </html>

核心实现

Viewer 初始化

在 app.js 中添加以下代码:

// 设置 Cesium ion 访问令牌(需注册获取)Cesium.Ion.defaultAccessToken = 'your_access_token';

// 初始化 Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
  baseLayerPicker: true,  // 显示底图选择器
  terrainProvider: Cesium.createWorldTerrain(),  // 使用 Cesium World Terrain
  timeline: false,  // 隐藏时间轴
  animation: false,  // 隐藏动画控件
  sceneModePicker: false,  // 隐藏场景模式选择器
  navigationHelpButton: false,  // 隐藏导航帮助按钮
  infoBox: false,  // 隐藏信息框
  selectionIndicator: false,  // 隐藏选择指示器
});

// 移除默认的版权信息(仅用于演示,生产环境请保留)viewer.cesiumWidget.creditContainer.style.display = 'none';

地形数据加载

Cesium 提供了多种地形数据源:

  1. Cesium World Terrain:高精度全球地形
  2. Ellipsoid Terrain:简单的椭球体地形
  3. 自定义地形服务
// 使用 Cesium World Terrain(需要 access token)viewer.terrainProvider = Cesium.createWorldTerrain({
  requestWaterMask: true,  // 请求水面效果
  requestVertexNormals: true  // 请求顶点法线用于光照
});

// 使用 Ellipsoid Terrain(无高度数据)// viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();

实体添加

Cesium 提供了两种主要的实体添加方式:

  1. Primitive:底层 API,性能更高,适合大量静态几何体
  2. Entity:高层 API,更易用,支持动态属性

添加点实体(Entity 方式)

// 添加一个点
const pointEntity = viewer.entities.add({
  name: '示例点',
  position: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 100),
  point: {
    pixelSize: 10,
    color: Cesium.Color.RED,
    outlineColor: Cesium.Color.WHITE,
    outlineWidth: 2
  }
});

// 飞向该点
viewer.flyTo(pointEntity);

添加多边形(Primitive 方式)

const polygon = new Cesium.Primitive({
  geometryInstances: new Cesium.GeometryInstance({
    geometry: new Cesium.PolygonGeometry({
      polygonHierarchy: new Cesium.PolygonHierarchy(
        Cesium.Cartesian3.fromDegreesArray([
          116.3, 39.8,
          116.5, 39.8,
          116.5, 40.0,
          116.3, 40.0
        ])
      ),
      height: 0
    }),
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE.withAlpha(0.5)
      )
    }
  }),
  appearance: new Cesium.PerInstanceColorAppearance({
    flat: true,
    translucent: true
  })
});

viewer.scene.primitives.add(polygon);

完整代码示例

以下是一个完整的简单三维地图 demo:

// app.js
Cesium.Ion.defaultAccessToken = 'your_access_token';

const viewer = new Cesium.Viewer('cesiumContainer', {
  baseLayerPicker: true,
  terrainProvider: Cesium.createWorldTerrain({
    requestWaterMask: true,
    requestVertexNormals: true
  }),
  timeline: false,
  animation: false
});

// 添加北京的点
const beijing = viewer.entities.add({
  name: '北京',
  position: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 0),
  point: {
    pixelSize: 15,
    color: Cesium.Color.RED,
    outlineColor: Cesium.Color.WHITE,
    outlineWidth: 2
  },
  label: {
    text: '北京',
    font: '14pt sans-serif',
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth: 2,
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    pixelOffset: new Cesium.Cartesian2(0, -15)
  }
});

// 添加上海的点
const shanghai = viewer.entities.add({
  name: '上海',
  position: Cesium.Cartesian3.fromDegrees(121.47, 31.23, 0),
  point: {
    pixelSize: 15,
    color: Cesium.Color.BLUE,
    outlineColor: Cesium.Color.WHITE,
    outlineWidth: 2
  },
  label: {
    text: '上海',
    font: '14pt sans-serif',
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth: 2,
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    pixelOffset: new Cesium.Cartesian2(0, -15)
  }
});

// 添加连接线
const line = viewer.entities.add({
  name: '北京 - 上海连线',
  polyline: {
    positions: [Cesium.Cartesian3.fromDegrees(116.4, 39.9),
      Cesium.Cartesian3.fromDegrees(121.47, 31.23)
    ],
    width: 3,
    material: new Cesium.PolylineGlowMaterialProperty({
      glowPower: 0.2,
      color: Cesium.Color.YELLOW
    })
  }
});

// 初始视角
viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(118.0, 35.0, 3000000),
  orientation: {heading: Cesium.Math.toRadians(0),
    pitch: Cesium.Math.toRadians(-45),
    roll: 0.0
  }
});

性能优化

  1. 内存管理
  2. 及时销毁不再使用的实体

    viewer.entities.remove(entity);

  3. 相机控制

  4. 使用 flyTo 而不是 setView 避免突兀的视角切换
  5. 限制相机高度和移动速度

  6. LOD(细节层次)

  7. 为复杂模型设置 LOD
  8. 使用 Cesium3DTileset 加载大规模 3D 数据

  9. 帧率监控

    viewer.scene.postRender.addEventListener(function() {
      const fps = viewer.clock.multiplier / viewer.clock._lastSystemTime;
      console.log(` 当前帧率: ${fps.toFixed(1)}`);
    });

避坑指南

  1. 跨域问题
  2. 开发时使用本地服务器(如 http-server)
  3. 生产环境配置 CORS

  4. Token 配置

  5. 记得设置 Cesium ion access token
  6. 免费账户有配额限制

  7. 坐标系转换

  8. Cesium 使用 WGS84 坐标系
  9. 常用转换方法:
    // 经纬度转笛卡尔坐标
    const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
    
    // 笛卡尔坐标转经纬度
    const cartographic = Cesium.Cartographic.fromCartesian(position);
    const longitude = Cesium.Math.toDegrees(cartographic.longitude);
    const latitude = Cesium.Math.toDegrees(cartographic.latitude);

进阶建议

  1. 学习路径建议:
  2. 掌握基础 API 后学习 3D Tiles
  3. 了解 Cesium 的着色器系统
  4. 研究自定义地形和影像服务

  5. 扩展功能方向:

  6. 集成第三方 GIS 数据(GeoJSON, WMS 等)
  7. 实现地形分析功能(可视域分析、剖面分析等)
  8. 开发自定义着色器效果

思考与实践

  1. 尝试修改示例代码,添加你所在城市的标记
  2. 研究如何加载本地地形数据(如 DEM 数据)
  3. 探索 Cesium 的时间动态功能,如随时间变化的轨迹显示

通过这篇教程,你应该已经掌握了 Cesium 的基础使用方法。三维地理可视化是一个广阔的领域,Cesium 提供了强大的工具集,期待看到你创建出精彩的应用!

正文完
 0
评论(没有评论)