1 Cesium
1.1 安装Cesium
# 安装Cesium
pnpm install cesium --save
# 安装指定版本的Cesium
pnpm install cesium@1.106
# 卸载
pnpm uninstall cesium
1.2 安装Cesium自动导入插件
pnpm i vite-plugin-cesium vite -D
# 安装Cesium类型以来 1.106版本之后不需要
pnpm i @types/cesium -D
1.2.1 在vite.config.js配置Cesium插件
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import cesium from 'vite-plugin-cesium'
export default defineConfig({
plugins: [vue(), cesium()]
});
1.3 Cesium初始化示例
<script setup lang="ts">
import { ref, watch, nextTick, onMounted } from 'vue'
import {
Viewer,
Camera,
Rectangle,
// GeographicTilingScheme,
// Ellipsoid,
UrlTemplateImageryProvider,
JulianDate
} from 'cesium'
// Cesium组件参数类型
import type { CesiumViewerProps } from '@/components/cesiumViewer/CesiumViewerProps'
// 定义组件参数
const props = defineProps<CesiumViewerProps>()
const cesiumViewerRef = ref()
// Cesium的Viewer对象
let viewer: Viewer | undefined
// 初始化Cesium场景
const initCesiumViewer = () => {
// 设置Cesium的默认初始化视角
Camera.DEFAULT_VIEW_RECTANGLE = Rectangle.fromDegrees(75, 0, 140.0, 60)
/**
* 初始化Cesium的Viewer
*/
viewer = new Viewer(mapContainer.value, {
// 选中相机框:不显示相机框
selectionIndicator: false,
// 信息框
infoBox: false,
// 地图导航罗盘
navigation: false,
// 右上角位置搜索按钮
geocoder: false,
// 底图图层选择器
baseLayerPicker: false,
// 回到主视图按钮
homeButton: false,
// 视图选择按钮:2D、2.5D、3D
sceneModePicker: false,
// 仅仅是3D视图
scene3DOnly: true,
// 帮助按钮
navigationHelpButton: false,
// 当前时间动画器件
animation: false,
// 全屏按钮
fullscreenButton: false,
// 底部时间轴控件
timeline: false,
// 设置基础底图
baseLayer: new Cesium.ImageryLayer(
new Cesium.UrlTemplateImageryProvider({
// 天地图
url: "http://t{s}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=1d109683f4d84198e37a38c442d68311", // 影像
subdomains: "01234567",
maximumLevel: 18,
})
),
// // 设置基础地图
// imageryProvider: new UrlTemplateImageryProvider({
// // 使用Cesium自带的瓦片
// url: '../lib/Cesium/Assets/Textures/NaturalEarthII/{z}/{x}/{reverseY}.jpg',
// maximumLevel: 2,
// tilingScheme: new Cesium.GeographicTilingScheme({
// ellipsoid: Cesium.Ellipsoid.WGS84,
// // numberOfLevelZeroTilesX: 2,
// // numberOfLevelZeroTilesY: 1
// })
// })
})
// 移除logo
// viewer.cesiumWidget.creditContainer.style.display = "none"; // 隐藏logo
viewer.cesiumWidget.creditContainer.remove(); // 删除logo
// 关闭太阳光照
viewer.scene.globe.enableLighting = false
// 设置当前时间,防止晚上进入系统,看到的是黑的
viewer.clock.currentTime = JulianDate.fromIso8601('2023-09-18T07:00:33.013999999995576218Z') // 北京时间下午15点
}
// 销毁Cesium场景
const destroyCesiumViewer = () => {
viewer && viewer.destroy()
viewer = undefined
}
watch([() => props.visible], () => {
if (props.visible) {
nextTick(() => {
initCesiumViewer()
})
} else {
destroyCesiumViewer()
}
})
onMounted(() => {
if (props.visible) {
// 初始化三维场景
initCesiumViewer()
}
})
</script>
<template>
<div ref="cesiumViewerRef" v-if="visible" class="cesium-viewer"></div>
</template>
<style scoped lang="scss">
.cesium-viewer {
width: 100%;
height: 100%;
}
</style>
2 Leaflet
2.1 安装Leaflet
# 安装Leaflet依赖
pnpm install --save leaflet
# 安装ts类型定义
pnpm install @types/leaflet --save-dev
2.2 基础示例
<template>
<div v-if="visible" v-show="show" ref="mapContainer" class="leaflet-map"></div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, nextTick } from 'vue'
import { MapComponentProps } from '../MapComponent'
import * as L from 'leaflet'
import type { Map } from 'leaflet'
import 'leaflet/dist/leaflet.css'
// Leaflet组件参数
const props = defineProps({
visible: {
type: Boolean,
default: true,
},
show: {
type: Boolean,
default: true,
},
})
const mapContainer = ref()
let map: Map | undefined
// 组件初始化完成,初始化地图
onMounted(() => {
// 动态设置Leaflet地图容器的id
;(<HTMLElement>mapContainer.value).id = 'map' + Date.now() + Math.round(Math.random() * 1000)
if (props.visible && props.show) {
initMap()
}
})
// 当组件可见时初始化地图
watch([() => props.visible, () => props.show], () => {
// 组件是否可见
if (props.visible && props.show && !map) {
initMap()
} else if (!props.visible) {
destroyMap()
}
})
/**
* 初始地图
*/
const initMap = () => {
nextTick(() => {
_initMap()
})
}
/**
* 销毁地图
*/
const destroyMap = () => {
console.log('销毁地图')
map && map.remove && map.remove()
map = undefined
}
/**
* 初始地图
*/
const _initMap = () => {
map = L.map(mapContainer.value.id, {
minZoom: 0, // 设置地图的最小层级
maxZoom: 18, // 设置地图的最大层级
center: L.latLng(30.560407944979296, 115.97852713758685), // 设置地图的中心点
zoom: 4, // 设置地图初始化的层级
zoomControl: false, // 缩放控件是否可见
attributionControl: false, // 属性控件是否可见
})
// 加载图层
L.tileLayer('https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s,m&gl=CN&x={x}&y={y}&z={z}').addTo(map)
}
</script>
<style lang="scss" scoped>
.leaflet-map {
width: 100%;
height: 100%;
}
</style>
3 OpenLayers
3.1 安装依赖
pnpm install --save ol
3.2 基础示例
<template>
<div v-if="visible" v-show="show" class="openlayers-map" ref="mapContainer"></div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, nextTick } from 'vue'
import 'ol/ol.css'
import { Map, View } from 'ol'
import TileLayer from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'
import { fromLonLat, transform } from 'ol/proj'
import { MapComponentProps } from '../MapComponent.ts'
const props = defineProps({
// 地图是否可见
visible: {
type: Boolean,
default: true,
},
// 地图是否显示
show: {
type: Boolean,
default: true,
},
})
const mapContainer = ref('')
let map: Map | undefined
// 当组件可见时初始化地图
onMounted(() => {
if (props.visible && props.show) {
initMap()
}
})
// 当组件可见时初始化地图
watch([() => props.visible, () => props.show], () => {
// 组件是否可见
if (props.visible && props.show && !map) {
initMap()
} else if (!props.visible) {
destroyMap()
}
})
const initMap = () => {
nextTick(() => {
_initMap()
})
}
/**
* 销毁地图
*/
const destroyMap = () => {
console.log('销毁地图')
map && map.dispose && map.dispose()
map = undefined
}
/**
* 真正初始化地图
*/
const _initMap = () => {
if (map) {
return
}
// 初始化OpenLayer视图
const view = new View({
center: fromLonLat([115.97852713758685, 30.560407944979296], 'EPSG:3857'),
// center: [104.912777, 34.730746], // 地图中心点
zoom: 4,
// projection: 'EPSG:4326',// 设置地图的投影
})
const layer = new TileLayer({
source: new XYZ({
// url: 'http://t{0-7}.tianditu.com/DataServer?T=vec_w&tk=b9031f80391e6b65bd1dd80dcde1b097&x={x}&y={y}&l={z}',
url: 'https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}',
}),
})
// 初始化地图
map = new Map({
target: mapContainer.value,
layers: [layer],
view: view,
})
}
</script>
<style scoped lang="scss">
.openlayers-map {
width: 100%;
height: 100%;
}
</style>
4 MapBoxGL
4.1 安装依赖
# 安装依赖
pnpm install --save mapbox-gl
# 安装ts类型定义
pnpm install @types/mapbox-gl -D
4.2 初始化样例
<template>
<div v-if="visible" v-show="show" ref="mapContainer" class="mapbox-map"></div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, nextTick } from 'vue'
import { MapComponentProps } from '../MapComponent'
import 'mapbox-gl/dist/mapbox-gl.css'
import { Map } from 'mapbox-gl'
import type { Control } from 'mapbox-gl'
const props = defineProps(MapComponentProps)
const mapContainer = ref() // 承载地图的容器
let map: Map | undefined // MapBox地图对象
// 组件挂载完成并且地图可见,初始化地图
onMounted(() => {
if (props.visible && props.show) {
initMap()
}
})
// 当组件可见时初始化地图
watch([() => props.visible, () => props.show], () => {
// 组件是否可见,不可见则销毁地图
if (props.visible && props.show && !map) {
initMap()
} else if (!props.visible) {
destroyMap()
}
})
// 初始化地图
const initMap = () => {
nextTick(() => {
_initMap()
})
}
/**
* 销毁地图
*/
const destroyMap = () => {
console.log('销毁地图')
map && map.remove && map.remove()
map = undefined
}
const _initMap = () => {
// 初始化MapBox地图
map = new Map({
container: mapContainer.value,
// style: "mapbox://styles/mapbox/streets-v12",
// 必须要设置style、sources、layers,如果有字体,必须要设置glyphs属性
style: {
version: 8,
sources: {},
layers: [],
},
center: [115.97852713758685, 30.560407944979296],
zoom: 3,
attributionControl: false,
})
// @ts-ignore
const controls = map?._controls
controls.forEach((control: Control) => {
// 移除MapBox logo控件
if ('_updateLogo' in control) {
map && map.removeControl(control)
}
},
)
// 移除MapBox的权限校验
// @ts-ignore
map._authenticate = () => {
}
map.on('load', () => {
// 加载图层
map && map.addLayer({
id: 'GoogleImageLayer',
type: 'raster',
source: {
'type': 'raster',
'tiles': ['https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}'],
'tileSize': 256,
},
})
})
}
</script>
<style scoped>
.mapbox-map {
width: 100%;
height: 100%;
}
</style>
4.3 功能定制
4.3.1 修改源码方式
MapBox在内网使用时,accesstoken不能使用,导致局域网内地图服务不能使用,只需修改mapbox-gl.js文件中this._requestManager._customAccessToken,(e=>{if(e&&(false))
,框架就不会验证token,可内网部署。
// 改之前:this._requestManager._customAccessToken,(t=>{if(t&&(t.message===e.AUTH_ERR_MSG||401===t.status))
// 改制后:this._requestManager._customAccessToken,(t=>{if(t&&(false))
4.3.2 非修改源码方式,TS依赖检查报错(需要忽略报错)
// <div ref="mapRef" id="map"></div>
// const mapRef = ref()
// container: mapRef.value, // 地图容器
// 初始化地图
const map = new mapboxgl.Map({
container: 'map',
// style: "mapbox://styles/mapbox/streets-v12",
// 必须要设置style、sources、layers,如果有字体,必须要设置glyphs属性
style: {
version: 8,
sources: {},
layers: []
},
center: [130, 50],
zoom: 0
});
console.log("初始化地图完成:", map);
// 添加导航控件
map.addControl(new mapboxgl.NavigationControl(), 'top-left');
// 移除Token校验
// @ts-ignore
map._authenticate = () => {
console.log("移除Token校验");
}
map.on('load', function () {
console.log('Map Load')
// 初始化后加载栅格类型的地图
map.addLayer({
id: "GoogleImageLayer",
type: "raster",
source: {
"type": "raster",
"tiles": ["https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}"],
"tileSize": 256
}
});
})
4.3.3 移除默认控件
// ͨ通过设置css样式移除
// map._controls[0]._container.style.display = 'none'
let controls = map._controls;
controls.forEach(control => {
console.log("'_updateLogo' in control", '_updateLogo' in control)
// 移除logo控件
if('_updateLogo' in control){
map.removeControl(control)
}
// 移除地图属性控件
if('_attribHTML' in control){
map.removeControl(control)
}
})
5 Maplibre
maplibre是基于MapBox 1.x分支出来的,在使用上与Mapbox类似,但是移除了Mapbox的校验,默认添加了字体支持(未验证默认字体对中文的字体的支持情况)。
5.1 安装依赖
参考:visgl.github.io/react-map-g…
# 安装依赖
pnpm install maplibre-gl
# maplibre款式规范
@maplibre/maplibre-gl-style-spec
6 ArcGIS for JavaScript
依赖下载:developers.arcgis.com/javascript/…
7 GeoScene
7.1 安装依赖
# 创建vue项目
pnpm create vite my-vue-app --template vue
# 安装GeoScene
pnpm install @geoscene/core
# 安装指定版本
pnpm install @geoscene/core@4.23.14
pnpm view @geoscene/core versions
7.2 本地化配置
7.2.1 本地化资源依赖配置(内网)
// 导入GeoScene全局配置
import geosceneConfig from '@geoscene/core/config'
// 导入GeoScene的静态资源加载路径(如GeoScene微件的配置)
geosceneConfig.assetsPath = 'https://ynyth.jcdiq.cn/geoscene/assets'
// 设置字体库的访问路径,内网环境需要设置,不然地图绘制标签时找不到字体,显示不出标签文本。
geosceneConfig.fontsUrl = 'https://ynyth.jcdiq.cn/geoscene/fonts'
7.2.2 导入GeoScene地图样式
方法一:使用js语法
<script setup lang="ts">
// 亮色
import '@geoscene/core/assets/geoscene/themes/light/main.css'
// 暗色
// import '@geoscene/core/assets/geoscene/themes/dark/main.css'
</script>
方法二:使用CSS样式导入语法(全局导入)
<!--导入GeoScene地图组件的默认样式-->
<style lang="scss">
// 使用scss的@user
@use '@geoscene/core/assets/geoscene/themes/dark/main.css';
// 使用原生CSS的中的@import
// @import '@geoscene/core/assets/geoscene/themes/dark/main.css';
</style>
7.3 入门示例组件
<template>
<div ref="mapRef" class="geoscene-map"></div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import '@geoscene/core/assets/geoscene/themes/light/main.css'
import geosceneConfig from '@geoscene/core/config'
import Map from '@geoscene/core/Map'
import MapView from '@geoscene/core/views/MapView'
const props = defineProps<{
id: string
mapId: string
fixed: boolean
}>()
/**
* @ClassName GeoSceneMap
* @Description GeoScene地图组件
* @Author xuyizhuo
* @Date 2024/3/30 16:12
*/
const mapRef = ref<HTMLDivElement | string>('')
// GeoScene地图
let geosceneMap: GeoSceneMap | undefined
// 初始化地图
function initMap() {
console.log('init map')
// 设置静态资源的访问路径,内网环境需要设置,不然前端的样式有些问题
geosceneConfig.assetsPath = 'https://ynyth.jcdiq.cn/geoscene/assets'
// 设置字体库的访问路径,内网环境需要设置,不然地图绘制标签时找不到字体,显示不出标签文本。
geosceneConfig.fontsUrl = 'https://ynyth.jcdiq.cn/geoscene/fonts'
const map = new Map({
basemap: 'tianditu-vector', // 设置底图,
})
const mapView = new MapView({
container: mapRef.value, // 绘制地图的容器
map,
center: [104.02480673856877, 27.79702076736095], // 设置地图的中心点
// zoom: 5, // 设置地图的缩放层级,ArcGIS地图中有瓦片图层才会生效,建议优先使用比例尺设置。
scale: 36978595.474472, // 设置比例尺
// 移除默认的地图组件
ui: {
components: []
},
})
// 移除ArcGIS中所以的地图微件
// mapView.ui.components = []
}
onMounted(initMap)
</script>
<style lang="scss" scoped>
.geoscene-map {
width: 100%;
height: 100%;
}
</style>
<!--<style lang="scss">
@use '@geoscene/core/assets/geoscene/themes/light/main.css';
</style>-->
8 数据格式转换工具
8.1 terraformer
支持ArcGIS的Geometry与GeoJSON的项目转换
npm使用:www.npmjs.com/package/@te…
github仓库:github.com/terraformer…
# 依赖
pnpm install @terraformer/arcgis
# ts类型校验
pnpm i @types/terraformer__arcgis -D