openlayers vue 实现台风

2023-11-27 20:59

本文主要是介绍openlayers vue 实现台风,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

openlayers6+vue2实现台风

  • 代码实现
    • 整体外观
    • 实现轨迹路线
    • 对轨迹点进行打点,因为我们需要点击轨迹点弹出popup
    • 根据台风接口返回的数据来绘制相应的点线和台风圈的数据
    • 绘制台风圈的方法
    • 统一封装的用来绘点的方法
    • 地图创建时绑定点击事件
    • 当点击时有要素
    • 当点击时没有要素或者用来清除popup框等
    • js方法
    • 数据格式

代码实现

整体外观

在这里插入图片描述在这里插入图片描述

实现轨迹路线

一得到数据
在这里插入图片描述

二,轨迹路线点数据放在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-undefconst 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);}});},

地图创建时绑定点击事件

//判断当前单击处是否有要素,捕获到要素时弹出popupthat.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.2572236var 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 bearingvar 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”
}
在这里插入图片描述

这篇关于openlayers vue 实现台风的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/428460

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount