153.在 Vue 3 中使用 OpenLayers + Cesium 实现 2D/3D 地图切换效果

🎬 效果演示截图


✨ 前言

在实际项目开发中,我们经常需要提供「二维地图 + 三维地形」的可视化效果切换,例如:

  • 智慧农业展示耕地分布 + 三维地形起伏;

  • 智慧城市展示建筑物点位 + 三维城市;

  • 数字孪生场景中,2D/3D 切换已是标配功能。

本文将手把手教你如何使用 Vue 3 + OpenLayers + Cesium 结合 ol-cesium 实现一键切换 2D/3D 地图视图。


📦 技术选型说明

工具库说明
Vue 3 + Composition API构建 UI 和交互
OpenLayers (ol@10.x)作为主地图引擎,承载2D地图
Cesium (cesium@1.131)提供3D地形图、3D建筑、卫星视角等能力
ol-cesium (v2.17)连接 OpenLayers 和 Cesium 的桥梁
Vite(推荐)高速构建工具,适配 Cesium 配置更方便

🔧 环境配置

1️⃣ 安装依赖

pnpm add ol cesium ol-cesium

或:

npm install ol cesium ol-cesium

2️⃣ 配置 Cesium 静态资源

推荐方式:使用 vite-plugin-cesium 自动处理 Cesium 资源路径

pnpm add vite-plugin-cesium -D

vite.config.ts 中配置插件:

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import cesium from 'vite-plugin-cesium'export default defineConfig({plugins: [vue(), cesium()]
})

✅ 这样可以让 CESIUM_BASE_URL 自动指向 /cesium/ 路径,无需手动复制 Cesium 静态文件。


💻 核心代码实现

以下是完整的 MapSwitcher.vue 示例组件,支持 2D/3D 地图切换:

🧩 组件结构代码

