基于天地图的Cesium三维地图开发实践

目录

一、前言

1、Cesium三维开发能力

2、天地图的Cesium插件优势

二、天地图资源申请

1、入口登记与账号认证

2、申请访问key

三、天地图Cesium集成

1、html主体定义

2、集成底图与标签

四、成果展示

1、三维地球展示

2、标签展示

3、地形展示

五、总结


📌 本文核心:从零讲解Cesium集成天地图三维底图全流程,包含天地图密钥申请、前端环境搭建、底图+标注图层集成、实战效果展示,代码开箱即用,适合WebGIS初学者及项目落地参考。

🔥 适用场景:三维可视化系统、智慧园区/城市GIS平台、地理数据分析系统、轻量化三维地球展示项目


一、前言

1、Cesium三维开发能力

在WebGIS三维开发领域,CesiumJS绝对是目前开源生态中最主流、最成熟的解决方案。作为一款开源的三维地球可视化引擎,它无需依赖任何插件,纯前端JS即可实现高精度的三维地球渲染,完美适配浏览器端各类地理信息展示需求。

相比于传统的二维地图框架,Cesium的核心优势非常突出:原生支持WGS84经纬度坐标系、高精度全球地形地貌渲染、海量瓦片地图加载、模型图层叠加、视角自由切换、飞行漫游、空间测量等功能。同时具备极佳的跨端兼容性和性能优化机制,能够支撑中小型项目的轻量化三维场景搭建,也是目前智慧GIS、应急测绘、实景三维项目的首选前端引擎。

但在实际项目开发中,Cesium原生底图存在明显短板:默认的Ion底图加载速度慢、国内访问卡顿、部分区域影像精度不足,且商用有一定限制,完全无法满足国内政企项目、商用GIS系统的落地需求。这也是我们需要接入国内合规、高精度、免费可用的天地图服务的核心原因。

2、天地图的Cesium插件优势

天地图(国家地理信息公共服务平台)是国内官方权威的地理信息服务平台,提供免费、合规、高精度的全球影像、矢量、标注、地形等地图服务,完全适配国内GIS项目的合规要求,无版权风险,是替代Cesium原生底图的最优方案。

针对Cesium三维开发场景,天地图提供了专属的适配插件和标准化WMTS、XYZ瓦片服务接口,无需复杂适配即可快速集成。相比于第三方地图服务,天地图Cesium适配方案有三大核心优势:

  1. 兼容性强:完美适配各版本Cesium引擎,支持影像底图、矢量底图、中文标注图层分层加载,解决原生底图无精准中文地名的痛点;

  2. 访问稳定:国内服务器部署,加载速度快、延迟低,彻底解决Cesium官方底图国内访问卡顿、加载失败问题;

3.免费合规:个人开发者免费申请密钥即可使用,小额调用完全满足日常开发和中小型项目上线需求,政企项目可申请商用授权,合规性拉满。

本文将结合本人实际项目落地经验,完整复盘从密钥申请、环境搭建、代码集成到效果展示的全流程,全程无冗余理论,全部干货实操。

二、天地图资源申请

想要在Cesium中调用天地图地图服务,必须先申请官方访问Key,所有地图瓦片请求都需要携带密钥鉴权,无密钥会直接请求失败、图层无法加载。下面是最新、最详细的申请流程,避开网上老旧教程的坑点。

1、入口登记与账号认证

  1. 打开天地图官方官网:国家地理信息公共服务平台 天地图,点击右上角【注册】按钮,完成手机号注册;

  2. 注册登录后,必须完成个人实名认证(免费),未认证账号无法创建应用、无法申请密钥;

  3. 认证通过后,进入官网控制台,找到【开发管理】-【应用管理】功能入口,这是创建服务密钥的核心入口。

💡 避坑提示:很多新手申请失败的原因是应用类型选错,前端Cesium网页开发,务必选择【Web服务】类型,不要选移动端、服务端类型,否则密钥无法正常鉴权。

2、申请访问key

  1. 在应用管理页面,点击【创建新应用】,自定义应用名称(例如:Cesium三维地图开发测试),应用类型选择【浏览器端】,这里一定要注意,根据我们实际的服务类型来确定,老版的天地图接口可以混用,现在接口更新后,key值不能混用,填写简单应用描述即可提交;
  1. 应用创建成功后,在应用详情页,即可获取访问密钥(tk),密钥为32位十六进制字符串,这是我们后续代码中需要用到的核心参数;以下是我的个人账号,这个号也已经注册有小两年了,时间真实飞速。
  1. 密钥生效无需审核,创建完成即可直接使用,个人开发者默认免费配额足够日常开发、本地测试和小型项目上线使用。截止2026年9月1日,天地图的配额信息如下:

