资讯动态

Cesium去Logo实战:Vue3项目规范做法与常见坑

发布时间:2026/9/13 16:45:07 来源:尧图企业网站定制
先说明一下个人项目里去掉 Cesium 的 Logo 属于很常见的需求官方文档其实也留了口子。但很多新手一搜去掉版权Logo搜到的都是直接改源码删代码那种野路子真正规范的做法反而被淹没了。这篇就从头到尾把 Cesium 的 Logo 机制讲透顺带把 Vue3 里集成 Cesium 的坑也一起排掉。1. Cesium 版权 Logo 的显示逻辑与去除原理1.1 先搞清楚 Logo 是怎么渲染出来的Cesium 初始化的时候会往页面容器里塞一堆 DOM 元素Logo 就是其中之一。很多人的第一反应是我能不能用 CSS 把它藏掉答案是可以但这不是最干净的做法。Cesium 的 Logo 在源码里走的是CreditContainer这条线它内部维护了一个CreditDisplay类专门负责把各种版权信息渲染到屏幕上。我们平时看到的左下角那行字本质上是 Cesium 在初始化时根据传入的creditContainer参数决定往哪里挂载const viewer new Cesium.Viewer(cesiumContainer, { creditContainer: document.createElement(div) // 传一个空白容器 });一旦你手动指定了creditContainerCesium 就会把版权信息渲染到你指定的这个元素里默认的左下角容器就不再生效。你只要不把这个元素挂到 DOM 上Logo 就自然消失了。这个方案完全不需要改源码升级 Cesium 版本也不会被覆盖是我在正式项目里最推荐的一种做法。1.2 为什么推荐这种方式而不是直接删源码网上流传比较广的办法是去node_modules里找到 Cesium 的源码文件把渲染 Logo 那几行代码删掉。这种做法在本地开发时候确实有效但一打包、一升级问题就来了node_modules是依赖目录重新npm install之后你改的东西全没了Cesium 升级版本时你很难记住自己到底改过哪里排查问题非常痛苦团队其他成员拉代码后并不会自动同步你本地的node_modules修改所以只要不是被逼到没办法我都建议避开改源码这条路。creditContainer这个参数就是官方留给开发者的合法出口用它在逻辑上最干净。1.3 确保已经先配置了 Cesium Ion 的 Token去掉 Logo 之前必须确认一件事你的 Cesium 是不是一个合法可用的状态。如果压根没配 TokenCesium 会频繁弹窗提示你要去申请这种情况下即使你去掉了 Logo后续加载影像、地形也会遇到问题。Cesium.Ion.defaultAccessToken 你的token;登录 Cesium Ion 官网注册账号后创建一个 Token 就行。这一步不复杂但确实是很多项目里地图不显示没有影像这类问题的根源我实际排查过不少都是这个原因。Token 配置好了再去处理 Logo 的事顺序不能反。2. Vue3 项目里集成 Cesium 的基础搭建2.1 环境准备Vue3 Vite 项目的初始化现在做 Vue3 项目大多用的是 Vite 而不是老牌的 vue-cli打包速度快、配置也直观。初始化命令很简单npm create vitelatest cesium-demo -- --template vue依赖装好后再把 Cesium 装进来npm install cesium装完后不要去动node_modules里的东西。Vite 项目需要在vite.config.js里做一些配置Cesium 才能正确打包。这里给一个我常用的配置模板import { defineConfig } from vite; import vue from vitejs/plugin-vue; import path from node:path; export default defineConfig({ plugins: [vue()], resolve: { alias: { : path.resolve(__dirname, ./src), cesium: path.resolve(__dirname, ./node_modules/cesium/Source), } }, define: { CESIUM_BASE_URL: JSON.stringify(/cesium), }, });CESIUM_BASE_URL这个变量很关键Cesium 运行时需要加载一堆静态资源比如Workers、Assets、Widgets这些目录如果你不定义它资源请求会 404直接导致地球出不来。2.2 静态资源拷贝让 Cesium 正常加载工作线程配好了CESIUM_BASE_URL还得保证这路径下真的存在对应的静态资源。在public目录里建一个cesium文件夹把node_modules/cesium/Build/Cesium/下的Workers和Assets两个目录复制过去。Vite 的public目录里的内容会原样拷贝到打包后的根路径下所以只要CESIUM_BASE_URL配成/cesium请求自然就能命中。一步步手动复制比较笨可以在vite.config.js里加一个插件自动处理但为了新手好理解我建议前期先手动复制一次跑通了再考虑自动化。脑袋里要有一张图请求/cesium/Workers/createGeometry.js时实际文件位置是public/cesium/Workers/createGeometry.js。2.3 页面组件的编写与 Cesium 实例化环境配好之后写一个最简单的 Vue3 组件来挂载地球。这一步我通常直接用一个普通的div作为容器然后onMounted里启动 Viewertemplate div idcesiumContainer classcesium-container/div /template script setup import { onMounted, onBeforeUnmount } from vue; import * as Cesium from cesium; let viewer null; onMounted(() { viewer new Cesium.Viewer(cesiumContainer, { timeline: false, animation: false, baseLayerPicker: false, geocoder: false, homeButton: false, sceneModePicker: false, navigationHelpButton: false, fullscreenButton: false, infoBox: false, selectionIndicator: false, }); }); onBeforeUnmount(() { if (viewer) { viewer.destroy(); viewer null; } }); /script style scoped .cesium-container { width: 100%; height: 100vh; position: relative; } /style注意onBeforeUnmount里的destroy很多新人会在路由切换后遇到地图崩溃、内存泄漏的问题很大程度上就是没有正确销毁 Viewer。这一点后面在3D 地球滚动崩溃相关常见问题里我会再展开说。2.4 初次运行可能遇到的资源加载报错按上面的步骤走完大概率能正常看到地球。如果页面一片灰、控制台一堆 404优先排查顺序是CESIUM_BASE_URL是否被正确读取public/cesium下是否有Workers和Assets目录请求路径和实际文件路径是不是一一对应我自己碰到最多的情况是路径配错比如请求的是/Assets/xxx但实际放到了/cesium/Assets/xxx这种情况下哪怕只差一层目录Cesium 也会直接罢工。3. 去除左下角 Cesium 版权 Logo 的几种实用方案3.1 方案一官方推荐的 creditContainer 方式老规矩先推荐正路。const creditContainer document.createElement(div); const viewer new Cesium.Viewer(cesiumContainer, { creditContainer: creditContainer, });因为creditContainer是自定义的 DOM 元素Cesium 会把 Logo 渲染到这个元素里但这个元素并不在你页面的可见区域里用户自然看不到。这种做法的好处没有修改任何源码Cesium 本身的功能完全不受影响升级 Cesium 版本时这一行配置不会失效后面如果想要把 Logo 显示在别的位置也完全可以拿这个容器做文章我单独提一句官方文档里写的是默认值会创建一个新的 div 并添加到 widget 容器内这句话的意思就是你不传这个参数时Cesium 会自动帮你创建一个。我们自己创建就是截胡了它的这个过程。3.2 方案二关闭默认的 creditDisplay 展示还有另一个配置项叫creditDisplay它是Viewer内部服务CreditDisplay的实例。如果你想在运行时动态控制版权信息的显隐可以通过访问viewer.creditDisplay来操作viewer.creditDisplay._creditsContainer.style.display none;注意下划线_creditsContainer属于私有成员理论上框架不保证它永远存在。所有带下划线开头的属性都是官方默认不推荐外部去动的。如果你只是为了快速验证效果临时用用没问题但我不推荐写进正式代码里因为 Cesium 升级后这个属性是有可能被改掉的。3.3 方案三CSS 层面隐藏不推荐但不失为一个思路很多文章里提到用 CSS 去隐藏.cesium-viewer-bottom { display: none; }这个 class 在默认情况下确实能瞄中左下角的版权区域。前面也说了能行但从合规角度来说这种方式属于视觉隐藏Cesium 的版权信息实际还在页面上渲染着。而且.cesium-viewer-bottom这个类名如果被 Cesium 内部其他模块复用样式可能会互相影响。我不太推荐但把它列出来是因为你在看别人代码时可能会遇到知道了总比一头雾水强。3.4 方案四基于 Cesium 源码的自定义打包如果你确实被逼到非要彻底改源码不可那我建议不要直接改node_modules而是去 fork 一份 Cesium 源码改完后自己打包引用。具体来说需要关注的源码位置在packages/widgets/Source/CreditDisplay/CreditDisplay.js里。这里面有一段代码负责把 Logo 加到creditContainer中逻辑大致是创建了一个div把 Cesium 的版权字符串塞进去。你可以自己去掉这段逻辑再把整个项目重新打包。这条路成本不低但适合两种人一是对 Cesium 二次开发有长期规划、想深入理解源码的团队二是用的 Cesium 版本比较旧、官方可能已经不更新支持了。普通项目确实没必要搞这么重。3.5 四种方案对比与选型建议方案难易程度是否改源码升级兼容性推荐度creditContainer低否好高动态操作 creditDisplay低否中等中CSS 隐藏低否中等低源码自定义打包高是定制低我在实际项目里优先用的是第一种简单、干净、不会因为版本升级而翻车。4. 深度玩法修改源码彻底移出 Logo4.1 找出生成 Logo 的具体代码位置这一节是给那些确确实实需要改源码的人准备的。如果你用的是常规方式安装的 Cesium那么关键文件通常在node_modules/cesium/Source/Widgets/CreditDisplay/CreditDisplay.js如果你用的是打包后的版本那可能要去node_modules/cesium/Build/Cesium/Cesium.js那么在压缩后的Cesium.js里找字符串会比较痛苦你会看到很多代码挤成一行或几行。建议先去搜CreditDisplay.prototype这样的关键字定位到类定义再从里面找logo、creditContainer、CreditLogo之类的标识。4.2 定制打包时的注意事项如果你选择 fork 源码自己打包需要额外注意CreditDisplay内部不只是挂了一个 Logo它还管理着所有数据源、图层的版权信息。如果盲目删除可能会导致某些图层的数据源版权信息一并失效比如加载了某些需要标明出处的数据服务这在合规上是有风险的。所以正确的改法不是删整个模块而是精准地去掉默认 Logo 渲染的那一段保留其他 credit 展示逻辑。具体到代码层面通常是找到类似这样的语句var logo document.createElement(div); logo.className cesium-credit-logoContainer;把这段创建和插入 DOM 的逻辑注释掉或者删除即可。但注释之前先确认这段逻辑是否同时负责初始化一些必要的事件绑定如果有那就要连事件绑定一起评估。4.3 什么场景下才真正需要改源码我提供一个判断标准只有当你的项目既不能用creditContainer方案又不能接受页面上有任何 CSS hack 痕迹时才需要考虑改源码。这种需求多见于有严格 UI 设计标准的可视化大屏项目或者客户当场打开开发者工具检查 DOM 结构的情况。在这类场景下改源码是唯一能彻底消灭Logo 的方式因为它是从渲染源头断掉的。5. 实际项目里的完整集成与优化5.1 封装一个可复用的 Cesium 地图组件在 Vue3 项目里Cesium 的地图不会只在一个页面用到。我通常会把它封装成组件暴露几个常用配置项比如是否显示 Logo、是否允许切换底图、视角初始位置等。这样在不同页面里只需要传不同 props 就能复用同一套逻辑。组件的大致结构长这样template div refcesiumRef classcesium-container/div /template script setup import { ref, onMounted, onBeforeUnmount } from vue; import * as Cesium from cesium; const props defineProps({ showLogo: { type: Boolean, default: false, }, initialView: { type: Object, default: () ({ longitude: 116.39, latitude: 39.9, height: 10000000, }), }, }); const cesiumRef ref(null); let viewer null; onMounted(() { const creditContainer props.showLogo ? undefined : document.createElement(div); viewer new Cesium.Viewer(cesiumRef.value, { creditContainer, animation: false, timeline: false, baseLayerPicker: false, geocoder: false, homeButton: false, sceneModePicker: false, navigationHelpButton: false, fullscreenButton: false, }); viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees( props.initialView.longitude, props.initialView.latitude, props.initialView.height ), }); }); onBeforeUnmount(() { viewer.destroy(); }); /script这个组件在多个业务页面里直接引用只需通过showLogo控制版权信息的显隐非常方便。5.2 影像底图与地形加载Cesium 默认使用的是 Ion 的天地图影像速度在国内一般。如果你的业务主要面向国内用户我更推荐直接接入高德或天地图影像。配置方法是在 Viewer 创建时指定imageryProviderimport { UrlTemplateImageryProvider } from cesium; const imageryProvider new UrlTemplateImageryProvider({ url: https://your-tile-server/{z}/{x}/{y}.png, maximumLevel: 18, }); viewer new Cesium.Viewer(cesiumContainer, { imageryProvider, baseLayerPicker: false, });底图服务商每家提供的瓦片格式略有差异接入前务必读一下对应文档。像天地图需要额外的 key高德则对subdomains有要求。如果搞不清可以先不换等 Logo 去掉了再慢慢调底图。5.3 动态光照、雷达扫描这类效果的加分项Cesium 里做动态光照最常见的做法是调整viewer.scene.light或者给Material设置随时间变化的属性。雷达扫描效果则常用PolylineCollection配合自定义 Material 来实现动态波纹。这些效果在概念上不难但调试时会遇到不少麻烦。比如动态光照如果frameState的渲染循环没有正确触发会发现灯光一直不变化雷达波纹如果Material的czm_material定义不严谨也会出现边界闪烁。我个人的建议是先把基础地球跑起来、Logo 处理干净再在它上面叠加这类视觉效果不然出了问题你真不知道是 Cesium 底子没搭好还是效果代码的问题。6. 常见问题排查为什么我的 Cesium 表现异常6.1 3D 地球滚动时崩溃这是最近被问得比较多的一类问题。场景往往是页面里嵌入了 Cesium 地球然后用户滚动页面或者页面内部有滚动容器滚动几下浏览器标签页就卡死或者崩溃。背后大概率是滚动事件把 Cesium 的渲染循环拖垮了。Cesium 渲染本身很吃 GPU 和 CPU滚动会造成浏览器频繁触发重绘和合成叠加起来就直接把页面拖崩。排查思路确认页面是否有不必要的全局滚动监听有就针对性优化查看有没有频繁调用viewer.camera之类的操作导致每次滚动都触发重新渲染用 Chrome 性能面板录制一段滚动操作看是哪些函数占用了大部分时间如果只是为了展示可以考虑把 Cesium 场景放在一个固定高度且不参与页面滚动的容器里如果要跟随页面滚动那就要好好做一下requestAnimationFrame的节流了。6.2 加载 3857 坐标系数据时出现偏移这个坑是真的有点深遇到的人也不少。3857 是 Web 墨卡托投影本身是平面坐标而 Cesium 默认是三维球面坐标直接在球上叠加平面投影数据必然会出现飘。解决思路是尽量在数据源头转换成经纬度或者通过GeoJSONDataSource加载时指定dataProjection参数让 Cesium 知道你的数据是哪个投影来的它内部会做转换。单纯依赖前端硬转并不现实因为一个 GeoJSON 里可能包含大量要素前端转的效率和精度都不理想。6.3 Edge 浏览器下按钮无法点击有朋友反馈 Vue3 项目在 Edge 浏览器里出现关闭不了右上角最小化按钮这类怪异问题。这通常是 CSS 的层级、z-index或pointer-events设置导致的。Cesium 的容器默认会创建多个层级的 DOM 和 canvas如果外层元素不小心给他加了transform或者filter会形成新的层叠上下文导致原有按钮被盖住。检查方式是打开 Edge 的开发者工具查看按钮元素的computed样式重点看pointer-events和z-index再逐层往上看是否有父元素影响了层级。这类问题跟 Cesium 本身没太大关系而是混合了 UI 框架后常见的样式冲突。7. 从入门到精通常犯的几个理解误区7.1 误区一Cesium 一定要用 npm 包手动配置其实 Cesium 也有 CDN 方式的引入直接script标签一样能用。但对于 Vue3 Vite 这种工程化项目npm 方式更利于依赖管理和版本锁定也能更好地利用 Vite 的打包优化。手动拷贝静态资源那一步只是前期配置成本后面都用得上谈不上麻烦。7.2 误区二去 Logo 就等于破解或违规Cesium 的正规版权协议中它本身提供了creditContainer这种合法隐藏 Logo 的机制许多商业项目也在用。只要你没有滥用 Cesium 的资源、没有抹掉其他不可删除的版权信息使用它提供的官方配置隐藏默认 Logo 是允许的。很多人的顾虑是因为看到太多改源码的野路子误以为去 Logo 一定违规这个理解需要修正。7.3 误区三Vue2 经验直接搬到 Vue3 没问题Vue2 和 Vue3 在响应式原理、组件通信、生命周期上差异很大。最典型的例子是this的引用方式完全不同Vue3 组合式 API 里已经没有this指向组件实例的习惯用法了。如果你之前习惯在mounted里写一堆初始化逻辑转 Vue3 后应该把这些逻辑分散到setup、onMounted等合适的位置里不要一把梭。Cesium 在 Vue2 项目里的集成方式放到 Vue3 里往往也不能直接复制。组件实例的生命周期钩子名字变了$refs 的获取时机也变了很容易出问题。8. 功能扩展除了去 LogoCesium 还能怎么玩8.1 绘制矩形与热力图绘制矩形在 Cesium 里主要用viewer.entities.add配合RectangleGraphics。给定西南角和东北角的经纬度就能直接在地图上拉出一个面。热力图则稍微复杂通常需要先用 ECharts 生成热力图 canvas再把 canvas 作为Material贴在 Cesium 的Rectangle上这样就能实现热力覆盖面的效果。想做成动态热力可以在前端定时更新数据、重新生成 canvas再刷新材质。8.2 鹰眼图与模型节点操作鹰眼也就是小地图导航很多 GIS 项目都会要这个。实现思路并不复杂创建一个小型的Viewer或者Scene和主视图保持同步camera.changed事件触发时把小地图的相机位置同步过去。模型节点操作就更有趣了加载一个 3D Tiles 或者 glTF 模型后你可以通过viewer.scene.getPickPosition获取鼠标点击位置再通过模型的ModelInstanceCollection获取对应节点就能实现点哪个零件高亮哪个零件这种交互。这在城市孪生方向特别常见。8.3 天空盒与 Unity 集成Cesium 支持自定义SkyBox你可以换成自己团队设计的天空贴图让整个三维场景的氛围更统一。和 Unity 集成则属于 Cesium for Unity 这条独立产品线的范畴它把 Cesium 的地球能力整合到 Unity 渲染引擎里。很多做城市孪生、数字孪生项目的团队都在走这条路。这种场景下版权 Logo 的处理又会变得不同因为渲染管线不再完全由 Cesium 控制。8.4 面试场景里 Cesium 相关的考点Cesium 面试题核心就集中在坐标系转换、相机视角控制、实体与图元渲染、离屏渲染、性能优化、requestRenderMode这几类。把 Cesium 官方文档里的Camera、Entity、Primitive相关 API 吃透再对这个项目里的集成经验做一个梳理面 Cesium 岗基本没什么大问题。毕竟项目里能踩的坑你都踩过了代码结构也完整这本身就是浓缩的实战经验。9. 一些踩坑记录与个人经验9.1 项目里的 3D 地球总是崩先看看内存有时候页面看着没进行什么复杂操作但地球时不时卡死刷新后又好了。这种情况大多数是内存泄漏。Cesium 的Viewer如果创建后没有正确销毁每次进页面都会创建一个新实例而且旧实例的 GPU 资源喂一直占着。时间一长页面内存飙升3D 场景必然崩。我自己的习惯是给组件用完后统一记日志在开发环境里切页面时观察window.performance.memory有没有明显上涨。这个经验能帮你早点发现泄漏别等现场客户反馈了才追着排查。9.2 requestRenderMode 是性能优化的核心开关如果你的项目并不需要地球持续转动或动画开启requestRenderMode: true会极大降低 CPU 和 GPU 消耗。它表示只有在场景发生变化时才渲染新帧否则静态画面就是空转。但要注意如果同时开了动态光照、雷达扫描这类需要持续帧更新的效果必须手动调用viewer.scene.requestRender()来让新帧重新绘制。这个开关理解起来容易用起来有点考功力因为你要清楚什么操作会触发新渲染什么操作不会。我一般会针对动态数据和静态场景分开处理做一个专门的渲染调度模块。ES6 模块化与 Cesium 的 import 时机Cesium 对 ES Module 的支持已经挺成熟了但依然有同学在import * as Cesium from cesium之后就报各种 undefined。多数情况是版本与引入方式不一致或者跟 Vite 的optimizeDeps处理产生了冲突。建议优先用 npm 最新稳定版本遇到错误时先看版本号而不是急着去改源码。如果你是用 CDN 方式加载的需要注意引入顺序确保 Cesium 的全局变量已经挂在 window 上之后再执行自己的代码。这个顺序在很多老教程里被忽略但实际项目里恰恰最容易出问题。小技巧利用监听器动态控制版权 Logo最后分享个小技巧。如果你希望页面上有个开关用户点了就显示 Logo再点了就隐藏 Logo可以直接操作creditDisplay的容器样式function toggleLogo(visible) { const container viewer.creditDisplay._creditsContainer; if (container) { container.style.display visible ? block : none; } }这个功能放在一个不起眼的工具栏里演示给客户看的时候特别方便。虽然前面说了私有成员有兼容风险但用在这种辅助功能里问题不大。真要进了生产环境记得优先考虑creditContainer方案。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价