Cesium实现“悬浮岛”式,三维立体的行政区划

在 WebGIS 可视化项目中,我们经常遇到一类高频需求,重点展示特定行政区划,并隐藏全球其他无关区域

本文将深入探讨如何利用 Cesium 原生 API ClippingPolygon 实现真正的地形反向裁剪最终构建一个具有科技感的沉浸式地图场景。

1. 核心技术方案概览

实现该效果主要包含三个关键技术点:

  1. 地形反向裁剪(Inverse Clipping) :利用 ClippingPolygonCollection 将非目标区域的地形完全剔除,实现"挖空"效果。

  2. 环境透明化(Scene Translucency):配置 Viewer 场景属性,使地球球体透明,从而露出底层的背景。

  3. 深度检测与遮挡(Depth Testing & Occlusion):开启深度测试,确保地下的边界墙体被地表正确遮挡,消除视觉杂乱。


2. 场景初始化与透明化处理

为了让地球"悬浮"在我们的网页背景(CSS Background)之上,首先需要剥离 Cesium 默认的天空盒、大气层以及地球底色。

javascript 复制代码
// 初始化 Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
  // ...基础配置
  contextOptions: {
    requestWebgl2: true // 建议开启 WebGL2 以获得更好的性能和渲染效果
  }
});

// 核心配置:移除默认环境元素
viewer.scene.skyBox.show = false;       // 隐藏天空盒
viewer.scene.sun.show = false;          // 隐藏太阳
viewer.scene.moon.show = false;         // 隐藏月亮
viewer.scene.skyAtmosphere.show = false;// 隐藏大气层

// 开启地球透明支持
viewer.scene.globe.translucency.enabled = true; 
viewer.scene.globe.baseColor = Cesium.Color.TRANSPARENT; // 地球基底颜色设为全透
viewer.scene.backgroundColor = Cesium.Color.TRANSPARENT; // 场景背景色设为全透

3. 实现地形反向裁剪 (Inverse Clipping)

Cesium 的 ClippingPolygon 类允许开发者定义裁剪区域。默认情况下,裁剪是"保留外部,剔除内部"。但在本案例中,我们需要保留中国区域,剔除世界其他区域,因此需要启用 反向裁剪(Inverse)

3.1 数据转换:GeoJSON 转 ClippingPolygon

我们需要解析 GeoJSON 数据,提取每个省份多边形的边界坐标(Positions),并实例化为 ClippingPolygon 对象。

javascript 复制代码
async function applyGlobalClipping(geojsonData) {
  const dataSource = await Cesium.GeoJsonDataSource.load(geojsonData);
  const entities = dataSource.entities.values;
  const clipPolygons = [];

  entities.forEach(entity => {
    if (entity.polygon) {
      const hierarchy = entity.polygon.hierarchy.getValue();
      // 将边界坐标转换为 ClippingPolygon
      clipPolygons.push(new Cesium.ClippingPolygon({
        positions: hierarchy.positions
      }));
    }
  });

  // 应用裁剪集合
  viewer.scene.globe.clippingPolygons = new Cesium.ClippingPolygonCollection({
    polygons: clipPolygons,
    enabled: true,
    inverse: true // 【关键】设置为 true,表示保留多边形内部,裁剪外部
  });
}

此时地球上除了中国区域的地形和影像,其余部分已被完全剔除,露出了网页底部的 DOM 背景。

4. 边界渲染与深度冲突解决

为了增强视觉效果,通常会沿着边界生成发光线条(Polyline)和向下延伸的光墙(Wall)。然而,直接添加 Wall 实体会导致一个严重的渲染问题,由于墙体延伸至地下深处,在某些视角下,地下的墙体会透过地表显示出来,导致画面杂乱无章。

4.1 开启深度测试 (Depth Test)

这是解决"透视"问题的核心。默认情况下,Cesium 可能不会对地形以下的物体进行严格的遮挡计算。我们需要强制开启针对地形的深度检测。

