Browse Source

feat: add Tianditu MapLayer skeleton with mapHelper/commonRefs

main
xiaosi 1 month ago
parent
commit
897fb338a7
  1. 71
      src/core/mapHelper.js
  2. 5
      src/layout/MainContainer.vue
  3. 71
      src/layout/MapLayer.vue
  4. 54
      src/utils/commonRefs.js

71
src/core/mapHelper.js

@ -0,0 +1,71 @@
/**
* 地图助手最小集
* maptalks@1.12.x 使用 checkSize 刷新容器尺寸
*/
class MapHelper {
_map = null
_originParent = null
_savedView = null
setMap(map) {
this._map = map
}
getMap() {
return this._map
}
toggleMapMode({ is2D = false, is3D = false } = {}) {
if (!this._map) return
if (is3D) {
this._map.setPitch(45)
this._map.setBearing(0)
this._map.config('dragRotate', true)
this._map.config('dragPitch', true)
}
if (is2D) {
this._map.setPitch(0)
this._map.setBearing(0)
this._map.config('dragRotate', false)
this._map.config('dragPitch', false)
}
}
replaceMapContainer(newParent) {
if (!this._map || !newParent) return
const el = this._map.getContainer()
this._originParent = this._originParent || el.parentNode
this._savedView = {
center: this._map.getCenter(),
zoom: this._map.getZoom(),
pitch: this._map.getPitch(),
bearing: this._map.getBearing(),
}
newParent.appendChild(el)
this._map.checkSize()
}
restoreMapContainer() {
if (!this._map || !this._originParent) return
const el = this._map.getContainer()
this._originParent.appendChild(el)
if (this._savedView) {
this._map.setCenter(this._savedView.center)
this._map.setZoom(this._savedView.zoom)
this._map.setPitch(this._savedView.pitch)
this._map.setBearing(this._savedView.bearing)
}
this._map.checkSize()
this._originParent = null
this._savedView = null
}
}
export default new MapHelper()

5
src/layout/MainContainer.vue

@ -3,6 +3,7 @@ import { ref, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import SideMenu from '@/layout/components/SideMenu.vue' import SideMenu from '@/layout/components/SideMenu.vue'
import TopBar from '@/layout/components/TopBar.vue' import TopBar from '@/layout/components/TopBar.vue'
import MapLayer from '@/layout/MapLayer.vue'
const route = useRoute() const route = useRoute()
const sidebarOpen = ref(false) const sidebarOpen = ref(false)
@ -34,7 +35,7 @@ function closeSidebar() {
<TopBar @toggle-sidebar="toggleSidebar" /> <TopBar @toggle-sidebar="toggleSidebar" />
</t-header> </t-header>
<t-content :class="s.content"> <t-content :class="s.content">
<!-- MapLayer mounts in Task 5; keep relative content for overlay -->
<MapLayer />
<router-view /> <router-view />
</t-content> </t-content>
</t-layout> </t-layout>
@ -89,7 +90,7 @@ function closeSidebar() {
.content { .content {
position: relative; position: relative;
height: 100%; height: 100%;
overflow: auto;
overflow: hidden;
background: #eef3f7; background: #eef3f7;
} }

71
src/layout/MapLayer.vue

@ -0,0 +1,71 @@
<script setup>
import { onMounted, onUnmounted } from 'vue'
import * as maptalks from 'maptalks'
import mapConfig, { createTiandituLayerOptions } from '@/config/map'
import commonRefs from '@/utils/commonRefs'
import mapHelper from '@/core/mapHelper'
import 'maptalks/dist/maptalks.css'
let map = null
function initMap() {
const tk = mapConfig.token
if (!tk) {
console.error('[MapLayer] 缺少 APP_TIANDITU_TOKEN,跳过地图初始化')
return
}
const layers = createTiandituLayerOptions(tk)
const baseLayer = new maptalks.GroupTileLayer('tianditu-base', [
new maptalks.TileLayer('tdt-img', layers.img),
new maptalks.TileLayer('tdt-cia', layers.cia),
])
map = new maptalks.Map('map', {
center: mapConfig.center,
zoom: mapConfig.zoom,
minZoom: 3,
attribution: false,
baseLayer,
})
commonRefs.setRef('map', map)
mapHelper.setMap(map)
}
onMounted(() => {
// 0
setTimeout(() => {
try {
initMap()
} catch (error) {
console.error('[MapLayer] 地图初始化失败:', error)
}
})
})
onUnmounted(() => {
if (map) {
map.remove()
commonRefs.removeRef('map')
mapHelper.setMap(null)
map = null
}
})
</script>
<template>
<div id="map" :class="s.root" />
</template>
<style lang="less" module="s">
.root {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
height: 100%;
z-index: 0;
}
</style>

54
src/utils/commonRefs.js

@ -0,0 +1,54 @@
/*
* 公共引用
* 异步获取引用对象
*/
const refs = Symbol('refs')
const pendingList = Symbol('pendingList')
class CommonRefs {
[refs] = {}
[pendingList] = {}
clearPendingList(key = '') {
if (!key) {
this[pendingList] = {}
} else {
this[pendingList][key] = []
}
}
setRef(key, ref) {
if (key in this[refs]) return
this[refs][key] = ref
const { [key]: resolves } = this[pendingList]
;(resolves || []).forEach((resolve, index) => {
if (!resolve) return
resolve(ref)
resolves[index] = undefined // 只作废,不删除
})
}
getRef(key) {
return new Promise((resolve) => {
const { [key]: ref } = this[refs]
if (ref) {
resolve(ref)
} else if (key in this[pendingList]) {
this[pendingList][key].push(resolve)
} else {
this[pendingList][key] = [resolve]
}
})
}
removeRef(key) {
if (key in this[refs]) {
delete this[refs][key]
}
}
}
export default new CommonRefs()
Loading…
Cancel
Save