要求:在地图中展示风场效果,大致效果如下图
由于不会这方面的原理,只能搬砖,也没啥好说的,下面开始搬砖吧。
开发环境:openlayers5
参考:
https://github.com/Esri/wind-js
https://github.com/blissvisitor/wind-layer
https://github.com/sakitam-fdd/wind-layer
https://blog.csdn.net/u012413551/article/details/94298039
https://www.cnblogs.com/yanjinliang/p/7879312.html
思路:
利用别人封装的适用于openlayers的windy.js开发风场效果,风场数据采用项目中json文件夹下的current-wind.json做数据源
主体代码:
var projection = ol.proj.get('EPSG:4326');
var projectionExtent = projection.getExtent();
var size = ol.extent.getWidth(projectionExtent) / 256;
var resolutions = new Array(19);
var matrixIds = new Array(19);
for (var z = 1; z < 19; ++z) {
resolutions[z] = size / Math.pow(2, z);
matrixIds[z] = z;
}
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.WMTS({
name: "天地图影像地图",
url: "http://t{0-7}.tianditu.gov.cn/vec_c/wmts?tk=1b94e3699b4d7b567dfb6c82599ef519",
layer: "vec",
style: "default",
matrixSet: "c",
format: "tiles",
wrapX: true,
tileGrid: new ol.tilegrid.WMTS({
origin: ol.extent.getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: matrixIds
})
}),
maxResolution: resolutions[0],
minResolution: resolutions[18]
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [113.53450137499999, 34.44104525],
zoom: 5
})
});
function getWindyLayer(){
$.ajax({
url:"json/current-wind.json",
type:"get",
dataType:"json",
success:function(result){
if(result.returnCode == "0"){
windydata = JSON.parse(result.DS.content);
if(!!windyLayer){
windyLayer.setData(windydata);
}else{
windyLayer = new WindLayer(windydata, {
layerName: 'data',
projection: 'EPSG:4326',
ratio: 1,
map: map
});
windyLayer.appendTo(map);
}
}else{
alert("暂无风场数据!");
}
}
})
}
function exitWindyLayer(){
windyLayer.clearWind();
}
效果:
https://kaixin51.github.io/openlayers-windy/
最近有个需求是,通过这个风场的数据,要求点击地图上任意一个点,返回风有关的详情。一脸懵逼中,然后去查了一下数据对应的含义:得到以下信息:
风场数据结构大致为:
[
{
header: {
dx: 1
dy: 1
la1: -7.5
la2: -28.5
lo1: 143
lo2: 156
nx: 14
ny: 22
parameterCategory: 2
parameterNumber: 2
parameterNumberName: "eastward_wind"
parameterUnit: "m.s-1"
refTime: "2017-02-01 23:00:00"
},
data:[num1,num2,....]
},{
header{
结构同上
},
data:[.....]
}
]
其中:
dx、dy网格间距,
nx、ny网格数量,总网格数量= nx * ny = data.length;
parameterNumberName:表示风向
parameterUnit:风速单位
lo1:起点经度
la1:起点纬度
lo2:终点经度
la2:终点纬度
data中提供了正东方向和正北方向的风速,于是可以求得对应的风速和风向。
var allgrid = [];
function analysisWindyData(windydata){
var p = 0;
var east,north;
if(windydata[0].header.parameterNumberName == "eastward_wind"){
east = windydata[0];
north = windydata[1];
}else{
east = windydata[1];
north = windydata[0];
}
for (var j = 0; j < north.header.ny; j++) {
var row = [];
for (var i = 0; i < north.header.nx; i++, p++) {
row[i] = [east.data[p],north.data[p]];
}
grid[j] = row;
}
}
function getWindyDetail(coord){
var lng = coord[0];
var lat = coord[1];
if(lng < 70 || lng > 140 || lat < 0 || lat > 60){
layer.alert("暂无该区域风向数据!");
return;
}
var xlength = Math.floor((lng-70)/0.5);
var ylength = Math.floor((60-lat)/0.5);
var xdata,ydata;
xdata = allgrid[ylength][xlength][0];
ydata = allgrid[ylength][xlength][1];
console.log(xdata);
console.log(ydata);
var v = Math.sqrt(Math.pow(xdata,2)+Math.pow(ydata,2));
var angle = getWindyAngle(xdata,ydata);
var result = {
"direction":getWindyDirection(angle),
"level":getWindyLevel(v),
"speed":v.toFixed(2)
};
return result;
}
function getWindyDirection(angle){
if((angle >=0 && angle <= 22.5) || (angle <=360 && angle >337.5)){
return "北风";
}
if(angle <=337.5 && angle >292.5){
return "西北风";
}
if(angle <=292.5 && angle > 247.5){
return "西风";
}
if(angle <=247.5 && angle > 202.5){
return "西南风";
}
if(angle <= 202.5 && angle >157.5){
return "南风";
}
if(angle <=157.5 && angle > 112.5){
return "东南风";
}
if(angle <= 112.5 && angle >67.5){
return "东风";
}
if(angle <= 67.5 && angle >22.5){
return "东北风";
}
}
function getWindyAngle(u,v) {
var fx = 0;
if (u > 0 & v > 0) {
fx = 270 - Math.atan(v / u) * 180 / Math.PI;
}
else if (u < 0 & v > 0) {
fx = 90 - Math.atan(v / u) * 180 / Math.PI;
}
else if (u < 0 & v < 0) {
fx = 90 - Math.atan(v / u) * 180 / Math.PI;
}
else if (u > 0 & v < 0) {
fx = 270 - Math.atan(v / u) * 180 / Math.PI;
}
else if (u == 0 & v > 0) {
fx = 180;
}
else if (u == 0 & v < 0) {
fx = 0;
}
else if (u > 0 & v == 0) {
fx = 270;
}
else if (u < 0 & v == 0) {
fx = 90;
}
else if (u == 0 & v == 0) {
fx = 999.9;
}
return fx;
}
function getWindyLevel(v){
if(v<0.3){
return 0;
}
if(v>=0.3 && v<1.6){
return 1;
}
if(v>=1.6 && v<3.4){
return 2;
}
if(v>=3.4 && v<5.5){
return 3;
}
if(v>=5.5 && v<8.0){
return 4;
}
if(v>=8.0 && v<10.8){
return 5;
}
if(v>=10.8 && v<13.9){
return 6;
}
if(v>=13.9 && v<17.2){
return 7;
}
if(v>=17.2 && v<20.8){
return 8;
}
if(v>=20.8 && v<24.5){
return 9;
}
if(v>=24.5 && v<28.5){
return 10;
}
if(v>=28.5 && v<32.7){
return 11;
}
if(v>=32.7 && v<37.0){
return 12;
}
if(v>=37.0 && v<41.5){
return 13;
}
if(v>=41.5 && v<46.2){
return 14;
}
if(v>=46.2 && v<51.0){
return 15;
}
if(v>=51.0 && v<56.1){
return 16;
}
if(v>=56.1 && v<61.2){
return 17;
}
if(v>=61.2){
return 18;
}
}