返回 导航

Vue.js

hangge.com

Vue.js - 集成Cesium构建三维可视化场景教程10(使用高德地图底图)

作者:hangge | 2026-07-16 08:46
    前文我演示了如何在 Vue.js + Cesium 的工程里接入天地图影像(点击查看),解决了使用默认地图在国内访问速度慢、合规性等常见问题。本文接着演示如何接入国内另一个比较流行的地图:高德(Amap)地图作为底图。

十、使用高德地图作为底图

1,使用样例

下面代码关闭 Cesium 默认底图并接入高德地图服务,同时实现影像地图与矢量地图的加载与切换,以及标记的显示与隐藏。
<template>
    <div class="map-container">
        <div ref="cesiumContainer" class="cesium-container"></div>

        <!-- 加载状态 -->
        <div v-if="loading" class="loading-overlay">
            <div class="loading-spinner"></div>
            <p>加载三维场景中...</p>
        </div>

        <!-- 工具栏 -->
        <div class="toolbar" v-if="!loading">
            <button @click="switchBaseLayer('img')">影像地图</button>
            <button @click="switchBaseLayer('vec')">矢量地图</button>
            <button @click="toggleLabels()">
                {{ showLabels ? '隐藏标注' : '显示标注' }}
            </button>
        </div>
    </div>
</template>

<script>
// 引入 Cesium 核心类
import * as Cesium from "cesium";

