This commit is contained in:
tsuki 2025-07-22 21:24:58 +08:00
parent 37f07671d2
commit 33af6ca468
3 changed files with 98 additions and 49 deletions

View File

@ -1,7 +1,8 @@
'use client' 'use client'
import React, { createContext, useContext, useRef, useState, ReactNode } from 'react' import React, { createContext, useContext, useRef, useState, ReactNode } from 'react'
import Map from 'ol/Map'; // import Map from 'ol/Map';
import { Map } from 'maplibre-gl';
import { fromLonLat } from 'ol/proj'; import { fromLonLat } from 'ol/proj';
// 定义MapContext的类型 // 定义MapContext的类型
@ -44,20 +45,23 @@ export function MapProvider({ children }: MapProviderProps) {
const setMap = (map: Map, layers: any[]) => { const setMap = (map: Map, layers: any[]) => {
// 监听视图变化事件 // 监听视图变化事件
const view = map.getView(); // const view = map.getView();
// 监听视图的缩放变化 // 监听视图的缩放变化
view.on('change:resolution', () => { map.on('zoom', () => {
setMapState(prevState => ({ setMapState(prevState => ({
...prevState, ...prevState,
zoomLevel: view.getZoom() || 11 zoomLevel: map.getZoom() || 11
})); }));
}); });
// 监听视图的中心点变化 // 监听视图的中心点变化
view.on('change:center', () => { map.on('move', () => {
const center = view.getCenter() const center = map.getCenter()
setMapState(prevState => ({
...prevState,
center: center
}));
}); });
mapRef.current = map; mapRef.current = map;
@ -67,8 +71,14 @@ export function MapProvider({ children }: MapProviderProps) {
const flyTo = (options: { center: [number, number]; zoom: number; duration?: number }) => { const flyTo = (options: { center: [number, number]; zoom: number; duration?: number }) => {
if (mapRef.current) { if (mapRef.current) {
mapRef.current.getView().animate({ // mapRef.current.getView().animate({
center: fromLonLat(options.center), // center: fromLonLat(options.center),
// zoom: options.zoom,
// duration: options.duration || 1000
// })
mapRef.current.flyTo({
center: options.center,
zoom: options.zoom, zoom: options.zoom,
duration: options.duration || 1000 duration: options.duration || 1000
}) })
@ -78,19 +88,22 @@ export function MapProvider({ children }: MapProviderProps) {
const zoomIn = () => { const zoomIn = () => {
if (mapRef.current) { if (mapRef.current) {
mapRef.current.getView().setZoom(mapRef.current.getView().getZoom()! + 1) // mapRef.current.getView().setZoom(mapRef.current.getView().getZoom()! + 1)
mapRef.current.zoomIn()
} }
} }
const zoomOut = () => { const zoomOut = () => {
if (mapRef.current) { if (mapRef.current) {
mapRef.current.getView().setZoom(mapRef.current.getView().getZoom()! - 1) // mapRef.current.getView().setZoom(mapRef.current.getView().getZoom()! - 1)
mapRef.current.zoomOut()
} }
} }
const zoomTo = (zoom: number) => { const zoomTo = (zoom: number) => {
if (mapRef.current) { if (mapRef.current) {
mapRef.current.getView().setZoom(zoom) // mapRef.current.getView().setZoom(zoom)
mapRef.current.zoomTo(zoom)
} }
} }
@ -109,8 +122,13 @@ export function MapProvider({ children }: MapProviderProps) {
const reset = () => { const reset = () => {
if (mapRef.current) { if (mapRef.current) {
mapRef.current.getView().setCenter([103.851959, 1.290270]) // mapRef.current.getView().setCenter([103.851959, 1.290270])
mapRef.current.getView().setZoom(11) // mapRef.current.getView().setZoom(11)
mapRef.current.flyTo({
center: [103.851959, 1.290270],
zoom: 11,
duration: 1000
})
} }
} }

View File

@ -1,20 +1,19 @@
'use client' 'use client'
import React, { useEffect, useRef } from 'react' import React, { useEffect, useRef } from 'react'
import maplibregl from 'maplibre-gl' import maplibregl, { ProjectionDefinition } from 'maplibre-gl'
import VectorTileLayer from 'ol/layer/VectorTile.js'
import 'maplibre-gl/dist/maplibre-gl.css' import 'maplibre-gl/dist/maplibre-gl.css'
import { useMap } from '@/app/map-context' import { useMap } from '@/app/map-context'
import { apply, applyStyle } from 'ol-mapbox-style'; import { apply, applyStyle } from 'ol-mapbox-style';
import { useTheme } from '@/components/theme-provider' import { useTheme } from '@/components/theme-provider'
import TileWMS from 'ol/source/TileWMS.js'; // import TileWMS from 'ol/source/TileWMS.js';
import Map from 'ol/Map'; // import Map from 'ol/Map';
import View from 'ol/View'; // import View from 'ol/View';
import TileLayer from 'ol/layer/Tile'; // import TileLayer from 'ol/layer/Tile';
import { transformExtent, fromLonLat } from 'ol/proj.js'; // import { transformExtent, fromLonLat } from 'ol/proj.js';
import StadiaMaps from 'ol/source/StadiaMaps.js'; // import StadiaMaps from 'ol/source/StadiaMaps.js';
import XYZ from 'ol/source/XYZ'; // import XYZ from 'ol/source/XYZ';
import 'ol/ol.css'; // import 'ol/ol.css';
import { useMapLocation } from '@/hooks/use-map-location' import { useMapLocation } from '@/hooks/use-map-location'
interface MapComponentProps { interface MapComponentProps {
@ -23,10 +22,7 @@ interface MapComponentProps {
zoom?: number zoom?: number
} }
const interval = 3 * 60 * 60 * 1000; // const extent = transformExtent([-126, 24, -66, 50], 'EPSG:4326', 'EPSG:3857');
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({ export function MapComponent({
style = 'https://api.maptiler.com/maps/019817f1-82a8-7f37-901d-4bedf68b27fb/style.json?key=hj3fxRdwF9KjEsBq8sYI', style = 'https://api.maptiler.com/maps/019817f1-82a8-7f37-901d-4bedf68b27fb/style.json?key=hj3fxRdwF9KjEsBq8sYI',
@ -40,34 +36,68 @@ export function MapComponent({
useEffect(() => { useEffect(() => {
if (!mapContainer.current) return if (!mapContainer.current) return
const tileWmsLayer = new TileLayer({ // const tileWmsLayer = new TileLayer({
extent: extent, // extent: extent,
source: new TileWMS({ // source: new TileWMS({
attributions: ['Iowa State University'], // attributions: ['Iowa State University'],
url: 'https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi', // url: 'https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi',
params: { 'LAYERS': 'nexrad-n0r-wmst' }, // params: { 'LAYERS': 'nexrad-n0r-wmst' },
}), // }),
opacity: 0.7, // opacity: 0.7,
}); // });
const map = new Map({ // const map = new Map({
target: mapContainer.current, // target: mapContainer.current,
view: new View({ // view: new View({
center: fromLonLat(location.center), // center: fromLonLat(location.center),
zoom: location.zoom, // zoom: location.zoom,
projection: 'EPSG:3857', // projection: 'EPSG:3857',
showFullExtent: true, // showFullExtent: true,
enableRotation: true // enableRotation: true
}), // }),
// })
// apply(map, style).then(() => {
// map.addLayer(tileWmsLayer)
// })
const map = new maplibregl.Map({
container: mapContainer.current,
style: style,
center: location.center,
zoom: location.zoom,
canvasContextAttributes: {
contextType: 'webgl2', // 请求 WebGL2
antialias: true // 打开多重采样抗锯齿
}
}) })
apply(map, style).then(() => { map.on('style.load', () => {
map.addLayer(tileWmsLayer) map.setProjection({
type: 'globe'
})
map.addSource('nexrad', {
type: 'raster',
tiles: [
// 'https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi?service=WMS&version=1.3.0&request=GetMap&layers=nexrad-n0r-wmst&styles=&format=image/png&transparent=true&crs=EPSG:3857&bbox={bbox-epsg-3857}&width=256&height=256'
'http://127.0.0.1:3050/tiles/{z}/{x}/{y}?time=202507220012'
],
tileSize: 256
});
map.addLayer({
id: 'nexrad-layer',
type: 'raster',
source: 'nexrad',
paint: { 'raster-opacity': 0.8 }
});
}) })
setMap(map, [tileWmsLayer])
setMap(map, [])
}, [mapContainer]) }, [mapContainer])

1
package-lock.json generated
View File

@ -3320,6 +3320,7 @@
"version": "5.6.1", "version": "5.6.1",
"resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.6.1.tgz", "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.6.1.tgz",
"integrity": "sha512-TTSfoTaF7RqKUR9wR5qDxCHH2J1XfZ1E85luiLOx0h8r50T/LnwAwwfV0WVNh9o8dA7rwt57Ucivf1emyeukXg==", "integrity": "sha512-TTSfoTaF7RqKUR9wR5qDxCHH2J1XfZ1E85luiLOx0h8r50T/LnwAwwfV0WVNh9o8dA7rwt57Ucivf1emyeukXg==",
"license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"@mapbox/geojson-rewind": "^0.5.2", "@mapbox/geojson-rewind": "^0.5.2",
"@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2",