从零实战!使用 Mars3D 快速构建水利监测 WebGIS 系统

从零实战!使用 Mars3D 快速构建水利监测 WebGIS 系统

前言

在智慧水利、数字孪生流域等项目的建设中,一个直观、高效的地理信息可视化平台至关重要。传统的 GIS 开发往往门槛较高,而 Mars3D 作为一个基于 CesiumJS 的国产开源 WebGL 地图引擎,极大地简化了三维地球应用的开发流程。

本文将手把手带你,利用 Mars3D 插件,快速搭建一个功能丰富的水利监测 WebGIS 系统。我们将实现以下核心功能:

  1. 加载天地图作为底图
  2. 动态加载并标记多种类型的水利站点(大坝、水文站、雨量站等)
  3. 为关键区域(如水库)添加描边和逼真的水面水纹特效
  4. 实现站点搜索与定位
  5. 集成图例筛选功能

通过本文,你将掌握 Mars3D 在实际项目中的基本用法,并能快速复用到自己的项目中。


一、环境准备与 Mars3D 安装

我们的项目基于 Vue3 + Vite 构建。

配置 Vite(可选但推荐) 为了优化打包体积和解决潜在的路径问题,可以在 vite.config.js 中添加别名:

// vite.config.js import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], resolve: { alias: { // Mars3D 推荐配置 cesium: "mars3d-cesium/Build/Cesium", }, }, }) 

安装 Mars3D 及其依赖 根据 Mars3D 官方文档,我们需要安装核心库和 Cesium。

# 安装 Mars3D 核心库 npm install mars3d # 安装 Mars3D 封装的 Cesium(推荐,已处理好路径等问题) npm install mars3d-cesium 

创建 Vue3 项目

npm create vue@latest my-water-gis cd my-water-gis npm install 

二、初始化 Mars3D 地图

我们创建一个 MapContainer.vue 组件来承载地图。核心在于 infoMars3d 方法。

// MapContainer.vue (script部分) import * as mars3d from "mars3d"; import * as Cesium from "mars3d-cesium"; export default { data() { return { map: null, // 地图实例 graphicLayer: null, // 图形图层,用于管理所有标记点 }; }, async mounted() { await this.initMap(); }, methods: { async initMap() { // 1. 配置地图选项 const mapOptions = { scene: { // 初始视角 center: { lat: 33.119017, lng: 117.901056, alt: 786.8, heading: 117.2, pitch: -16.1 }, sceneMode: 3, // 3D模式 }, control: { // 显示控件 baseLayerPicker: true, // 底图切换 homeButton: true, // 复位 fullscreenButton: true, // 全屏 }, // 2. 配置底图(天地图) basemaps: [ { name: "天地图影像", type: "group", show: true, layers: [ { name: "底图", type: "tdt", layer: "img_d", crs: "EPSG:4326" }, { name: "注记", type: "tdt", layer: "img_z", crs: "EPSG:4326" }, ], }, // ...可以添加更多底图 ], }; // 3. 创建地图实例 this.map = new mars3d.Map("mapContainer", mapOptions); // 4. 创建一个图形图层,用于后续添加所有标记点 this.graphicLayer = new mars3d.layer.GraphicLayer(); this.map.addLayer(this.graphicLayer); } } } 

对应的模板非常简单:

<!-- MapContainer.vue (template部分) --> <template> <div></div> </template> 

至此,一个带有天地图底图的 3D 地球就成功加载了!


三、动态加载并标记水利站点

假设我们有一个后端 API /api/points,返回如下格式的站点数据:

