Cesium引入天地图、高德、百度地图

这里借助了ceisum-map开源项目进行了实现。

cesium-map中的百度地图存在一定问题,使用矢量地图的时候,感觉地图的样式不太理想,而且卫星底图仅显示了东半球,所以自己写了个一个提供器,也存在一定的问题,在0°线位置,会有一条缝隙,尝试解决了一番,还是有这么个问题,等我研究明白了再修改吧

主要代码如下:

BaiduImageryProvider.js

javascript 复制代码
// 百度地图图层提供者
import * as Cesium from "cesium";

class CustomBaiduImageryProvider {
	constructor(options = {}) {
		// 使用正确的百度地图瓦片地址
		this._url = 'http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1';
		this._tileWidth = 256;
		this._tileHeight = 256;
		this._maximumLevel = 18;
		this._minimumLevel = 0;

		// 使用之前可以工作的投影参数
		let southwestInMeters = new Cesium.Cartesian2(-33554054, -33746824);
		let northeastInMeters = new Cesium.Cartesian2(33554054, 33746824);
		this._tilingScheme = new Cesium.WebMercatorTilingScheme({
			rectangleSouthwestInMeters: southwestInMeters,
			rectangleNortheastInMeters: northeastInMeters
		});

		this._rectangle = this._tilingScheme.rectangle;
		this._credit = undefined;
		this._ready = true;
	}

	get url() {
		return this._url;
	}

	get tileWidth() {
		return this._tileWidth;
	}

	get tileHeight() {
		return this._tileHeight;
	}

	get maximumLevel() {
		return this._maximumLevel;
	}

	get minimumLevel() {
		return this._minimumLevel;
	}

	get tilingScheme() {
		return this._tilingScheme;
	}

	get rectangle() {
		return this._rectangle;
	}

	get credit() {
		return this._credit;
	}

	get ready() {
		return this._ready;
	}

	get hasAlphaChannel() {
		return true;
	}

	getTileCredits() {
		return [];
	}

	requestImage(x, y, level) {
		if (!this._ready) {
			throw new Cesium.DeveloperError('requestImage must not be called before the imagery provider is ready.');
		}

		const xTiles = this._tilingScheme.getNumberOfXTilesAtLevel(level);
		const yTiles = this._tilingScheme.getNumberOfYTilesAtLevel(level);

		let baiduX = Math.floor(x - xTiles / 2);
		let baiduY = Math.floor(yTiles / 2 - y - 1);

		let url = this._url
			.replace('{x}', baiduX)
			.replace('{y}', baiduY)
			.replace('{z}', level)
			.replace('{s}', Math.floor(Math.random() * 10));

		return Cesium.ImageryProvider.loadImage(this, url);
	}
}

export default CustomBaiduImageryProvider;

LoadBaseMap.vue

html 复制代码
<template>
  <div>
    <div
        ref="cesiumContainer"
        id="cesiumContainer"
        class="cesium-container"
        style="width: 100%; height: 100vh;"
    >
      
    </div>
    <div class="layer-switcher">
      <label for="baseMap">选择底图:</label>
      <select id="baseMap" v-model="selectedBaseMap" @change="switchBaseMap">
        <option value="cesium">Cesium 默认</option>
        <option value="tianditu">天地图</option>
        <option value="gaode">高德地图</option>
        <option value="baidu">百度地图</option>
      </select>
    </div>
  </div>
</template>

<script setup>
import { onMounted, ref, reactive } from 'vue';
import {
  BingMapsImageryProvider,
  BingMapsStyle,
  Cartesian3,
  Color, HeadingPitchRange,
  Ion,
  Viewer
} from "cesium";
import "cesium/Build/Cesium/Widgets/widgets.css";
import CustomBaiduImageryProvider from "../cesium-extensions/BaiduImageryProvider.js";
import { AMapImageryProvider,BaiduImageryProvider,TdtImageryProvider }  from '@cesium-china/cesium-map'
import * as Cesium from "cesium";

const cesiumContainer = ref(null)
const viewer = ref(null)
const selectedBaseMap = ref('cesium')