| 类别 | 服务名称 | 个人开发者 | 工商企业 | 政府机构 |

类别 服务名称 日配额 日配额 日配额
地图API 影像底图 10000 3000000 5000000
地图API 矢量底图 10000 3000000 5000000
地图API 矢量注记 10000 3000000 5000000
地图API 影像注记 10000 3000000 5000000
地图API 地形晕渲 10000 3000000 5000000
地图API 地形注记 10000 3000000 5000000
地图API 矢量英文注记 10000 3000000 5000000
地图API 影像英文注记 10000 3000000 5000000
地图API 全球境界 10000 3000000 5000000
地图API 三维地名 10000 3000000 5000000
地图API 三维地形 10000 3000000 5000000
Web服务API 静态地图 3000 6000000 8000000
Web服务API 行政区划服务 3000 6000000 8000000
Web服务API 逆地理编码 7000 6000000 8000000
Web服务API 地理编码 7000 6000000 8000000
Web服务API 公交规划 3000 6000000 8000000
Web服务API 驾车规划 3000 6000000 8000000
Web服务API 地图搜索 3000 6000000 8000000

💡 开发建议:本地开发调试时,可直接使用密钥;项目正式上线后,建议配置域名白名单,防止密钥被盗用,减少异常调用损耗。

三、天地图Cesium集成

本次实战采用原生HTML+JS 开发,无需Vite、Vue、Webpack等工程化工具,极简环境、零配置,新手直接复制代码即可运行,快速验证集成效果。核心实现:初始化Cesium三维地球、加载天地图影像底图、叠加中文地名标注图层。为了方便大家学习,天地图官方也推出了Cesium集成教程,具体地址如下:天地图三维集成参考

为了方便大家学习,我这里将官方的内容拆解成可复制的教程,跟着博主一起来走进三维的世界吧。

天地图三维地名服务和地形服务需要利用 cesium 开源三维地球API与天地图扩展插件共同使用,目前支持cesuim1.108。天地图三维地名服务和三维地形服务对所有用户开放。

1、html主体定义

首先搭建基础HTML结构,引入Cesium官方CDN资源,定义三维地球容器,设置页面全屏样式,保证三维场景铺满屏幕。

完整基础HTML代码如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <title>天地图三维服务接入</title>
    <script type="text/javascript" cesium="true" src="https://api.tianditu.gov.cn/cdn/demo/sanwei/static/cesium/Cesium.js"></script>
    <script type="text/javascript" cesium="true" src="https://api.tianditu.gov.cn/cdn/plugins/cesium/Cesium_ext_min.js"></script>
    <script type="text/javascript" cesium="true" src="https://api.tianditu.gov.cn/cdn/plugins/cesium/long.min.js"></script>
    <script type="text/javascript" cesium="true" src="https://api.tianditu.gov.cn/cdn/plugins/cesium/bytebuffer.min.js"></script>
    <script type="text/javascript" cesium="true" src="https://api.tianditu.gov.cn/cdn/plugins/cesium/protobuf.min.js"></script>
    <link rel="stylesheet" cesium="true" href="https://api.tianditu.gov.cn/cdn/demo/sanwei/static/cesium/Widgets/widgets.css">
    <style>
        html, body{
            margin: 0;
            padding: 0;
            overflow: hidden;
        }

        #cesiumContainer {
            width: 100%;
            height: 100%;
        }

        #cesiumContainer .cesium-viewer-bottom{
            display: none;
        }
    </style>
</head>
<body>
    <div id="cesiumContainer"></div>
</body>
</html>

💡 版本说明:本文采用1.108稳定版Cesium,兼容性极佳,避免新版本API变动导致的报错,适合稳定开发。如果不是最新想尝鲜,可以直接使用该版本即可。

2、集成底图与标签

核心逻辑:关闭Cesium默认底图,通过天地图WMTS服务接口,分别加载卫星影像底图中文地名标注图层,两层叠加实现高清三维地图效果。将下方代码写入页面script标签中,替换空白脚本区域。