javascript 复制代码
// 【核心代码】开启地形深度检测
// 作用:如果一个像素点位于地形表面之下,则不进行绘制。
// 这确保了我们向下延伸的 Wall 只有露出地表的部分可见,内部复杂的网格被完美遮挡。
viewer.scene.globe.depthTestAgainstTerrain = true;

4.2 构建渐变光墙与发光边界

在解决了遮挡关系后,我们可以放心地添加视觉元素。

  • 发光边界 :使用 PolylineGlowMaterialProperty 实现流光效果。

  • 渐变光墙 :使用 WallGraphics 配合动态生成的 Canvas 渐变纹理,实现从地表向下渐隐的科技感帷幕。

javascript 复制代码
// 示例:在遍历 GeoJSON 实体时同步添加视觉边界
viewer.entities.add({
  polyline: {
    positions: positions,
    width: 3,
    material: new Cesium.PolylineGlowMaterialProperty({
      glowPower: 0.2,
      color: Cesium.Color.CYAN.withAlpha(0.8)
    }),
    clampToGround: true // 贴地线
  }
});

viewer.entities.add({
  wall: {
    positions: positions,
    // 设置墙体高度范围:从地下 500km 到 地表 0m
    minimumHeights: new Array(positions.length).fill(-500000),
    maximumHeights: new Array(positions.length).fill(0),
    material: new Cesium.ImageMaterialProperty({
      image: createGradientCanvas(), // 辅助函数生成的线性渐变 Canvas
      transparent: true
    })
  }
});

注意事项ClippingPolygon 的性能开销与多边形的顶点数量及多边形个数成正比。如果加载过于破碎的行政区划(如包含大量岛屿的详细数据),可能会导致帧率下降或 WebGL 上下文丢失。在生产环境中,建议对 GeoJSON 进行简化处理,仅使用外轮廓数据进行裁剪。

关于作者 & 合作

感谢阅读!我是专注于 WebGIS 前端可视化 的独立开发者。

如果你的团队正在做 智慧城市、数字孪生、流域监测 等项目,却苦于没有专业的 GIS 前端支持,或者需要快速输出高质量的 2D/3D 地图效果,欢迎联系我。

  • 核心技术栈: Vue3 / React + Mapbox / Cesium / Three.js + Springboot/FastAPI + PostgreSQL/PostGIS

  • 服务范围: WebGIS 项目整包开发、复杂地图交互实现。

目前已成立个人工作室、公司。可公对公,可开发票。

相比于找昂贵的大型外包公司,我能提供更灵活的沟通更高的性价比。无论是几十个页面的管理大屏,还是一个核心的地图功能模块,我都会像对待自己的产品一样打磨细节。

手头目前有档期,欢迎各位老板、PM 砸单。首单合作,价格好商量,保质保量交朋友!

相关推荐
计算机学姐2 小时前
基于SpringBoot的汽车租赁系统【个性化推荐算法+数据可视化统计】
java·vue.js·spring boot·后端·spring·汽车·推荐算法
不一样的少年_2 小时前
产品催: 1 天优化 Vue 官网 SEO?我用这个插件半天搞定(不重构 Nuxt)
前端·javascript·vue.js
-dcr2 小时前
50.智能体
前端·javascript·人工智能·ai·easyui
BingoGo2 小时前
免费可商用商业级管理后台 CatchAdmin V5 正式发布 插件化与开发效率的全面提升
vue.js·后端·php
哈__2 小时前
React Native 鸿蒙跨平台开发:LayoutAnimation 实现鸿蒙端页面切换的淡入淡出过渡动画
javascript·react native·react.js
我要敲一万行2 小时前
前端文件上传
前端·javascript
要加油哦~2 小时前
算法 | 整理数据结构 | 算法题中,JS 容器的选择
前端·javascript·算法
一 乐11 小时前
婚纱摄影网站|基于ssm + vue婚纱摄影网站系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端
北辰alk12 小时前
Vue 模板引擎深度解析:基于 HTML 的声明式渲染
vue.js