<!--* @Author: 彭麒* @Date: 2025/7/15* @Email: 1062470959@qq.com* @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。-->
<template><div class="full-screen"><div ref="mapContainer" class="map-container"></div><button class="toggle-btn" @click="toggle3D">切换到 {{ is3D ? '2D' : '3D' }}</button></div>
</template><script setup lang="ts">
import {onBeforeUnmount, onMounted, ref} from 'vue'
import 'ol/ol.css'
import {Map, View} from 'ol'
import TileLayer from 'ol/layer/Tile'
import OSM from 'ol/source/OSM'
import {fromLonLat} from 'ol/proj'// 定义全局变量类型
declare global {interface Window {CESIUM_BASE_URL: string;Cesium: any; // 添加全局Cesium类型}
}// 设置Cesium资源路径 - 使用相对路径
window.CESIUM_BASE_URL = './node_modules/cesium/Build/Cesium';// 导入Cesium并赋值给全局对象
import * as Cesium from 'cesium'
window.Cesium = Cesium; // 关键步骤:将Cesium设为全局对象import 'cesium/Build/Cesium/Widgets/widgets.css'
// @ts-ignore
import OLCesium from 'ol-cesium'const mapContainer = ref<HTMLDivElement | null>(null)
const is3D = ref(false)
let map: Map
let olCesiumObj: anyonMounted(() => {// 初始化2D地图map = new Map({target: mapContainer.value!,layers: [new TileLayer({ source: new OSM() })],view: new View({center: fromLonLat([104.0668, 30.5728]),zoom: 5})})try {// 确保Cesium已加载if (!window.Cesium) {console.error('Cesium未正确加载为全局对象')return}// 初始化3D视图olCesiumObj = new OLCesium({map: map})// 初始设置为2D模式olCesiumObj.setEnabled(false)// 设置地形initTerrain()} catch (error) {console.error('初始化Cesium失败:', error)}
})function initTerrain() {try {if (window.Cesium && window.Cesium.createWorldTerrainAsync) {window.Cesium.createWorldTerrainAsync({requestWaterMask: true,requestVertexNormals: true}).then(terrainProvider => {if (olCesiumObj && olCesiumObj.getCesiumScene) {olCesiumObj.getCesiumScene().terrainProvider = terrainProvider;}}).catch(error => {console.error('加载地形失败:', error);});}} catch (error) {console.error('设置地形失败:', error);}
}onBeforeUnmount(() => {if (olCesiumObj) {olCesiumObj.setEnabled(false)olCesiumObj.destroy()}map?.setTarget(undefined)
})function toggle3D() {is3D.value = !is3D.valueolCesiumObj?.setEnabled(is3D.value)
}
</script><style scoped>
.full-screen {position: relative;width: 100%;height: 100vh;
}
.map-container {width: 100%;height: 100%;
}
.toggle-btn {position: absolute;top: 16px;left: 16px;z-index: 1000;padding: 8px 12px;background: white;border: 1px solid #ccc;cursor: pointer;
}
</style>

💡 项目拓展建议

  • ✅ 添加图层切换、绘图、定位等功能;

  • ✅ 使用 Cesium 加载 3D 模型(glTF、倾斜摄影);

  • ✅ 增加鼠标拾取、飞行动画;

  • ✅ 与 GIS 属性数据结合进行业务可视化。


❓常见问题汇总

问题解决方式
OLCesium is not a constructor确保导入的是 ol-cesium 并正确写法:import OLCesium from 'ol-cesium'
Cesium 未加载必须设置 window.Cesium = Cesium,否则 ol-cesium 找不到全局对象
地形不生效检查 createWorldTerrainAsync 调用是否报错、scene 是否为空
Cesium 路径报错使用 vite-plugin-cesium 自动设置 CESIUM_BASE_URL,避免路径问题


📚 参考资料

  • Cesium 官方文档

  • OpenLayers 官网

  • ol-cesium Github

  • vite-plugin-cesium


✍️ 结语

如果你也在做地图相关项目,希望本文能帮你快速搭建一个可切换的 2D/3D 地图系统。该示例可直接嵌入业务页面,未来也可以拓展更多可视化能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/89473.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/89473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

纯C++11实现!零依赖贝叶斯情感分析系统,掌握机器学习系统工程化的秘密!

本文深度剖析了一个完全基于C++11标准库实现的贝叶斯情感分析系统。该系统采用模块化设计,实现了从文本预处理、特征提取到朴素贝叶斯分类的完整机器学习流水线。 1. 系统架构概览 1.1 技术栈选择与设计哲学 该系统完全采用C++11标准库实现,无任何外部依赖,体现了"纯…

Android原生Dialog

在原生android里面&#xff0c;有两种dialog写法&#xff0c;一种是直接使用里面提供的AlertDialog.Builder方法去使用&#xff0c;另一种是我们自己根据自己的ui来设计&#xff08;自定义&#xff09;。在一般开发中&#xff0c;我们主要使用的是自定义&#xff0c;主要是Aler…

Nacos 开源 MCP Router,加速 MCP 私有化部署

作者&#xff1a;正己 Nacos MCP Router 简介 Nacos MCP Router 是一个基于 MCP 官方 SDK 开发的标准 MCP Server&#xff0c;为 MCP Client 提供 MCP Server 的智能搜索、安装、代理等功能&#xff0c;极大地简化了 MCP 服务的使用流程。同时&#xff0c;Nacos MCP Router 跟…

【赵渝强老师】Redis的主从复制集群

Redis的主从复制是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器。前者称为Master主节点&#xff0c;后者称为Slave从节点。数据的复制是单向的&#xff0c;只能由主节点到从节点。在默认情况下每台Redis服务器都是主节点。一个主节点可以有多个从节点或者没有…

Git 子模块只更新部分模块的问题排查总结

Git 子模块只更新部分模块的问题排查总结 问题描述 在执行 git submodule update --init --recursive 命令时&#xff0c;虽然 .gitmodules 文件中定义了 3 个子模块&#xff0c;但只有 handy-ollama 被更新&#xff0c;其他两个子模块没有被处理。 > git submodule upda…

React 源码7:Lane、React和schedule优先级转换

在《源码3》requestUpdateLane函数根据eventLane获取不同情况对应优先级。一、优先级1.Lane的tag一共有32种lane。var TotalLanes 31; var NoLanes /* */ 0; var NoLane /* */ 0; var SyncLane /* …

Linux RDMA Maillist patchsets (Jul. 7 - Jul. 13, 2025)

1. Optimize DMABUF Mkey Page Size in mlx5 优化 mlx5 中的 DMABUF Mkey 页大小 This patch series enables the mlx5 driver to dynamically select the optimal page size for DMABUF-based memory keys (mkeys), rather than relying on a fixed page size during registr…

Maven详细解

Maven 工具介绍 Maven是Apache组织下的一个跨平台的项目管理工具&#xff0c;它主要用来帮助实现项目的构建、测试、打包和部署。Maven 提供了标准的软件生命周期模型和构建模型&#xff0c;通过配置就能对项目进行全面的管理。它的跨平台性保证了在不同的操作系统上可以使用相…

Springboot儿童摄影服务91f0v(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能&#xff1a;用户,员工,摄影套餐,套餐系列,客片欣赏,摄影预约,摄影订单,取片通知,摄影评价开题报告内容基于Spring Boot的儿童摄影服务系统设计与实现开题报告一、研究背景与意义随着国家生育政策调整&#xff0c;儿童摄影市场需求呈现爆发式增长。以北…

vue-seo优化

一、为什么 Vue 需要专门做 SEO Vue 默认是客户端渲染 SPA&#xff0c;首屏 HTML 几乎为空&#xff0c;爬虫抓取不到内容&#xff1b;即使 Googlebot 能执行 JS&#xff0c;也存在“渲染预算”与加载延迟问题 二、技术落地 4 条路线 场景技术选型实现要点适用内容更新频…

DNS防护实战:用ipset自动拦截异常解析与群联AI云防护集成

问题场景 DNS服务器常成为黑客探测源IP的首选目标。攻击者通过高频DNS查询获取解析记录&#xff0c;或利用异常请求触发服务器响应&#xff0c;从而定位源站IP。传统单IP拦截效率低下&#xff0c;难以应对分布式攻击。 核心解决方案 ipset自动化拦截 ipset是iptables的扩展&…

养老院跌倒误报频发?陌讯时空图卷积实现95%精准检测

​开篇痛点​​> "传统视觉算法在养老院场景面临三大挑战&#xff1a; > ① 夜间低光照下识别率骤降&#xff08;<50% mAP&#xff09; > ② 多人遮挡场景姿态检测漂移 > ③ 跌倒误报率高达30%&#xff08;某养老机构2024年报告&#xff09;"通…

[spring6: BeanPostProcessor BeanFactoryPostProcessor]-生命周期

BeanFactoryPostProcessor BeanFactoryPostProcessor 接口允许在 Spring 容器初始化完所有的 bean 定义之后&#xff0c;但还未实例化任何 bean 时&#xff0c;修改应用上下文的内部 bean 工厂。通过实现 postProcessBeanFactory 方法&#xff0c;你可以覆盖或添加属性&#xf…

MISRA C-2012准则之声明与定义

目录 一、MISRA C简介 二、声明与定义 1. 必需。类型应被显式声明。 2. 必需。函数应以原型形式命名参数。 3. 必需。所有对象和函数的声明需要使用完全相同的名字和参数。 4. 必需。当定义有外部链接的对象或函数时&#xff0c;兼容声明应是可见的。 5. 必需。外部变量…

【blender】使用Vscode进行blender调试

配置vscodeblender 直接使用blender中的text editor没有代码补全&#xff0c;终端输出通常和blender不在同一个页面&#xff0c;只适合非常简单的代码测试。使用Vscode能有效提高blender调试的效率&#xff0c;具体方式见&#xff1a;VSCode 开发 Blender脚本工具配置。 调试…

Au速成班-乐理知识补充+网页下载音乐

音质分类 通过查看音频频谱&#xff0c;128Kbps、192Kbps、320Kbps、无损&#xff08;Lossless HD&#xff09;CD音质&#xff08;频率都在20kHz以上&#xff09;。 各家平台对无损的定义不一样&#xff0c;em各有说法吧。 无损的含义是&#xff1a;无损失的声音格式。只要能…

JAVA中的Collection集合及ArrayList,LinkedLIst,HashSet,TreeSet和其它实现类的常用方法

文章目录前言一、Collection 接口常用方法1.boolean add(E e)2.boolean remove(Object o)3.boolean contains(Object o)4.boolean isEmpty()5.int size()6.void clear()7.Object[] toArray()8.boolean containsAll(Collection<?> c)9.boolean addAll(Collection<? e…

有n棍棍子,棍子i的长度为ai,想要从中选出3根棍子组成周长尽可能长的三角形。请输出最大的周长,若无法组成三角形则输出0。

题目描述&#xff1a; 有n棍棍子&#xff0c;棍子i的长度为ai&#xff0c;想要从中选出3根棍子组成周长尽可能长的三角形。请输出最大的周长&#xff0c;若无法组成三角形则输出0。 算法为O(nlogn) 初始理解题目 首先&#xff0c;我们需要清楚地理解题目要求&#xff1a; 输入…

【Echarts】 电影票房汇总实时数据横向柱状图比图

效果图code <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>圆角柱状图</title><script src"https://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js"></script> </head> <…

【深度学习基础】PyTorch中model.eval()与with torch.no_grad()以及detach的区别与联系?

目录1. 核心功能对比2. 使用场景对比3. 区别与联系4. 典型代码示例(1) 模型评估阶段(2) GAN 训练中的判别器更新(3) 提取中间特征5. 关键区别总结6. 常见问题与解决方案(1) 问题&#xff1a;推理阶段显存爆掉(2) 问题&#xff1a;Dropout/BatchNorm 行为异常(3) 问题&#xff1…