javascript 复制代码
<script>
    var token = '你申请的key';
    // 服务域名
    var tdtUrl = 'https://t{s}.tianditu.gov.cn/';
    // 服务负载子域
    var subdomains=['0','1','2','3','4','5','6','7'];

    // cesium 初始化
    var viewer = new Cesium.Map('cesiumContainer', {
        shouldAnimate: true, //是否允许动画
        selectionIndicator: false,
        baseLayerPicker: false,
        fullscreenButton: false,
        geocoder: false,
        homeButton: false,
        infoBox: false,
        sceneModePicker: false,
        timeline: false,
        navigationHelpButton: false,
        navigationInstructionsInitiallyVisible: false,
        showRenderLoopErrors: false,
        shadows: false,
    });

    // 抗锯齿
    viewer.scene.fxaa = true;
    viewer.scene.postProcessStages.fxaa.enabled=false;
    // 水雾特效
    viewer.scene.globe.showGroundAtmosphere = true;
    // 设置最大俯仰角,[-90,0]区间内,默认为-30,单位弧度
    viewer.scene.screenSpaceCameraController.constrainedPitch = Cesium.Math.toRadians(-20);
    viewer.scene.screenSpaceCameraController.autoResetHeadingPitch = false;
    viewer.scene.screenSpaceCameraController.inertiaZoom = 0.5;
    viewer.scene.screenSpaceCameraController.minimumZoomDistance = 50;
    viewer.scene.screenSpaceCameraController.maximumZoomDistance = 20000000;
    viewer.scene.screenSpaceCameraController.zoomEventTypes = [
        Cesium.CameraEventType.RIGHT_DRAG,
        Cesium.CameraEventType.WHEEL,
        Cesium.CameraEventType.PINCH,
    ];
    viewer.scene.screenSpaceCameraController.tiltEventTypes = [
        Cesium.CameraEventType.MIDDLE_DRAG,
        Cesium.CameraEventType.PINCH,
        {
            eventType: Cesium.CameraEventType.LEFT_DRAG,
            modifier: Cesium.KeyboardEventModifier.CTRL,
        },
        {
            eventType: Cesium.CameraEventType.RIGHT_DRAG,
            modifier: Cesium.KeyboardEventModifier.CTRL,
        },
    ];
    // 取消默认的双击事件
    viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

    // 叠加影像服务
    var imgMap = new Cesium.UrlTemplateImageryProvider({
        url: tdtUrl + 'DataServer?T=img_w&x={x}&y={y}&l={z}&tk=' + token,
        subdomains: subdomains,
        tilingScheme : new Cesium.WebMercatorTilingScheme(),
        maximumLevel : 18
    });
    viewer.imageryLayers.addImageryProvider(imgMap); 

    // 叠加国界服务
    var iboMap = new Cesium.UrlTemplateImageryProvider({
        url: tdtUrl + 'DataServer?T=ibo_w&x={x}&y={y}&l={z}&tk=' + token,
        subdomains: subdomains,
        tilingScheme : new Cesium.WebMercatorTilingScheme(),
        maximumLevel : 10
    });
    viewer.imageryLayers.addImageryProvider(iboMap);

    // 叠加地形服务
    var terrainUrls = new Array();

    for (var i = 0; i < subdomains.length; i++){
        var url = tdtUrl.replace('{s}', subdomains[i]) + 'mapservice/swdx?T=elv_c&tk=' + token;
        terrainUrls.push(url);
    }

    var provider = new Cesium.GeoTerrainProvider({
        urls: terrainUrls
    });

    viewer.terrainProvider = provider;

    // 将三维球定位到中国
    viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(103.84, 31.15, 17850000),
        orientation: {
            heading :  Cesium.Math.toRadians(348.4202942851978),
            pitch : Cesium.Math.toRadians(-89.74026687972041),
            roll : Cesium.Math.toRadians(0)
        },
        complete:function callback() {
            // 定位完成之后的回调函数
        }
    });

    // 叠加三维地名服务
    var wtfs = new Cesium.GeoWTFS({
        viewer,
        //三维地名服务,使用wtfs服务
        subdomains:subdomains,
        metadata:{
            boundBox: {
                minX: -180,
                minY: -90,
                maxX: 180,
                maxY: 90
            },
            minLevel: 1,
            maxLevel: 20
        },
        depthTestOptimization: true,
        dTOElevation: 15000,
        dTOPitch: Cesium.Math.toRadians(-70),
        aotuCollide: true, //是否开启避让
        collisionPadding: [5, 10, 8, 5], //开启避让时,标注碰撞增加内边距,上、右、下、左
        serverFirstStyle: true, //服务端样式优先
        labelGraphics: {
            font:"28px sans-serif",
            fontSize: 28,
            fillColor:Cesium.Color.WHITE,
            scale: 0.5,
            outlineColor:Cesium.Color.BLACK,
            outlineWidth: 2,
            style:Cesium.LabelStyle.FILL_AND_OUTLINE,
            showBackground:false,
            backgroundColor:Cesium.Color.RED,
            backgroundPadding:new Cesium.Cartesian2(10, 10),
            horizontalOrigin:Cesium.HorizontalOrigin.LEFT,
            verticalOrigin:Cesium.VerticalOrigin.TOP,
            eyeOffset:Cesium.Cartesian3.ZERO,
            pixelOffset: new Cesium.Cartesian2(5, 5),
            disableDepthTestDistance:undefined
        },
        billboardGraphics: {
            horizontalOrigin:Cesium.HorizontalOrigin.CENTER,
            verticalOrigin:Cesium.VerticalOrigin.CENTER,
            eyeOffset:Cesium.Cartesian3.ZERO,
            pixelOffset:Cesium.Cartesian2.ZERO,
            alignedAxis:Cesium.Cartesian3.ZERO,
            color:Cesium.Color.WHITE,
            rotation:0,
            scale:1,
            width:18,
            height:18,
            disableDepthTestDistance:undefined
        }
    });

    //三维地名服务,使用wtfs服务
    wtfs.getTileUrl = function(){
        return tdtUrl + 'mapservice/GetTiles?lxys={z},{x},{y}&VERSION=1.0.0&tk='+ token; 
    }

    // 三维图标服务
    wtfs.getIcoUrl = function(){
        return tdtUrl + 'mapservice/GetIcon?id={id}&tk='+ token;
    }

    wtfs.initTDT([{"x":6,"y":1,"level":2,"boundBox":{"minX":90,"minY":0,"maxX":135,"maxY":45}},{"x":7,"y":1,"level":2,"boundBox":{"minX":135,"minY":0,"maxX":180,"maxY":45}},{"x":6,"y":0,"level":2,"boundBox":{"minX":90,"minY":45,"maxX":135,"maxY":90}},{"x":7,"y":0,"level":2,"boundBox":{"minX":135,"minY":45,"maxX":180,"maxY":90}},{"x":5,"y":1,"level":2,"boundBox":{"minX":45,"minY":0,"maxX":90,"maxY":45}},{"x":4,"y":1,"level":2,"boundBox":{"minX":0,"minY":0,"maxX":45,"maxY":45}},{"x":5,"y":0,"level":2,"boundBox":{"minX":45,"minY":45,"maxX":90,"maxY":90}},{"x":4,"y":0,"level":2,"boundBox":{"minX":0,"minY":45,"maxX":45,"maxY":90}},{"x":6,"y":2,"level":2,"boundBox":{"minX":90,"minY":-45,"maxX":135,"maxY":0}},{"x":6,"y":3,"level":2,"boundBox":{"minX":90,"minY":-90,"maxX":135,"maxY":-45}},{"x":7,"y":2,"level":2,"boundBox":{"minX":135,"minY":-45,"maxX":180,"maxY":0}},{"x":5,"y":2,"level":2,"boundBox":{"minX":45,"minY":-45,"maxX":90,"maxY":0}},{"x":4,"y":2,"level":2,"boundBox":{"minX":0,"minY":-45,"maxX":45,"maxY":0}},{"x":3,"y":1,"level":2,"boundBox":{"minX":-45,"minY":0,"maxX":0,"maxY":45}},{"x":3,"y":0,"level":2,"boundBox":{"minX":-45,"minY":45,"maxX":0,"maxY":90}},{"x":2,"y":0,"level":2,"boundBox":{"minX":-90,"minY":45,"maxX":-45,"maxY":90}},{"x":0,"y":1,"level":2,"boundBox":{"minX":-180,"minY":0,"maxX":-135,"maxY":45}},{"x":1,"y":0,"level":2,"boundBox":{"minX":-135,"minY":45,"maxX":-90,"maxY":90}},{"x":0,"y":0,"level":2,"boundBox":{"minX":-180,"minY":45,"maxX":-135,"maxY":90}}]);

