UNPKG

atchain-mapbox-vue

Version:

A Vue 3 MapBox component library with subway lines, stations, markers and polygons support. Zero dependencies except Vue 3 and Mapbox GL JS.

263 lines (224 loc) 5.41 kB
/** * MapBox 核心地图管理 */ import { shallowRef, type Ref } from 'vue' import type { Map as MapboxMap } from 'mapbox-gl' import mapboxgl from 'mapbox-gl' // 地图实例和状态 const mapInstance = shallowRef<MapboxMap | null>(null) const mapLoaded = shallowRef(false) /** * 地图配置接口 */ export interface MapConfig { token: string style: string center: [number, number] zoom: number container: string | HTMLElement } /** * 地图事件回调接口 */ export interface MapEventCallbacks { onLoad?: () => void onError?: (error: Error) => void onMove?: () => void onMoveEnd?: () => void onZoom?: () => void onZoomEnd?: () => void } /** * 使用地图核心功能 */ export const useMapBoxCore = () => { /** * 设置地图实例 */ const setMapInstance = (map: MapboxMap) => { mapInstance.value = map mapLoaded.value = false } /** * 清理地图实例 */ const clearMapInstance = () => { if (mapInstance.value) { mapInstance.value.remove() mapInstance.value = null mapLoaded.value = false } } /** * 设置地图加载状态 */ const setMapLoaded = (loaded: boolean) => { mapLoaded.value = loaded } /** * 创建地图实例 */ const createMap = (config: MapConfig, callbacks: MapEventCallbacks = {}): MapboxMap => { const { token, style, center, zoom, container } = config const { onLoad, onError, onMove, onMoveEnd, onZoom, onZoomEnd } = callbacks // 设置访问令牌 mapboxgl.accessToken = token // 创建地图 const map = new mapboxgl.Map({ container, style, center, zoom }) // 绑定事件 map.on('load', () => { setMapLoaded(true) onLoad?.() }) map.on('error', (e) => { console.error('地图加载错误:', e.error) onError?.(e.error) }) if (onMove) { map.on('move', onMove) } if (onMoveEnd) { map.on('moveend', onMoveEnd) } if (onZoom) { map.on('zoom', onZoom) } if (onZoomEnd) { map.on('zoomend', onZoomEnd) } // 设置实例 setMapInstance(map) return map } /** * 获取地图中心点 */ const getMapCenter = (): [number, number] | null => { if (!mapInstance.value) return null const center = mapInstance.value.getCenter() return [center.lng, center.lat] } /** * 获取地图缩放级别 */ const getMapZoom = (): number | null => { if (!mapInstance.value) return null return mapInstance.value.getZoom() } /** * 设置地图中心点 */ const setMapCenter = (center: [number, number], zoom?: number) => { if (!mapInstance.value) return if (zoom !== undefined) { mapInstance.value.setCenter(center).setZoom(zoom) } else { mapInstance.value.setCenter(center) } } /** * 飞行到指定位置 */ const flyTo = (center: [number, number], zoom?: number, options?: any) => { if (!mapInstance.value) return mapInstance.value.flyTo({ center, zoom: zoom || mapInstance.value.getZoom(), ...options }) } /** * 适应边界 */ const fitBounds = (bounds: [[number, number], [number, number]], options?: any) => { if (!mapInstance.value) return mapInstance.value.fitBounds(bounds, options) } /** * 检查地图是否已加载 */ const isMapLoaded = (): boolean => { return mapLoaded.value && mapInstance.value !== null } /** * 检查图层是否存在 */ const hasLayer = (layerId: string): boolean => { if (!mapInstance.value) return false return !!mapInstance.value.getLayer(layerId) } /** * 检查数据源是否存在 */ const hasSource = (sourceId: string): boolean => { if (!mapInstance.value) return false return !!mapInstance.value.getSource(sourceId) } /** * 安全地移除图层 */ const removeLayer = (layerId: string): boolean => { if (!mapInstance.value || !hasLayer(layerId)) return false try { mapInstance.value.removeLayer(layerId) return true } catch (error) { console.warn(`移除图层失败: ${layerId}`, error) return false } } /** * 安全地移除数据源 */ const removeSource = (sourceId: string): boolean => { if (!mapInstance.value || !hasSource(sourceId)) return false try { mapInstance.value.removeSource(sourceId) return true } catch (error) { console.warn(`移除数据源失败: ${sourceId}`, error) return false } } return { // 状态 mapInstance: mapInstance as Readonly<Ref<MapboxMap | null>>, mapLoaded: mapLoaded as Readonly<Ref<boolean>>, // 核心方法 setMapInstance, clearMapInstance, setMapLoaded, createMap, // 地图操作 getMapCenter, getMapZoom, setMapCenter, flyTo, fitBounds, // 状态检查 isMapLoaded, hasLayer, hasSource, // 清理方法 removeLayer, removeSource } }