122 lines
2.8 KiB
TypeScript
122 lines
2.8 KiB
TypeScript
'use client'
|
||
|
||
import React, { createContext, useContext, useRef, useState, ReactNode } from 'react'
|
||
import type { Map } from 'maplibre-gl'
|
||
|
||
// 定义MapContext的类型
|
||
interface MapContextType {
|
||
mapRef: React.RefObject<Map | null>
|
||
mapState: MapState
|
||
setMap: (map: Map) => void
|
||
flyTo: (options: { center: [number, number]; zoom: number; duration?: number }) => void
|
||
zoomIn: () => void
|
||
zoomOut: () => void
|
||
zoomTo: (zoom: number) => void
|
||
reset: () => void
|
||
isMapReady: boolean
|
||
}
|
||
|
||
// 创建Context
|
||
const MapContext = createContext<MapContextType | undefined>(undefined)
|
||
|
||
// Provider组件的Props类型
|
||
interface MapProviderProps {
|
||
children: ReactNode
|
||
}
|
||
|
||
interface MapState {
|
||
zoomLevel: number
|
||
}
|
||
|
||
// MapProvider组件
|
||
export function MapProvider({ children }: MapProviderProps) {
|
||
const mapRef = useRef<Map | null>(null)
|
||
const [isMapReady, setIsMapReady] = useState(false)
|
||
const [mapState, setMapState] = useState<MapState>({
|
||
zoomLevel: 11
|
||
});
|
||
|
||
mapRef.current?.on('zoom', () => {
|
||
setMapState(prevState => ({
|
||
...prevState,
|
||
zoomLevel: mapRef.current?.getZoom() || 11
|
||
}));
|
||
});
|
||
|
||
const setMap = (map: Map) => {
|
||
mapRef.current = map;
|
||
setIsMapReady(true);
|
||
}
|
||
|
||
const flyTo = (options: { center: [number, number]; zoom: number; duration?: number }) => {
|
||
if (mapRef.current) {
|
||
mapRef.current.flyTo({
|
||
...options,
|
||
duration: options.duration || 1000
|
||
})
|
||
}
|
||
}
|
||
|
||
const zoomIn = () => {
|
||
if (mapRef.current) {
|
||
mapRef.current.zoomIn()
|
||
}
|
||
}
|
||
|
||
const zoomOut = () => {
|
||
if (mapRef.current) {
|
||
mapRef.current.zoomOut()
|
||
}
|
||
}
|
||
|
||
const zoomTo = (zoom: number) => {
|
||
if (mapRef.current) {
|
||
mapRef.current.zoomTo(zoom)
|
||
}
|
||
}
|
||
|
||
const reset = () => {
|
||
if (mapRef.current) {
|
||
mapRef.current.flyTo({
|
||
center: [103.851959, 1.290270],
|
||
zoom: 11,
|
||
duration: 1000
|
||
})
|
||
}
|
||
}
|
||
|
||
const value: MapContextType = {
|
||
mapRef,
|
||
mapState,
|
||
setMap,
|
||
flyTo,
|
||
zoomIn,
|
||
zoomOut,
|
||
zoomTo,
|
||
reset,
|
||
isMapReady
|
||
}
|
||
|
||
return (
|
||
<MapContext.Provider value={value}>
|
||
{children}
|
||
</MapContext.Provider>
|
||
)
|
||
}
|
||
|
||
// 自定义Hook用于使用MapContext
|
||
export function useMap() {
|
||
const context = useContext(MapContext)
|
||
|
||
if (context === undefined) {
|
||
throw new Error('useMap必须在MapProvider内部使用')
|
||
}
|
||
|
||
return context
|
||
}
|
||
|
||
// 便捷的Hook,直接返回map实例
|
||
export function useMapInstance() {
|
||
const { mapRef } = useMap()
|
||
return mapRef.current
|
||
}
|