export default {
    name: 'CesiumAmapViewer',

    data() {
        return {
            viewer: null,
            loading: true,
            // 图层管理
            layers: {
                img: null,      // 影像底图
                vec: null,      // 矢量底图
                labels: null    // 注记图层
            },
            // 当前显示状态
            showLabels: false
        }
    },

    mounted() {
        // 确保 Cesium 已加载
        if (typeof Cesium === 'undefined') {
            console.error('Cesium 未加载,请检查配置')
            this.loading = false
            return
        }

        // 初始化 Cesium 场景
        this.initCesium()
    },

    beforeDestroy() {
        // 组件销毁时清理资源
        this.destroyCesium()
    },

    methods: {
        // 初始化 Cesium
        async initCesium() {
            try {
                // 创建 Viewer 实例,关闭默认底图
                this.viewer = new Cesium.Viewer(this.$refs.cesiumContainer, {
                    imageryProvider: false,      // 不显示默认底图
                    baseLayerPicker: false,      // 关闭默认图层选择器
                    animation: false,            // 隐藏动画控件
                    timeline: false,             // 隐藏时间轴
                    sceneModePicker: false,      // 隐藏2D/3D切换按钮
                    navigationHelpButton: false, // 隐藏帮助按钮
                    fullscreenButton: true,      // 保留全屏按钮
                    geocoder: false,             // 隐藏搜索框
                    homeButton: true,            // 保留Home按钮
                    infoBox: false,              // 隐藏信息框
                    selectionIndicator: false,   // 隐藏选取指示器
                    shadows: true,               // 启用阴影
                    shouldAnimate: true,         // 自动播放动画
                    scene3DOnly: true            // 仅3D渲染以节省内存
                })

                // 强制重新计算画布尺寸
                this.viewer.canvas.width = this.viewer.container.clientWidth;
                this.viewer.canvas.height = this.viewer.container.clientHeight;
                this.viewer.resize(); // 核心方法:告知 Cesium 容器大小已变

                // 设置初始相机位置和视角
                this.setInitialView()

                // 添加高德地图图层
                await this.addAmapLayers()

                // 加载完成
                this.loading = false

                console.log('Cesium 场景初始化完成,已集成高德地图')
            } catch (error) {
                console.error('初始化 Cesium 失败:', error)
                this.loading = false
            }
        },

        // 创建高德地图影像服务提供者
        createAmapProvider(layerType) {
            // 高德地图瓦片服务地址模板
            const templates = {
                // 影像地图
                img: `https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}`,
                // 矢量地图
                vec: `https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}`,
                // 矢量注记(需要叠加在矢量图上)
                labels: `https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}`,
            }

            // 子域名,用于负载均衡
            const subdomains = ['1', '2', '3', '4']

            // 确保请求的层级在有效范围内
            const maxLevel = 18  // 高德地图最大缩放级别
            const minLevel = 3   // 最小缩放级别

            return new Cesium.UrlTemplateImageryProvider({
                url: templates[layerType],
                subdomains: subdomains,
                minimumLevel: minLevel,
                maximumLevel: maxLevel,
                credit: new Cesium.Credit('© 高德地图')
            })
        },

        // 添加高德地图所有图层
        async addAmapLayers() {
            // 创建各图层提供者
            const imgProvider = this.createAmapProvider('img')
            const vecProvider = this.createAmapProvider('vec')
            const labelsProvider = this.createAmapProvider('labels')

            // 添加到场景中
            this.layers.img = this.viewer.imageryLayers.addImageryProvider(imgProvider)
            this.layers.vec = this.viewer.imageryLayers.addImageryProvider(vecProvider)
            this.layers.labels = this.viewer.imageryLayers.addImageryProvider(labelsProvider)

            // 默认显示影像地图和注记
            this.layers.img.show = true
            this.layers.vec.show = false
            this.layers.labels.show = false

            // 确保注记图层在最上层
            this.viewer.imageryLayers.raiseToTop(this.layers.labels)

            // 添加版权信息
            this.viewer.credits.addCredit(
                new Cesium.Credit('高德地图 GS(2023)6379号', true)
            )
        },

        // 设置初始位置(例如:北京天安门)
        setInitialView() {
            const initialPosition = Cesium.Cartesian3.fromDegrees(116.3974, 39.9093, 2000)
            this.viewer.camera.setView({
                destination: initialPosition,
                orientation: {
                    heading: Cesium.Math.toRadians(0),
                    pitch: Cesium.Math.toRadians(-90),
                    roll: 0
                }
            })
        },

        // 切换底图类型
        switchBaseLayer(type) {
            if (!this.viewer) return

            // 隐藏所有基础图层
            Object.keys(this.layers).forEach(key => {
                if (key !== 'labels') {
                    this.layers[key].show = false
                }
            })

            // 根据类型显示对应图层
            switch (type) {
                case 'img':
                    this.layers.img.show = true
                    break
                case 'vec':
                    this.layers.vec.show = true
                    break
            }

            // 确保注记图层在最上层
            if (this.showLabels) {
                this.viewer.imageryLayers.raiseToTop(this.layers.labels)
            }
        },

        // 切换注记显示/隐藏
        toggleLabels() {
            this.showLabels = !this.showLabels
            this.layers.labels.show = this.showLabels

            // 如果显示注记,将其置于最上层
            if (this.showLabels) {
                this.viewer.imageryLayers.raiseToTop(this.layers.labels)
            }
        },

        // 销毁 Cesium 资源
        destroyCesium() {
            if (this.viewer && !this.viewer.isDestroyed()) {
                this.viewer.destroy()
                this.viewer = null
            }
        },
    }
}
</script>

<style scoped>
.layer-container {
    position: relative;
    width: 100%;
    height: 100%;
}


.cesium-container {
    width: 100%;
    height: 100%;
}

.loading-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 1000;
    color: white;
}

.loading-spinner {
    border: 4px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    border-top: 4px solid #42b983;
    width: 50px;
    height: 50px;
    animation: spin 1s linear infinite;
    margin-bottom: 15px;
}

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

.toolbar {
    position: absolute;
    top: 20px;
    left: 20px;
    z-index: 999;
    display: flex;
    gap: 10px;
}

.toolbar button {
    padding: 8px 15px;
    background: rgba(40, 44, 52, 0.8);
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    transition: background 0.3s;
}

.toolbar button:hover {
    background: rgba(66, 185, 131, 0.8);
}
</style>

2,运行效果

(1)页面打开后默认会展示高德影像底图。

(2)点击工具栏的“显示标注”可以将注记图层叠加在最上面。

(3)点击“矢量地图”按钮可以将底图实时切换为矢量地图。

(4)切换为矢量地图后,上面再添加注记图层效果如下:
评论

全部评论(0)

回到顶部