</script>

💡 核心解析

  1. 采用天地图WMTS标准服务接口,相比传统XYZ瓦片,加载更稳定、层级精度更高;

  2. 分离影像层和标注层,可灵活控制标注显示/隐藏,适配不同项目需求;

  3. 关闭多余控件,简化页面效果,减少资源占用,提升三维场景渲染性能。

💡 常见报错解决:图层加载空白、控制台报错,90%是Key错误、应用类型选错、网络跨域问题,本地直接打开HTML即可测试,无需本地服务器。请注意,这里集成的是天地图的在线服务,如果您的开发环境不支持联网,请申请连接网络或者在能连接天地图的环境下使用。或者本地集成了瓦片服务才可以。经过以上的代码集成就可以实现Cesium三维开发,并且默认叠加了影像底图和中文标签,包括行政区划边界和地形数据。

四、成果展示

1、三维地球展示

代码部署完成后,直接打开HTML文件,即可加载出流畅、高清的三维地球场景。相比Cesium原生底图,天地图影像色彩更真实、清晰度更高,国内城市、地貌细节展示更精准,缩放至各级层级均无模糊、瓦片加载缺失的问题。

三维场景支持鼠标自由操作:左键拖拽旋转视角、滚轮缩放、右键拖拽平移,完全满足三维地球可视化的基础交互需求,场景渲染流畅,无卡顿、无闪烁。