// 定义各个底图的 ImageryProvider
const imageryProviders = reactive({
  cesium: [new BingMapsImageryProvider({
    url: 'https://dev.virtualearth.net',
    key: '', // Cesium默认使用Bing Maps,需要替换为你的密钥,登录cesium控制台获取
    mapStyle: BingMapsStyle.AERIAL,
  })],
  tianditu: [new TdtImageryProvider({
    style: 'vec', //style: vec、cva、img、cia、ter 
    key:'', // 需去天地图申请
  }),new TdtImageryProvider({
    style: 'cva', //style: vec、cva、img、cia、ter 
    key:'', // 需去天地图申请
  })],
  gaode: [new AMapImageryProvider({
    style: 'img', // style: img、elec、cva
    crs: 'WGS84' // 使用84坐标系,默认为:GCJ02
  }),
    new AMapImageryProvider({
    style: 'cva', // style: img、elec、cva
    crs: 'WGS84' // 使用84坐标系,默认为:GCJ02
  })],
  // 使用cesium-map 组件实现
  /*baidu: [new BaiduImageryProvider({
    url:"http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1",
    style: 'normal', // style: img、vec、normal、dark
    crs: 'WGS84' // 使用84坐标系,默认为:BD09
  })],*/
  // 自定义百度地图提供器
  baidu:[new CustomBaiduImageryProvider()]
})

onMounted(() => {
  // 设置 Cesium Ion 访问令牌
  Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhNmQ5NDYyNi1lZTdhLTRiYTItODFiZi1mYzNiYWNjNDFjMzgiLCJpZCI6NTk3MTIsImlhdCI6MTY2MDE4MDAyNX0.bDTaHEah0hRjUyJWz0hyxIL0Fg63awPXV26OmQ5MCdM'; // 替换为你的访问令牌

  viewer.value = new Viewer('cesiumContainer', {
    animation: false, // 移除动画控件
    timeline: false, // 移除时间轴控件
    geocoder: false, // 移除地理编码控件
    homeButton: false, // 移除主页按钮
    sceneModePicker: false, // 移除场景模式选择器
    selectionIndicator: false, // 移除选择指示器
    fullscreenButton: false, // 移除全屏按钮
    vrButton: false // 移除 VR 按钮
  });

  // 添加默认实体或其他初始化操作
  const tiananmenEntity = viewer.value.entities.add({
    position: Cartesian3.fromDegrees(116.397128, 39.916527),
    point: { pixelSize: 10, color: Color.RED },
    name: '天安门',
  })
  viewer.value.flyTo(tiananmenEntity,{
    duration: 3, // 飞行时间,单位秒
    offset: new HeadingPitchRange(
        0, // Heading,航向角,0表示正北方向
        Cesium.Math.toRadians(-80), // Pitch,俯仰角,负值表示向下俯视
        405000 // Range,距离目标的距离,增加此值以提高视角高度
    )
  })
});
const switchBaseMap = () => {
  // 移除当前的底图图层
  if (viewer.value.imageryLayers.length > 0) {
    viewer.value.imageryLayers.removeAll()
  }

  let newProviders = imageryProviders[selectedBaseMap.value];
  
  for (let i = 0; i < newProviders.length; i++) {
    viewer.value.imageryLayers.addImageryProvider(newProviders[i])
  }
  
}
</script>

<style>
.cesium-container {
  width: 100%;
  height: 100%;
  position: relative;
}
/* 隐藏页面底部的 Cesium logo 和数据归属 */
.cesium-viewer .cesium-widget-credits {
  display: none !important; /* 隐藏整个 Cesium 控件 */
}

/* 隐藏 右上角的 Imagery 和 Navigation instructions */
.cesium-viewer .cesium-viewer-toolbar {
  display: none !important; /* 隐藏工具栏 */
}

.layer-switcher {
  position: absolute;
  top: 10px;
  left: 10px;
  background: rgba(42, 42, 42, 0.8);
  padding: 10px;
  border-radius: 4px;
  color: white;
  z-index: 1;
}

.layer-switcher select {
  margin-left: 5px;
  padding: 2px 5px;
  border-radius: 2px;
  border: none;
}
</style>

源码

相关推荐
xiangshangdemayi2 个月前
vue3环境下mapbox本地部署极速入门
部署·矢量切片·mapbox·内网·离线·天地图
Amarantine、沐风倩✨2 个月前
实现uniapp天地图边界范围覆盖
前端·uni-app·移动端·天地图·全端
ikgade2 个月前
Leaflet 接入天地图服务
javascript·html·leaflet·天地图
方与圆之帆1 年前
超图iClient3DforCesium地形、影像、模型、在线影像交互示例
超图iclient3d·ceisum·bim模型交互示例