[ { "id": 1, "pointName": "主坝", "pointType": "PSK", "lng": 117.9, "lat": 33.12, "warnSatus": false }, { "id": 2, "pointName": "五河站", "pointType": "PSW", "lng": 117.91, "lat": 33.13, "warnSatus": true }, // ... ] 

我们需要根据 pointType 显示不同的图标,并处理报警状态。

// 在 MapContainer.vue 中添加方法 methods: { // ... initMap // 加载并渲染站点 async loadAndRenderPoints(pointList) { // 清空旧的标记 this.graphicLayer.clear(); pointList.forEach((item) => { // 1. 根据类型选择图标 const getImageByType = (type) => { const iconMap = { PSK: "@/assets/img/map/icon-dam.png", PSW: "@/assets/img/map/icon-sw.png", PYL: "@/assets/img/map/icon-yl.png", // ...其他类型映射 }; return require(iconMap[type] || "@/assets/img/map/default.png"); }; // 2. 创建标记点实体 (BillboardEntity) const billboardEntity = new mars3d.graphic.BillboardEntity({ position: [item.lng, item.lat], style: { image: getImageByType(item.pointType), scale: 1, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 3. 添加站点名称标签 label: { text: item.pointName, font_size: 20, color: "#ffffff", outline: true, outlineColor: Cesium.Color.BLACK, // ...其他样式 }, }, }); // 4. 如果是报警状态,启动弹跳动画 if (item.warnSatus) { billboardEntity.startBounce({ autoStop: false, step: 0.3, maxHeight: 20 }); } // 5. 绑定鼠标事件 billboardEntity.on("mouseOver", () => { if (item.warnSatus) billboardEntity.stopBounce(); // 悬停停止弹跳 // 这里可以绑定自定义信息弹窗 }); billboardEntity.on("mouseOut", () => { if (item.warnSatus) billboardEntity.startBounce(); // 移出恢复弹跳 }); // 6. 绑定点击事件,打开详情 billboardEntity.on("click", () => { // 根据 pointType 打开不同的详情弹窗组件 if (item.pointType === "PYL") { this.openRainfallDialog(item); } else if (item.pointType === "PSK") { this.showReservoirDamView(item); // 切换到大坝平面图视图 } // ...其他类型处理 }); // 7. 将实体添加到图层 this.graphicLayer.addGraphic(billboardEntity); }); } } 

通过这个方法,我们就能将从 API 获取的数据动态渲染到地图上,并赋予丰富的交互能力。


四、为水库添加描边与水纹特效

这是 Mars3D 的亮点之一,可以轻松实现非常酷炫的效果。通常,水库的范围会以 GeoJSON 格式提供。

  1. 准备 GeoJSON 文件 假设我们有一个 qzj.json 文件,描述了“樵子涧水库”的边界。
  2. 加载 GeoJSON 并应用水纹材质initMap 方法中或单独封装一个方法:
// 在 MapContainer.vue 中添加方法 addReservoirWaterEffect() { const geoJsonLayer = new mars3d.layer.GeoJsonLayer({ url: "/public/qzj.json", // 确保文件放在 public 目录下 symbol: { type: "waterC", // 关键!指定为水面材质 styleOptions: { height: 17, // 水面高度(相对于地形) normalMap: require("@/assets/img/reservoir/waterNormals.jpg"), // 水波法线贴图 frequency: 8000.0, animationSpeed: 0.02, amplitude: 5.0, // 波浪幅度 baseWaterColor: "#006ab4", // 水的颜色 opacity: 0.4, // 透明度 clampToGround: true, // 贴地 // 添加描边 outline: true, outlineStyle: { color: "#067cd3", width: 3, opacity: 1, }, }, }, tooltip: "樵子涧水库", // 鼠标悬停提示 flyTo: true, // 自动飞向该区域 }); this.map.addLayer(geoJsonLayer); } 

调用 this.addReservoirWaterEffect() 后,地图上就会出现一个带有动态水纹和蓝色描边的水库,效果非常直观和专业。


五、其他实用功能

您的代码中还包含了几个非常实用的功能点:

  • 站点搜索:通过 searchByName 方法,遍历 pointList,使用 this.map.flyToPoint([lng, lat, height]) 实现快速定位。
  • 图例筛选:通过 layerPop 弹窗获取用户选择的 pointType,然后调用 loadAndRenderPoints 重新渲染筛选后的点位。
  • 视图切换toOneMap 方法实现了从“大坝详情平面图”视图切换回“全局地图”视图,通过销毁和重建地图实例完成。

总结

通过以上步骤,我们利用 Mars3D 成功构建了一个功能完备的水利监测 WebGIS 基础框架。Mars3D 的优势在于其对 CesiumJS 的深度封装和大量开箱即用的组件(如 BillboardEntity, GeoJsonLayer),让我们能够用更少的代码实现更强大的 GIS 功能。

Mars3D平台

国家地理信息公共服务平台

 

 


希望这篇文章对你有帮助!

Could not load content