171 lines
4.3 KiB
TypeScript
171 lines
4.3 KiB
TypeScript
'use client'
|
||
|
||
import React, { createContext, useContext, useRef, useState, ReactNode } from 'react'
|
||
// import Map from 'ol/Map';
|
||
import { Map } from 'maplibre-gl';
|
||
import { fromLonLat } from 'ol/proj';
|
||
|
||
// 定义MapContext的类型
|
||
interface MapContextType {
|
||
mapRef: React.RefObject<Map | null>
|
||
layers: React.RefObject<any[]>
|
||
mapState: MapState
|
||
setMap: (map: Map, layers: any[]) => void
|
||
flyTo: (options: { center: [number, number]; zoom: number; duration?: number }) => void
|
||
zoomIn: () => void
|
||
zoomOut: () => void
|
||
zoomTo: (zoom: number) => void
|
||
reset: () => void
|
||
setTime: (date: Date) => 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
|
||
});
|
||
|
||
const layersRef = useRef<any[]>([])
|
||
|
||
|
||
const setMap = (map: Map, layers: any[]) => {
|
||
// 监听视图变化事件
|
||
// const view = map.getView();
|
||
|
||
// 监听视图的缩放变化
|
||
map.on('zoom', () => {
|
||
setMapState(prevState => ({
|
||
...prevState,
|
||
zoomLevel: map.getZoom() || 11
|
||
}));
|
||
});
|
||
|
||
// 监听视图的中心点变化
|
||
map.on('move', () => {
|
||
const center = map.getCenter()
|
||
setMapState(prevState => ({
|
||
...prevState,
|
||
center: center
|
||
}));
|
||
});
|
||
|
||
mapRef.current = map;
|
||
layersRef.current = layers;
|
||
setIsMapReady(true);
|
||
}
|
||
|
||
const flyTo = (options: { center: [number, number]; zoom: number; duration?: number }) => {
|
||
if (mapRef.current) {
|
||
// mapRef.current.getView().animate({
|
||
// center: fromLonLat(options.center),
|
||
// zoom: options.zoom,
|
||
// duration: options.duration || 1000
|
||
// })
|
||
|
||
mapRef.current.flyTo({
|
||
center: options.center,
|
||
zoom: options.zoom,
|
||
duration: options.duration || 1000
|
||
})
|
||
|
||
}
|
||
}
|
||
|
||
const zoomIn = () => {
|
||
if (mapRef.current) {
|
||
// mapRef.current.getView().setZoom(mapRef.current.getView().getZoom()! + 1)
|
||
mapRef.current.zoomIn()
|
||
}
|
||
}
|
||
|
||
const zoomOut = () => {
|
||
if (mapRef.current) {
|
||
// mapRef.current.getView().setZoom(mapRef.current.getView().getZoom()! - 1)
|
||
mapRef.current.zoomOut()
|
||
}
|
||
}
|
||
|
||
const zoomTo = (zoom: number) => {
|
||
if (mapRef.current) {
|
||
// mapRef.current.getView().setZoom(zoom)
|
||
mapRef.current.zoomTo(zoom)
|
||
}
|
||
}
|
||
|
||
const setTime = (date: Date) => {
|
||
if (mapRef.current) {
|
||
layersRef.current.forEach(layer => {
|
||
const source = layer.getSource()
|
||
if (source) {
|
||
source.updateParams({
|
||
'TIME': date.toISOString()
|
||
})
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
const reset = () => {
|
||
if (mapRef.current) {
|
||
// mapRef.current.getView().setCenter([103.851959, 1.290270])
|
||
// mapRef.current.getView().setZoom(11)
|
||
mapRef.current.flyTo({
|
||
center: [103.851959, 1.290270],
|
||
zoom: 11,
|
||
duration: 1000
|
||
})
|
||
}
|
||
}
|
||
|
||
const value: MapContextType = {
|
||
setTime,
|
||
mapRef,
|
||
layers: layersRef,
|
||
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
|
||
}
|