如何用 OpenLayers 做风场地图:2 种可视化风格的完整指南
【免费下载链接】openlayersOpenLayers项目地址: https://gitcode.com/gh_mirrors/op/openlayers
编写台风风况报告时,你需要把风向和风速叠到地图上。OpenLayers 有两条现成的风场可视化路径:离散测点用 RegularShape 箭头图层,连续格点数据用 WebGL Flow 图层。两种画法都基于仓库自带的官方示例数据,可以直接跑起来。
🧭 方案概览:3 个组件各管一段
整个方案只依赖 3 个官方模块,分工边界很清晰:
RegularShape(src/ol/style/RegularShape.js):正多边形形状样式,用它拼出风向箭头的箭杆和箭头。DataTileSource(src/ol/source/DataTile.js):格点数据瓦片源,你提供 loader 按瓦片返回数值数组,浏览器只取视口内的瓦片。Flow(src/ol/layer/Flow.js):实验性 WebGL 图层,在 GPU 上模拟粒子沿矢量场运动,无需逐点建矢量要素。
手里是站点数据就选箭头,是格点风场数据就选 Flow。
🏹 风向箭头最短路径:把 wind.speed 与 wind.deg 画成箭头
少量测点(站、浮标)的场景,几十到几百个要素,箭头画法就够了。数据源是 examples/data/openweather/weather.json,每条记录带经纬度,外加 wind.speed(m/s)和 wind.deg(方向角)。
箭头由两个形状拼成:2 个点的 RegularShape 当箭杆、3 个点的当箭头,都设 rotateWithView: true 让符号跟着地图一起旋转。风格函数里真正起作用的是这几行:
const angle = ((wind.deg - 180) * Math.PI) / 180; const scale = wind.speed / 10; shaft.setScale([1, scale]); head.setDisplacement([0, head.getRadius() / 2 + shaft.getRadius() * scale]);deg 是风的来向,必须减 180° 才是去向;箭头不随箭杆缩放,而是用位移推到箭杆末端。忘了 -180 这个偏移,所有箭头都会指反。完整实现在 examples/wind-arrows.js。
🗺 PNG 格点风分块:DataTileSource loader 怎么写
连续风场数据的目标是喂给 DataTileSource:每块瓦片是一个 256×256 的 Float32Array,视口之外不请求。
官方示例把 U、V 分量存在 wind.png 的两个通道里,压到 0–255,实际范围 U 从 -21.32 到 26.8,V 从 -21.57 到 21.42。loader 里做的事:取瓦片 extent 和分辨率,每个像素先把地图坐标从 EPSG:3857 反算回数据的 EPSG:4326,再对最近四个像素做双线性插值,最后按 min + delta × value/255 还原成 m/s 写入数组。
两套坐标系的换算是关键:PNG 是整球的 4326 图像,地图按 3857 渲染,逐像素反算采样才不会整体偏移。采样索引跨经度边界时要回绕(代码里 x1<0、x2≥宽度的分支),否则日期变更线附近会留白。
🌊 Flow 图层配置速查:粒子流只要 4 行
Flow 用 WebGL 模拟粒子运动,不用逐点建矢量要素。数据源就是上一节拼好的 DataTileSource:
new Flow({ source: wind, maxSpeed: 20, style: { color: ['interpolate', ['linear'], ['get', 'speed'], ...colorStops], }, })maxSpeed 是粒子速度上限,也是 U/V 归一化的分母;colorStops 由 viridis 色带生成(10 档、透明度 0.75),低速偏蓝、高速偏黄。particles 默认 65536,speedFactor 默认 0.001,想让流走得更快就调后者。完整示例见 examples/wind.js。
⚠️ 容易踩的 3 个坑,都写在仓库代码里
- transition 必须是 0。DataTileSource 默认对新瓦片做淡入,Flow 在过渡期无法正确合成,粒子流会闪烁撕裂。examples/wind.js 里专门注释了 transition: 0,别删。
- maxSpeed 忘了给会抛错。Flow 构造函数校验 maxSpeed > 0,漏传直接 throw。它还兼作色标分母:给小了颜色梯度直接打满,给大了粒子走得磨蹭。
- deg 的语义别搞混。OpenWeather 的 deg 是风从哪个方向吹来,箭头层要减 180°;如果换成语义为"去向"的其他接口,这里要重新换算。
接着可以往哪走
- 把 wind.png 换成实时 NetCDF 或 GRIB:loader 的签名(z, x, y)不变,像素读取换成解码调用即可,整条管线不用动。
- 叠加温度热力层:examples/heatmap-earthquakes.js 里 HeatmapLayer 的 weight 是个从要素里取数的函数,把温度映射进去就能叠在风场之上。
两种画法各管一类场景,挑一个跑起来,风场就上地图了。有其他气象图层玩法,欢迎留言聊聊。
【免费下载链接】openlayersOpenLayers项目地址: https://gitcode.com/gh_mirrors/op/openlayers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考