2、标签展示

叠加中文标注图层后,地图会精准展示全国及全球的城市名称、道路名称、水系、地标等中文信息,完美解决Cesium原生底图无精准中文地名、标注错乱的行业痛点。

标注图层与影像底图完美贴合,缩放层级同步适配,不会出现标注偏移、错位、重叠问题,整体视觉效果整洁、专业,完全可以直接用于项目展示、系统上线。

3、地形展示

除了可以展示影像底图、文字标签外,天地图还集成了地形数据。将页面进行旋转后,选择西南或者西藏地区进行地形展示,如下:

五、总结

本文从零完成了天地图+Cesium三维地图的全流程开发实践,从原理分析、密钥申请、代码集成到效果落地,全程基于实战场景,代码极简可复用,规避了新手开发中常见的密钥配置、图层加载、适配兼容等坑点。简单总结本次开发的核心要点:

  1. Cesium原生底图不适用于国内项目,天地图作为官方合规GIS服务,是三维地图项目的最优替代方案;

  2. 天地图集成核心是密钥申请与WMTS服务接口适配,选对Web服务应用类型是集成成功的关键;

  3. 分层加载影像底图和中文标注,可实现高清、流畅、适配国内场景的三维地球效果,满足绝大多数WebGIS三维可视化需求。

后续可以基于本文基础版本,拓展地形加载、点位标记、模型叠加、轨迹漫游、空间测量、行政区划高亮等功能,快速搭建完整的三维GIS可视化平台。如果本文对你有帮助,欢迎点赞+收藏+关注,后续持续更新Cesium三维开发、天地图进阶实战、GIS项目落地干货!有任何集成问题欢迎评论区交流,一一回复!行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。

相关推荐
fxshy5 天前
WebGIS 游戏化实践:基于 Cesium + Vue3 实现全球飞行模拟系统:从球体坐标、飞行动力学到地形碰撞实战
游戏·vue3·cesium·webgis·飞行模拟
新中地GIS开发老师12 天前
WebGIS开发学生作品 | 基于无人机影像的烟草检测智能体与数字化管理平台
vue·web·mapbox·webgis
万亿少女的梦1681 个月前
基于Vue、Vite与CesiumJS的江西省铜矿资源WebGIS系统设计
vue·vite·cesiumjs·webgis·空间数据可视化
新中地GIS开发老师1 个月前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
REDcker1 个月前
Cesium三维WebGIS入门详解
前端·gis·web·cesium·webgis
新中地GIS开发老师1 个月前
零基础WebGIS开发入门 | GeoJSON数据持久化
前端·javascript·gis·webgis·三维gis开发
新中地GIS开发老师1 个月前
地信职业百科④:GIS开发工程师
前端·数据库·gis·webgis·三维gis开发
Ai尚研修-贾莲2 个月前
基于Claude Code与Codex双Agent协作的WebGIS全链路开发
codex·webgis·ai-agent·claude code·maplibre·openclaw·leaflet交互地图
梦想的初衷~2 个月前
《双 Agent 工作台 + 全栈 GIS 项目搭建:前端地图/空间数据库/后端/云部署指南》
人工智能·echarts·leaflet·webgis·ai 辅助编程