openlayers6+vue2实现台风
代码实现
整体外观
实现轨迹路线
一得到数据
二,轨迹路线点数据放在list中
三,生成要素并设置长啥样
四,放进我们准备好的featureslist中,确保台风模块在一个矢量图层里
对轨迹点进行打点,因为我们需要点击轨迹点弹出popup
先画线
const feature = new Feature({
geometry: new LineString(lxList),
// attribute: attr
});
feature.setStyle(
new Style({
stroke: new Stroke({
color: "#3F77CA",
width: 1,
}),
})
);
features.push(feature);
const vectorLayer = new VectorLayer({
zIndex: 110,
name: "tf-route",
source: new Vector({
wrapX: false,
features: features,
}),
});
this.map.addLayer(vectorLayer);
that.layers.push(vectorLayer);
再汇点,汇点的方法我给封装统一了,我现在只把绘制台风点相关的代码贴出来
setMap(data, type, name, source) {
const markData = data;
const features = new Array(markData.length);
markData.forEach(function (item, index) {
let attr = {}
if (type == 'tf') {
features[index] = new Feature({
geometry: new Point([item.lng, item.lat]),
attribute: attr,
});
}
let iconList = [{
type: 'yjjd',
iconSrc: require("../../assets/img/data_icon/map_base.png"),
iconSrc_point: require("../../assets/img/data_icon/map_base_point.png")
},
{
type: 'yjdw',
iconSrc: require("../../assets/img/data_icon/map_rank.png"),
iconSrc_point: require("../../assets/img/data_icon/map_rank_point.png")
},
{
type: 'zdl',
iconSrc: require("../../assets/img/data_icon/ico_阻断路.png"),
iconSrc_point: require("../../assets/img/data_icon/ico_阻断路_point.png")
},
{
type: 'qtz',
iconSrc: require("../../assets/img/data_icon/map_抢通中.png"),
iconSrc_point: require("../../assets/img/data_icon/map_抢通中_point.png")
},
{
type: 'qtl',
iconSrc: require("../../assets/img/data_icon/ico_抢通路.png"),
iconSrc_point: require("../../assets/img/data_icon/ico_抢通路_point.png")
},
{
type: 'yjYhd',
iconSrc: require("../../assets/img/data_icon/map_一级隐患.png"),
iconSrc_point: require("../../assets/img/data_icon/map_一级隐患_point.png")
},
{
type: 'rjYhd',
iconSrc: require("../../assets/img/data_icon/map_二级隐患.png"),
iconSrc_point: require("../../assets/img/data_icon/map_二级隐患_point.png")
},
{
type: 'gpdbd',
iconSrc: require("../../assets/img/data_icon/挂牌督办.png"),
iconSrc_point: require("../../assets/img/data_icon/map_挂牌督办点_point.png")
},
{
type: 'tf',
iconSrc: require("../../assets/img/已发生.png")
},
{
type: 'tfyc',
iconSrc: require("../../assets/img/未发生.png")
},
]
let vectorLayer;
let iconY;
let iconX;
let scale;
let iconYUnits = "pixels";
iconSrc = iconList.filter((item) => item.type == type)
vectorLayer = new VectorImageLayer({
name: type,
zIndex: 99,
source: new Vector({
wrapX: false,
features: features,
}),
style: [
new Style({
image: new Icon(
/** @type {olx.style.IconOptions} */
({
anchor: [iconX, iconY],
anchorOrigin: "top-right",
anchorXUnits: "fraction",
anchorYUnits: iconYUnits,
offsetOrigin: "top-right",
offset: [0, 0], // 偏移量设置
scale, // 图标缩放比例
opacity: 1, // 透明度
src: iconSrc[0].iconSrc, // 图标的url
})
),
}),
],
});
}
this.layers.push(vectorLayer);
this.map.addLayer(vectorLayer);
}
…我把代码全部贴出来算了,基本都有注释,代码质量自己甄别
根据台风接口返回的数据来绘制相应的点线和台风圈的数据
/* 获取台风数据 */
getTyphoonData() {
this.$$request
.getTyphoon({ lng: this.center[0], lat: this.center[1] })
.then((res) => {
if (res.success) {
if (res.result.length > 0) {
that.typhoonList = res.result;
that.allTaifengStr = "";
for (let i in res.result) {
/* 以前的逻辑不管,这是最新逻辑 */
let data = res.result[i].typhoonPathVoList;
let needData = data[data.length - 1];
that.allTaifengStr =
that.allTaifengStr +
"\xa0\xa0\xa0\xa0\xa0\xa0\xa0" +
(Number(i) + 1) +
" ," +
"\xa0\xa0" +
needData.jl +
"\xa0\xa0\xa0\xa0\xa0\xa0\xa0" +
needData.ckposition;
let lxList = [];
let lxList1 = [];
let lxList2 = [];
let lxList3 = [];
let lxList4 = [];
let lxList5 = [];
let features = [];
/* 绘制台风范围圈 并设置风圈说明*/
if (JSON.parse(needData.radius7).length > 0) {
that.mytest(
[Number(needData.lng), Number(needData.lat)],
JSON.parse(needData.radius7),
7
);
let point7 = getLonAndLat(
Number(needData.lng),
Number(needData.lat),
0,
JSON.parse(needData.radius7)[0] * 1000
);
const featurePointCenter7 = new Feature({
geometry: new Point([point7.lng, point7.lat]),
});
featurePointCenter7.setStyle(
new Style({
text: new Text({
font: "bold 12px 微软雅黑",
text: "7级风圈",
offsetX: 0,
offsetY: 0,
fill: new Fill({
color: "#fff",
}),
}),
})
);
features.push(featurePointCenter7);
}
if (JSON.parse(needData.radius10).length > 0) {
that.mytest(
[Number(needData.lng), Number(needData.lat)],
JSON.parse(needData.radius10),
10
);
let point10 = getLonAndLat(
Number(needData.lng),
Number(needData.lat),
0,
JSON.parse(needData.radius10)[0] * 1000
);
const featurePointCenter10 = new Feature({
geometry: new Point([point10.lng, point10.lat]),
});
featurePointCenter10.setStyle(
new Style({
text: new Text({
font: "bold 12px 微软雅黑",
text: "10级风圈",
offsetX: 0,
offsetY: 0,
fill: new Fill({
color: "#fff",
}),
}),
})
);
features.push(featurePointCenter10);
}
if (JSON.parse(needData.radius12).length > 0) {
that.mytest(
[Number(needData.lng), Number(needData.lat)],
JSON.parse(needData.radius12),
12
);
let point12 = getLonAndLat(
Number(needData.lng),
Number(needData.lat),
0,
JSON.parse(needData.radius12)[0] * 1000
);
const featurePointCenter12 = new Feature({
geometry: new Point([point12.lng, point12.lat]),
});
featurePointCenter12.setStyle(
new Style({
text: new Text({
font: "bold 12px 微软雅黑",
text: "12级风圈",
offsetX: 0,
offsetY: 0,
fill: new Fill({
color: "#fff",
}),
}),
})
);
features.push(featurePointCenter12);
}
const featurePointCenter = new Feature({
geometry: new Point([
Number(needData.lng),
Number(needData.lat),
]),
});
// gif动图的url的链接
const gifUrl = require("@/assets/img/tf.gif");
// 使用Gifler将链接转化为gif图片
// eslint-disable-next-line no-undef
const gif = gifler(gifUrl);
gif.frames(
document.createElement("canvas"),
function (ctx, frame) {
if (!featurePointCenter.getStyle()) {
featurePointCenter.setStyle(
new Style({
image: new Icon({
img: ctx.canvas,
imgSize: [frame.width, frame.height],
opacity: 0.8,
}),
})
);
}
ctx.clearRect(0, 0, frame.width, frame.height);
ctx.drawImage(frame.buffer, frame.x, frame.y);
that.map.render();
},
true
);
features.push(featurePointCenter);
for (let ii in that.typhoonList[i].typhoonPathVoList) {
lxList.push([
Number(that.typhoonList[i].typhoonPathVoList[ii].lng),
Number(that.typhoonList[i].typhoonPathVoList[ii].lat),
]);
}
for (let ii in that.typhoonList[i].typhoonForecastPathVoList) {
this.setMap(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList, //来源是中国的预测
"tfyc",
that.typhoonList[i].name,
that.typhoonList[i].typhoonForecastPathVoList[ii].source
);
for (let iii in that.typhoonList[i].typhoonForecastPathVoList[
ii
].typhoonPathVoList) {
switch (
that.typhoonList[i].typhoonForecastPathVoList[ii].source
) {
case "中国":
lxList1.push([
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lng
),
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lat
),
]);
break;
case "日本":
lxList2.push([
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lng
),
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lat
),
]);
break;
case "美国":
lxList3.push([
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lng
),
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lat
),
]);
break;
case "中国台湾":
lxList4.push([
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lng
),
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lat
),
]);
break;
case "中国香港":
lxList5.push([
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lng
),
Number(
that.typhoonList[i].typhoonForecastPathVoList[ii]
.typhoonPathVoList[iii].lat
),
]);
break;
}
}
}
this.setMap(
that.typhoonList[i].typhoonPathVoList,
"tf",
that.typhoonList[i].name
);
const feature = new Feature({
geometry: new LineString(lxList),
// attribute: attr
});
feature.setStyle(
new Style({
stroke: new Stroke({
color: "#3F77CA",
width: 1,
}),
})
);
const feature1 = new Feature({
geometry: new LineString(lxList1),
// attribute: attr
});
feature1.setStyle(
new Style({
stroke: new Stroke({
color: "#FF4050",
width: 1,
lineDash: [10],
}),
})
);
features.push(feature1);
const feature2 = new Feature({
geometry: new LineString(lxList2),
// attribute: attr
});
feature2.setStyle(
new Style({
stroke: new Stroke({
color: "#43FF4B",
width: 1,
lineDash: [10],
}),
})
);
features.push(feature2);
const feature3 = new Feature({
geometry: new LineString(lxList3),
// attribute: attr
});
feature3.setStyle(
new Style({
stroke: new Stroke({
color: "#40DDFF",
width: 1,
lineDash: [10],
}),
})
);
features.push(feature3);
const feature4 = new Feature({
geometry: new LineString(lxList4),
// attribute: attr
});
feature4.setStyle(
new Style({
stroke: new Stroke({
color: "#FFA040",
width: 1,
lineDash: [10],
}),
})
);
features.push(feature4);
const feature5 = new Feature({
geometry: new LineString(lxList5),
// attribute: attr
});
feature5.setStyle(
new Style({
stroke: new Stroke({
color: "#FF66FF",
width: 1,
lineDash: [10],
}),
})
);
features.push(feature5);
features.push(feature);
const vectorLayer = new VectorLayer({
zIndex: 110,
name: "tf-route",
source: new Vector({
wrapX: false,
features: features,
}),
});
this.map.addLayer(vectorLayer);
that.layers.push(vectorLayer);
}
} else {
that.typhoonList = [];
}
} else {
that.$message.error(res.message);
}
});
},
绘制台风圈的方法
/* 名字就不改了,这个是用来画台风圈的方法 */
mytest(center, arr, type) {
var config = {
x: center[0], //台风圈中心点经度
y: center[1], //台风圈中心点维度
r: {
SE: arr[0] * 0.01,
NE: arr[1] * 0.01,
NW: arr[2] * 0.01,
SW: arr[3] * 0.01,
},
interval: 6, // 6° 一个间隔;间隔越小,台风圈越平滑
};
var wktformat = new format.WKT();
var features = [];
var wkt = `POLYGON((`;
var wkt0 = "";
for (var i = 0; i < 360 / config.interval; i++) {
var r = 0;
var ang = i * config.interval;
//第一象限
if (ang > 0 && ang <= 90) {
r = config.r.NE;
}
//第二象限
else if (ang > 90 && ang <= 180) {
r = config.r.NW;
}
// 第三象限
else if (ang > 180 && ang <= 270) {
r = config.r.SW;
}
// 第四象限
else {
r = config.r.SE;
}
var x = config.x + r * Math.cos((ang * Math.PI) / 180);
var y = config.y + r * Math.sin((ang * Math.PI) / 180);
wkt = wkt + `${x} ${y},`;
if (i === 0) {
wkt0 = `${x} ${y}`;
}
}
wkt = wkt + wkt0 + "))";
features.push(wktformat.readFeature(wkt));
features.push(
wktformat.readFeature("POINT(" + config.x + " " + config.y + ")")
);
let color1, color2;
if (type == 7) {
color1 = "rgba(39,181,65,0.16)";
color2 = "rgba(39,181,65)";
}
if (type == 10) {
color1 = "rgba(221,209,39,0.16)";
color2 = "rgba(221,209,39)";
}
if (type == 12) {
color1 = "rgba(231,45,32,0.16)";
color2 = "rgba(231,45,32)";
}
var styleFunc = function () {
return new Style({
fill: new Fill({
color: color1,
}),
stroke: new Stroke({
color: color2,
width: 1,
}),
// text: new Text({
// font: "bold 14px 微软雅黑",
// text: type + "风圈",
// offsetX: 10,
// offsetY: 15,
// fill: new Fill({
// color: color1,
// }),
// }),
});
};
var vector = new VectorLayer({
name: "tf-fq",
zIndex: 100,
source: new Vector({
features: features,
}),
style: styleFunc,
});
this.map.addLayer(vector);
that.layers.push(vector);
},
统一封装的用来绘点的方法
/* 往地图上绘点 */
setMap(data, type, name, source) {
// let that = this;
const markData = data;
const features = new Array(markData.length);
markData.forEach(function (item, index) {
let attr = {}
if (type == "zdl") {
attr = {
reportTime: item.reportTime,
source: item.source,
location: item.location,
lon: item.latitude,
lat: item.longitude,
type: type,
img: item.picture,
reportor: item.reportor,
description: item.description,
stakeNo: item.stakeNo,
level: item.level,
coverage: item.coverage,
zdtype: item.type,
occurrenceTime: item.occurrenceTime,
name: item.name,
phone: item.phone,
memberNo: item.memberNo,
manager: item.manager,
emergencyMaterialList: item.emergencyMaterialList,
roadName: item.roadName,
yjSjSsGzList: item.yjSjSsGzList
};
} else if (type == 'tf') {
attr = {
type: "tf",
name: name,
lat: Number(item.lng),
lon: Number(item.lat),
details: item,
};
// console.log("attr1111==",attr)
} else if (type == 'tfyc') {
attr = {
type: "tfyc",
name: name,
lat: Number(item.lng),
lon: Number(item.lat),
details: item,
source: source
};
// console.log("attr2222==",attr)
} else if (type == 'gpdbd') {
attr = {
yhdLx: item.yhdLx,
yhdMc: item.yhdMc,
yhdGydw: item.yhdGydw,
imgList: item.imgList,
yhdQdzh: item.yhdQdzh,
yhdZdzh: item.yhdZdzh,
lxName: item.lxName,
lon: Number(item.zxWd),
lat: Number(item.zxJd),
type: type,
img: item.picture,
reportor: item.reportor,
description: item.description,
stakeNo: item.stakeNo,
level: item.level,
coverage: item.coverage,
zdtype: item.type,
occurrenceTime: item.occurrenceTime,
name: item.name,
phone: item.phone,
memberNo: item.memberNo,
manager: item.manager,
emergencyMaterialList: item.emergencyMaterialList,
roadName: item.roadName,
location: item.location,
xlMc: item.xlMc,
ldGlz: item.ldGlz,
jtDm: item.jtDm,
zlZrDw: item.zlZrDw
};
} else {
attr = {
yhdLx: item.yhdLx,
yhdMc: item.yhdMc,
yhdGydw: item.yhdGydw,
imgList: item.imgList,
yhdQdzh: item.yhdQdzh,
yhdZdzh: item.yhdZdzh,
lxName: item.lxName,
lon: item.latitude,
lat: item.longitude,
type: type,
img: item.picture,
reportor: item.reportor,
description: item.description,
stakeNo: item.stakeNo,
level: item.level,
coverage: item.coverage,
zdtype: item.type,
occurrenceTime: item.occurrenceTime,
name: item.name,
phone: item.phone,
memberNo: item.memberNo,
manager: item.manager,
emergencyMaterialList: item.emergencyMaterialList,
roadName: item.roadName,
location: item.location,
xlMc: item.xlMc,
ldGlz: item.ldGlz,
jtDm: item.jtDm,
zlZrDw: item.zlZrDw
};
}
if (type == 'tf') {
features[index] = new Feature({
geometry: new Point([item.lng, item.lat]),
attribute: attr,
});
} else if (type == 'tfyc') {
features[index] = new Feature({
geometry: new Point([item.lng, item.lat]),
attribute: attr,
});
} else if (type == 'gpdbd') {
features[index] = new Feature({
geometry: new Point([Number(item.zxJd), Number(item.zxWd)]),
attribute: attr,
});
// that.addDynamicPoints([Number(item.zxJd), Number(item.zxWd)], type)
} else {
features[index] = new Feature({
geometry: new Point([item.longitude, item.latitude]),
attribute: attr,
});
}
});
let vectorLayer;
let iconSrc;
let iconList = [{
type: 'yjjd',
iconSrc: require("../../assets/img/data_icon/map_base.png"),
iconSrc_point: require("../../assets/img/data_icon/map_base_point.png")
},
{
type: 'yjdw',
iconSrc: require("../../assets/img/data_icon/map_rank.png"),
iconSrc_point: require("../../assets/img/data_icon/map_rank_point.png")
},
{
type: 'zdl',
iconSrc: require("../../assets/img/data_icon/ico_阻断路.png"),
iconSrc_point: require("../../assets/img/data_icon/ico_阻断路_point.png")
},
{
type: 'qtz',
iconSrc: require("../../assets/img/data_icon/map_抢通中.png"),
iconSrc_point: require("../../assets/img/data_icon/map_抢通中_point.png")
},
{
type: 'qtl',
iconSrc: require("../../assets/img/data_icon/ico_抢通路.png"),
iconSrc_point: require("../../assets/img/data_icon/ico_抢通路_point.png")
},
{
type: 'yjYhd',
iconSrc: require("../../assets/img/data_icon/map_一级隐患.png"),
iconSrc_point: require("../../assets/img/data_icon/map_一级隐患_point.png")
},
{
type: 'rjYhd',
iconSrc: require("../../assets/img/data_icon/map_二级隐患.png"),
iconSrc_point: require("../../assets/img/data_icon/map_二级隐患_point.png")
},
{
type: 'gpdbd',
iconSrc: require("../../assets/img/data_icon/挂牌督办.png"),
iconSrc_point: require("../../assets/img/data_icon/map_挂牌督办点_point.png")
},
{
type: 'tf',
iconSrc: require("../../assets/img/已发生.png")
},
{
type: 'tfyc',
iconSrc: require("../../assets/img/未发生.png")
},
]
let iconY;
let iconX;
let scale;
if (type == 'tf' || type == 'tfyc') {
iconY = 9;
iconX = 0.5;
scale = 0.68
} else {
iconY = 35;
iconX = 0.5;
scale = 1;
}
let iconYUnits = "pixels";
if (data.length > 10 && type !== 'tf' && type !== 'tfyc') {
const clusterSource = new Cluster({
distance: 40,
source: new Vector({
features: features,
}),
});
const styleCache = {};
vectorLayer = new VectorImageLayer({
name: type,
zIndex: 99,
source: clusterSource,
style: function (feature) {
var size = feature.get("features").length;
var style = styleCache[size];
if (!style) {
iconSrc = iconList.filter((item) => item.type == type)
if (size > 1) {
iconSrc = iconList.filter((item) => item.type == type)
style = [
new Style({
image: new Icon(
/** @type {olx.style.IconOptions} */
({
anchor: [iconX, iconY],
anchorOrigin: "top-right",
anchorXUnits: "fraction",
anchorYUnits: iconYUnits,
offsetOrigin: "top-right",
offset: [0, 0], // 偏移量设置
scale, // 图标缩放比例
opacity: 1, // 透明度
src: iconSrc[0].iconSrc_point, // 图标的url
})
),
text: new Text({
font: "normal 12px 微软雅黑",
text: size.toString(),
offsetX: 11,
offsetY: -3.5,
fill: new Fill({
color: "#fff",
}),
stroke: new Stroke({
color: '#666666',
width:3
}),
}),
}),
];
styleCache[size] = style;
} else {
style = [
new Style({
image: new Icon(
/** @type {olx.style.IconOptions} */
({
anchor: [iconX, iconY],
anchorOrigin: "top-right",
anchorXUnits: "fraction",
anchorYUnits: iconYUnits,
offsetOrigin: "top-right",
offset: [0, 0], // 偏移量设置
scale, // 图标缩放比例
opacity: 1, // 透明度
src: iconSrc[0].iconSrc, // 图标的url
})
),
}),
];
styleCache[size] = style;
}
}
return style;
},
});
} else {
iconSrc = iconList.filter((item) => item.type == type)
vectorLayer = new VectorImageLayer({
name: type,
zIndex: 99,
source: new Vector({
wrapX: false,
features: features,
}),
style: [
new Style({
image: new Icon(
/** @type {olx.style.IconOptions} */
({
anchor: [iconX, iconY],
anchorOrigin: "top-right",
anchorXUnits: "fraction",
anchorYUnits: iconYUnits,
offsetOrigin: "top-right",
offset: [0, 0], // 偏移量设置
scale, // 图标缩放比例
opacity: 1, // 透明度
src: iconSrc[0].iconSrc, // 图标的url
})
),
}),
],
});
}
this.layers.push(vectorLayer);
this.map.addLayer(vectorLayer);
/* 设置加载图层但不显示 */
//不能让默认的图层被隐藏
let allList = this.checkedListArr.concat(this.defaultList);
this.checkedList = allList;
this.layers.map((item) => {
if (allList.indexOf(item.getProperties().name) === -1) {
item.setVisible(false);
} else {
item.setVisible(true);
}
});
},
地图创建时绑定点击事件
//判断当前单击处是否有要素,捕获到要素时弹出popup
that.map.forEachFeatureAtPixel(evt.pixel, function (feature) {
if (
feature &&
!that.clickClose &&
(feature.values_.attribute || feature.values_.features.length > 0)
) {
that.selectFeature(feature);
} else {
that.unSelect();
}
});
var viewResolution = that.map.getView().getResolution();
const source_lx = new TileWMS({
url: "http://192.168.1.117:8080/geoserver/cite/wms",
params: {
LAYERS: "cite:LX_C",
STYLES: "",
TILED: true,
},
serverType: "geoserver",
crossOrigin: "anonymous",
});
var url = source_lx.getFeatureInfoUrl(
evt.coordinate,
viewResolution,
"EPSG:3857",
{
INFO_FORMAT: "application/json", //输出为json字符串
FEATURE_COUNT: 1,
}
);
if (url) {
const urlSplit =
window._CONFIG["staticDomainURLGEOSERVE"] +
"geoserver" +
url.split("geoserver")[1];
fetch(urlSplit, { mode: "no-cors" })
.then(function (res) {
return res.text(); //返回Promise
})
.then((data) => {
// console.log(data);
let objData = JSON.parse(data);
let info = objData.features[0];
console.log(info);
});
}
});
当点击时有要素
/* 选中 */
selectFeature(feature) {
this.unSelect();
if (feature) {
let featureInfo = feature.getProperties().attribute;
if (!featureInfo) {
if (feature.getProperties().features) {
featureInfo = feature.getProperties().features[0].values_.attribute;
}
}
if (featureInfo) {
this.addFeatureInfo(featureInfo, feature);
}
}
},
当点击时没有要素或者用来清除popup框等
/* 反选(点击地图) */
unSelect() {
if (this.selectedFeature != null) {
this.selectedFeature.setStyle(null);
this.selectedFeature.changed();
this.showzdl = false;
}
this.overlay.setPosition(undefined);
this.showzdl = false;
},
js方法
/* 经纬度转换成三角函数中度分表形式 */
export const rad = (d) => {
return (d * Math.PI) / 180.0;
};
export const deg = (x) => {
return x * 180 / Math.PI;
}
/* 根据某个确定的点的经纬度以及确定的距离和偏向角来确定另一个点的位置 */
/**
* 度换成弧度
* @param {Float} d 度
* @return {[Float} 弧度
*/
/**
* 弧度换成度
* @param {Float} x 弧度
* @return {Float} 度
*/
export const getLonAndLat = (lng, lat, brng, dist) => {
//大地坐标系资料WGS-84 长半径a=6378137 短半径b=6356752.3142 扁率f=1/298.2572236
var a = 6378137;
var b = 6356752.3142;
var f = 1 / 298.257223563;
var lon1 = lng * 1;
var lat1 = lat * 1;
var s = dist;
var alpha1 = rad(brng);
var sinAlpha1 = Math.sin(alpha1);
var cosAlpha1 = Math.cos(alpha1);
var tanU1 = (1 - f) * Math.tan(rad(lat1));
var cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)),
sinU1 = tanU1 * cosU1;
var sigma1 = Math.atan2(tanU1, cosAlpha1);
var sinAlpha = cosU1 * sinAlpha1;
var cosSqAlpha = 1 - sinAlpha * sinAlpha;
var uSq = cosSqAlpha * (a * a - b * b) / (b * b);
var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
var sigma = s / (b * A),
sigmaP = 2 * Math.PI;
while (Math.abs(sigma - sigmaP) > 1e-12) {
var cos2SigmaM = Math.cos(2 * sigma1 + sigma);
var sinSigma = Math.sin(sigma);
var cosSigma = Math.cos(sigma);
var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
sigmaP = sigma;
sigma = s / (b * A) + deltaSigma;
}
var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
var lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
(1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp));
var lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
var C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
var L = lambda - (1 - C) * f * sinAlpha *
(sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
// var revAz = Math.atan2(sinAlpha, -tmp); // final bearing
var lngLatObj = {
lng: lon1 + deg(L),
lat: deg(lat2)
}
return lngLatObj;
}
数据格式
鉴于有些同学想看下数据格式,今天刚好出现了新的台风
{
“power”: “13”,
“radius7”: “[360,300,280,280]”,
“radius10”: “[90,90,80,80]”,
“radius12”: “[50,50,40,40]”,
“strong”: “4”,
“pressure”: “965”,
“time”: “2023-05-22 14:00:00”,
“speed”: “38”,
“moveSpeed”: “13”,
“moveDirection”: “北北西”,
“jl”: " “玛娃”将以每小时10-15公里的速度向北偏西方向移动,强度逐渐增强 (下次更新时间为22日17时30分)“,
“ckposition”: " 距离美国关岛南偏东方向约510公里”,
“lng”: “147”,
“lat”: “9.4”
}