HRES 图层图片接入
使用 Leaflet ImageOverlay 将 HRES 高分辨率区域气象图层以图片方式叠加到地图上,支持点击取值,适合快速接入场景。
HRES(High Resolution European System)是欧洲中期天气预报中心(ECMWF)提供的高分辨率区域预报模型,分辨率约 9km,被认为是全球最先进的数值预报模型。
图片接入是门槛最低的接入方式:通过 Leaflet 的 L.imageOverlay 将气象图层叠加在底图上,点击取值时另行调用点取值 API。适合不需要复杂交互的快速集成场景。
1. 关键参数说明
| 参数 | 说明 |
|---|---|
model | hres |
element_level | 要素,如 temperature_2m(2m 气温) |
time | 通过 /api/vis/hres/meta 接口获取,返回数组第一项即为最新时间 |
| HRES 覆盖范围 | 南北:14.96°N ~ 55.04°N,东西:69.96°E ~ 140.08°E |
| Leaflet bounds | [[14.9587, 69.9588], [55.0412, 140.0799]](格式:[[南纬, 西经], [北纬, 东经]]) |
| 图片 URL | https://api.mirror-earth.com/api/vis/part/hres/{element_level}/{time}.webp?apikey={apikey} |
| 取值 API | https://api.mirror-earth.com/api/vis/point?model=hres&variable={element}&time={time}&lat={lat}&lon={lon}&apikey={apikey} |
| 返回格式 | { "data": [17.0] } → 取 data.data[0] |
注意:图片 URL 中使用 /part/ 路径前缀,表示返回的是可直接渲染的标准墨卡托投影(EPSG
data 数组,取第 0 个元素即为数值。
2. 示例代码
import { useEffect, useRef, useState } from 'react';
import 'leaflet/dist/leaflet.css';
const API_KEY = 'YOUR_API_KEY';
// HRES 覆盖范围:格式为 [[南, 西], [北, 东]]
const HRES_BOUNDS: [[number, number], [number, number]] = [
[14.9587, 69.9588],
[55.0412, 140.0799],
];
export default function HresImageDemo() {
const mapRef = useRef<HTMLDivElement>(null);
const mapInstance = useRef<any>(null);
const [clickedValue, setClickedValue] = useState<string | null>(null);
// 将 hresTime 提升到 loadLayers 外部,点击取值时能访问到
let hresTime = '';
useEffect(() => {
if (!mapRef.current || mapInstance.current) return;
const init = async () => {
const L: any = await import('leaflet');
const map = L.map(mapRef.current).setView([35.0, 105.0], 4);
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
subdomains: ['a', 'b', 'c', 'd'],
attribution: '© CartoDB',
}).addTo(map);
mapInstance.current = map;
// 1. 获取最新时间
const metaRes = await fetch(
`https://api.mirror-earth.com/api/vis/hres/meta?apikey=${API_KEY}&timezone=Asia/Shanghai`
);
const metaJson = await metaRes.json();
hresTime = metaJson.data[0];
// 2. 构建图片 URL 并加载图层
const url = `https://api.mirror-earth.com/api/vis/part/hres/temperature_2m/${hresTime}.webp?apikey=${API_KEY}&timezone=Asia/Shanghai`;
L.imageOverlay(url, HRES_BOUNDS, { opacity: 0.7 }).addTo(map);
// 3. 点击取值
map.on('click', async (e: any) => {
const { lat, lng } = e.latlng;
const res = await fetch(
`https://api.mirror-earth.com/api/vis/point?model=hres&variable=temperature_2m&time=${hresTime}&lat=${lat}&lon=${lng}&apikey=${API_KEY}`
);
const data = await res.json();
setClickedValue(
`坐标: ${lat.toFixed(2)}, ${lng.toFixed(2)} | 温度: ${data.data[0]}℃`
);
});
};
init();
return () => {
mapInstance.current?.remove();
mapInstance.current = null;
};
}, []);
return (
<div>
<div ref={mapRef} style={{ width: '100%', height: '500px' }} />
{clickedValue && (
<div style={{ padding: '8px 12px', background: '#f6ffed', borderTop: '1px solid #b7eb8f' }}>
{clickedValue}
</div>
)}
</div>
);
}<template>
<div>
<div ref="mapRef" style="width: 100%; height: 500px" />
<div v-if="clickedValue" style="padding: 8px 12px; background: #f6ffed; border-top: 1px solid #b7eb8f">
{{ clickedValue }}
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
const API_KEY = 'YOUR_API_KEY';
// HRES 覆盖范围:格式为 [[南, 西], [北, 东]]
const HRES_BOUNDS = [
[14.9587, 69.9588],
[55.0412, 140.0799],
];
const mapRef = ref<HTMLDivElement>();
const clickedValue = ref<string | null>(null);
let map: any = null;
// 提升到 handler 外部,点击取值时能访问到
let hresTime = '';
onMounted(async () => {
const L: any = await import('leaflet');
await import('leaflet/dist/leaflet.css');
map = L.map(mapRef.value!).setView([35.0, 105.0], 4);
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
subdomains: ['a', 'b', 'c', 'd'],
attribution: '© CartoDB',
}).addTo(map);
// 1. 获取最新时间
const metaRes = await fetch(
`https://api.mirror-earth.com/api/vis/hres/meta?apikey=${API_KEY}&timezone=Asia/Shanghai`
);
const metaJson = await metaRes.json();
hresTime = metaJson.data[0];
// 2. 构建图片 URL 并加载图层
const url = `https://api.mirror-earth.com/api/vis/part/hres/temperature_2m/${hresTime}.webp?apikey=${API_KEY}&timezone=Asia/Shanghai`;
L.imageOverlay(url, HRES_BOUNDS, { opacity: 0.7 }).addTo(map);
// 3. 点击取值
map.on('click', async (e: any) => {
const { lat, lng } = e.latlng;
const res = await fetch(
`https://api.mirror-earth.com/api/vis/point?model=hres&variable=temperature_2m&time=${hresTime}&lat=${lat}&lon=${lng}&apikey=${API_KEY}`
);
const data = await res.json();
clickedValue.value = `坐标: ${lat.toFixed(2)}, ${lng.toFixed(2)} | 温度: ${data.data[0]}℃`;
});
});
onUnmounted(() => {
map?.remove();
});
</script>3. Demo 仓库
完整可运行示例(含模型切换、WebGL、风场粒子等)已上传至 Gitee:
- 仓库:https://gitee.com/gfyml/me-layer-demo.git
- React 示例:
react-demo/src/components/ImageLayerDemo.tsx - Vue 示例:
vue-demo/src/components/ImageLayerDemo.vue