mosaicmap/components/map-component.tsx
2025-07-21 21:27:35 +08:00

81 lines
2.4 KiB
TypeScript

'use client'
import React, { useEffect, useRef } from 'react'
import maplibregl from 'maplibre-gl'
import VectorTileLayer from 'ol/layer/VectorTile.js'
import 'maplibre-gl/dist/maplibre-gl.css'
import { useMap } from '@/app/map-context'
import { apply, applyStyle } from 'ol-mapbox-style';
import { useTheme } from '@/components/theme-provider'
import TileWMS from 'ol/source/TileWMS.js';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import { transformExtent, fromLonLat } from 'ol/proj.js';
import StadiaMaps from 'ol/source/StadiaMaps.js';
import XYZ from 'ol/source/XYZ';
import 'ol/ol.css';
import { useMapLocation } from '@/hooks/use-map-location'
interface MapComponentProps {
style?: string
center?: [number, number]
zoom?: number
}
const interval = 3 * 60 * 60 * 1000;
const step = 15 * 60 * 1000;
const frameRate = 0.5; // frames per second
const extent = transformExtent([-126, 24, -66, 50], 'EPSG:4326', 'EPSG:3857');
export function MapComponent({
style = 'https://api.maptiler.com/maps/019817f1-82a8-7f37-901d-4bedf68b27fb/style.json?key=hj3fxRdwF9KjEsBq8sYI',
// center = [103.851959, 1.290270],
// zoom = 11
}: MapComponentProps) {
const mapContainer = useRef<HTMLDivElement>(null)
const { setMap } = useMap()
const { location } = useMapLocation()
useEffect(() => {
if (!mapContainer.current) return
const tileWmsLayer = new TileLayer({
extent: extent,
source: new TileWMS({
attributions: ['Iowa State University'],
url: 'https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi',
params: { 'LAYERS': 'nexrad-n0r-wmst' },
}),
opacity: 0.7,
});
const map = new Map({
target: mapContainer.current,
view: new View({
center: fromLonLat(location.center),
zoom: location.zoom,
projection: 'EPSG:3857',
showFullExtent: true,
enableRotation: true
}),
})
apply(map, style).then(() => {
map.addLayer(tileWmsLayer)
})
setMap(map, [tileWmsLayer])
}, [mapContainer])
return (
<div
ref={mapContainer}
className="w-full h-full"
style={{ minHeight: '400px' }}
/>
)
}