十年前我刚接触WebGIS时,大多数项目还停留在二维地图展示阶段。那时候用ArcGIS Server发布几个WMS服务,配合OpenLayers或者Leaflet就能完成一个基础项目。但随着智慧城市、数字孪生等概念的兴起,单纯二维地图已经无法满足需求。
去年我参与了一个智慧园区项目,客户明确提出要三维可视化需求。他们不仅需要看到园区建筑的外观,还要能查看内部管线分布、实时监控设备状态。这就是典型的三维地理应用场景——将空间数据从平面扩展到立体维度,实现更丰富的交互和分析功能。
全栈开发在这里显得尤为重要。因为三维地理应用涉及:
我见过不少团队把这三个部分交给不同小组开发,结果联调时各种接口对不上。所以推荐从项目开始就采用全栈思路,一个人或一个小团队负责完整功能链路。
Vue 2 + Cesium是我推荐的主流组合。Vue 3虽然新,但配套生态还不够成熟。去年我用Vue 3 + Cesium 1.95就遇到过Webpack打包问题,最后不得不回退到Vue 2。
具体版本建议:
bash复制npm install vue@2.6.14
npm install cesium@1.95.0
重要提示:不要盲目追求最新版!Cesium 1.96+需要额外配置WebAssembly加载器,对新手很不友好。1.95版经过大量项目验证,稳定性最好。
Spring Boot + MyBatis Plus组合提供了快速开发能力。对于空间数据操作,建议添加GeoTools依赖:
xml复制<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>25.0</version>
</dependency>
数据库方面,MySQL 8.0开始支持空间函数,但如果是专业GIS项目,PostgreSQL+PostGIS组合更强大。我做过性能对比,同样的空间查询,PostGIS比MySQL快3-5倍。
Geoserver和Cesium ion是两种主流方案:
小型项目可以用Cesium自带的STK地形服务(免费但有配额限制):
javascript复制const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain()
});
Cesium在Vue中的集成需要特殊配置。首先修改vue.config.js:
javascript复制const path = require('path');
module.exports = {
configureWebpack: {
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: 'node_modules/cesium/Build/Cesium/Workers', to: 'Workers' },
{ from: 'node_modules/cesium/Build/Cesium/ThirdParty', to: 'ThirdParty' },
{ from: 'node_modules/cesium/Build/Cesium/Assets', to: 'Assets' }
]
})
]
}
};
常见坑点:
Spring Boot集成GeoTools时要注意JTS版本冲突。推荐配置:
java复制@Configuration
public class GeoConfig {
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
// 解决三维模型跨域问题
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new CorsFilter());
bean.addUrlPatterns("/*");
return bean;
}
}
空间查询示例(查找5公里内的POI):
java复制@Select("SELECT * FROM poi WHERE ST_Distance(location, ST_GeomFromText(#{point}, 4326)) < 5000")
List<Poi> findNearbyPois(@Param("point") String wktPoint);
对于大型三维场景,建议采用3D Tiles规范组织模型。我总结的最佳实践是:
javascript复制const tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: './tileset/tileset.json',
progressiveResolution: true
})
);
在三维场景中实现缓冲区分析:
javascript复制// 创建缓冲区几何体
const buffer = turf.buffer(selectedFeature.geometry, 500, {units: 'meters'});
// 添加到场景
viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray(
buffer.geometry.coordinates[0].flatMap(p => [p[0], p[1]])
),
material: Cesium.Color.RED.withAlpha(0.5)
}
});
javascript复制viewer.scene.lodBias = 2.0; // 值越大细节保留越多
javascript复制const worker = new Worker('./workers/analysis.js');
worker.postMessage({type: 'buffer', data: points});
javascript复制viewer.entities.removeById('tempEntity');
三维项目常见的跨域问题可以通过Nginx反向代理解决:
nginx复制location /geoserver {
proxy_pass http://localhost:8080/geoserver;
add_header 'Access-Control-Allow-Origin' '*';
}
将Cesium静态文件部署到CDN可以显著提升加载速度。我的部署目录结构通常是这样:
code复制/static
/cesium
/Workers
/Assets
/ThirdParty
/tileset
/model1
tileset.json
/*.b3dm
推荐使用Sentry捕获前端错误,特别是Cesium的WebGL上下文丢失问题:
javascript复制import * as Sentry from '@sentry/vue';
Sentry.init({
dsn: 'your_dsn',
integrations: [new Sentry.Integrations.Cesium()]
});
去年完成的智慧港口项目中,我们实现了:
关键技术突破点:
性能指标:
javascript复制const viewer = new Cesium.Viewer('cesiumContainer');
viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 10000)});
坐标系不匹配是常见问题。解决方案:
javascript复制viewer.scene.globe.ellipsoid = Cesium.Ellipsoid.CGCS2000;
三维项目容易内存泄漏,建议:
掌握基础功能后,可以尝试:
最近我在研究Cesium for Unreal,将GIS数据导入游戏引擎可以实现更逼真的效果。比如用Nanite技术渲染超大规模地形,用Lumen实现动态全局光照。这可能是下一代三维GIS的发展方向。