vue openlayers实现台风轨迹示例详解
冬日暖阳一片云 人气:0功能描述
- 台风轨迹点实时绘制,根据不同点的类型绘制不同的轨迹点颜色
- 轨迹线绘制,涉及实时轨迹线段与预报轨迹线,根据台风类型绘制成不同颜色
- 当前正在发生的台风还需增加当前台风所风圈位置
- 台风轨迹点点击弹框显示轨迹点信息
openlayers(简称ol)这里不做介绍,刚开始写此类文章,直接上代码
创建一个地图容器
引入地图相关对象
import Map from 'ol/Map'; import View from 'ol/View'; import XYZ from 'ol/source/XYZ'; import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
创建地图对象
都是一些基本活
const center = [-5639523.95, -3501274.52]; const map = new Map({ target: document.getElementById('map'), view: new View({ center: center, zoom: 10, minZoom: 2, maxZoom: 19, }), layers: [ ], }); this.addEventMapClick()
监听地图点击事件
addEventMapClick () { const nameDom = document.createElement('div') nameDom.setAttribute('class', 'typhoon-popup') const nameOverlay = new ol.Overlay({ element: nameDom, position: [0, 0], positioning: 'right-center', stopEvent: false, insertFirst: false, autoPanAnimation: { duration: 250 } }) this.viewer.addOverlay(nameOverlay) this._popup = nameOverlay // 监听地图点击事件 this.viewer.on('singleclick', e => { this._popup.getElement().parentElement.style.display = 'none' this.viewer.forEachFeatureAtPixel( e.pixel, (result) => { if (result) { let Properties = result.get('properties') let layerType = result.get('layerType') // 台风点点击 // && layerType === 'typhoonpoint' if (layerType === 'typhoonLyer') { let html = `<div class="typhoonLyer"><div class="con">名称: ${Properties.CODE || ''} ${Properties.NAME_CN || ''} ${Properties.NAME_EN || ''}</div> <div class="con">风速: ${Properties.MOVE_SPEED || '--'} km/h</div> <div class="con">中心气压: ${Properties.PRESS || '--'}</div> <div class="con">时间: ${Properties.time || '--'}</div> <div class="con">中心位置: ${Properties.LON}/${Properties.LAT}</div></div>` this._popup.getElement().innerHTML = html this._popup.setPosition([Properties.LON, Properties.LAT]) // this._popup.setOffset([25, 0]) this._popup.getElement().parentElement.style.display = 'block' } else { this._popup.getElement().parentElement.style.display = 'none' } } } ) }) }
开始绘制
准备台风数据和图层
台风数据我是用的JSON。这里就简单描述一下数据中只要用到的字段信息
[ { CODE: "202122",//台风编号 DB7: null,//七级东北 DB10: null,//十级东北 DB12: null,//十二级东北 DN7: null,//七级东南 DN10: null,//十级东南 DN12: null,//十二级东南 LAT: 5.5,//维度 LON: 140.9,//经度 MOVE_DIR: null,//风向 MOVE_SPEED: null,//风向速度 OBJECTID: 27848,//id PRESS: 998,//中心气压 SHIJIAN: null, STRENGTH: "台风(热带风暴级)",//强度 TH: null, TIME: "2021-12-13-14",//日期 WIND: 18,//最大风速 XB7: null,//七级西北 XB10: null,//十级西北 XB12: null,//十二级西北 XN7: null,//七级西南 XN10: null,//十级西南 XN12: null,//十二级西南 }, ]
let tfsource = new ol.source.Vector({ crossOrigin: 'anonymous', features: [] }) let tflayer = new ol.layer.Vector({ source: tfsource }) map.addLayer(tflayer)
绘制台风名称
// 利用第一个点 创建名称Overlay层 显示台风名称 const nameDom = document.createElement('div') nameDom.setAttribute('class', 'typhoon-name-panel') nameDom.classList.add(lx) nameDom.innerHTML = label const position = [point.LON, point.LAT] const nameOverlay = new ol.Overlay({ element: nameDom, position: position, wz: position, positioning: 'center-left', offset: [15, 0] }) map.addOverlay(nameOverlay) map.getView().setCenter(position)
绘制台风轨迹点和轨迹线
//point 为数组对象中每一个点数据 // 点颜色 根据强度区分不同点的颜色 let pointColor = this.setPointFillColor(point.STRENGTH) // 添加点 if (point.LON && point.LAT) { const feature = new ol.Feature({ geometry: new ol.geom.Point([point.LON, point.LAT]), layerType: 'typhoonLyer', properties: point }) // this.tfStyle为我提前定义到的各种类型的点样式 feature.setStyle(this.tfStyle[pointColor.index]) tflayer.getSource().addFeature(feature) } // 添加线 let startPoint = [point.LON, point.LAT] 开始点 let endPonit = [points[index - 1].LON, points[index - 1].LAT] 结束点 let coords = [startPoint, endPonit] let lineDash 线段样式 实线或者虚线 if (lx !== 'ss') { lineDash = [0] } else { lineDash = (!point.predict && !points[index - 1].predict) ? [0] : [10] } // this.tfLinStyle 为提前定义好的线段样式 let lineStyle = lineDash[0] === 0 ? this.tfLinStyle[pointColor.index] : this.tfLinStyle[6] let feature = new ol.Feature({ geometry: new ol.geom.LineString(coords), layerType: 'typhoonLyer', properties: point }) feature.setStyle(lineStyle) tflayer.getSource().addFeature(feature)
代码解析 文中提到的this.tfLinStyle 和 this.tfStyle 为提前定义好的点和线的样式,这么做的目的是为了提高性能,减少oplayer中new 一堆重复性的样式堆栈,消耗内存
this.tfStyle = [ new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({ color: '#eed139' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.6)', width: 1 }) }) }), new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({ color: '#0000ff' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.6)', width: 1 }) }) }), new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({ color: '#0f8000' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.6)', width: 1 }) }) }), new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({ color: '#fe9c45' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.6)', width: 1 }) }) }), new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({ color: '#fe00fe' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.6)', width: 1 }) }) }), new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({ color: '#fe0000' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.6)', width: 1 }) }) }) ] this.tfLinStyle = [ new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#eed139', width: 2, lineDash: [0] }) }), new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#0000ff', width: 2, lineDash: [0] }) }), new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#0f8000', width: 2, lineDash: [0] }) }), new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#fe9c45', width: 2, lineDash: [0] }) }), new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#fe00fe', width: 2, lineDash: [0] }) }), new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#fe0000', width: 2, lineDash: [0] }) }), new ol.style.Style({ stroke: new ol.style.Stroke({ color: '#fe0000', width: 2, lineDash: [10] }) })]
setPointFillColor函数判别点类型
setPointFillColor (type) { let pointFillColor = '#eed139' let index = 0 switch (type) { case '台风(热带低压)': case '热带低压': pointFillColor = '#eed139' index = 0 break case '热带风暴': case '热带风暴级': case '台风(热带风暴)': case '台风(热带风暴级)': pointFillColor = '#0000ff' index = 1 break case '台风(强热带风暴级)': case '强热带风暴级': case '强热带风暴': pointFillColor = '#0f8000' index = 2 break case '台风': pointFillColor = '#fe9c45' index = 3 break case '强台风': case '台风(强台风级)': case '台风(强台风)': pointFillColor = '#fe00fe' index = 4 break case '超强台风': case '台风(超强台风级)': case '台风(超强台风)': pointFillColor = '#fe0000' index = 5 break } return {pointFillColor, index} }
以上代码很完整,我加了注释,整体思路总结如下:
- 先获取台风数据
- 构造台风轨迹图层并添加到地图容器
- 循环构造点、线及名称要素对象 添加到台风图层数据源中
- 添加风圈动画
添加台风风圈动画
根据判断台风类型是否是实时台风还是历史台风进行添加台风风圈,在数据中获取到最后一个实时点位数据,利用Overlay添加一个动态图标,我是利用的gif图片
let key = LX + '-' + tfbh const points = this._typhoonData[key].point let fqindex = points.findIndex(item => !item.predict) // 添加风圈 if (fqindex) { const nameDom = document.createElement('div') nameDom.setAttribute('class', 'typhoon-area') let nameOverlay = new ol.Overlay({ position: [points[fqindex].LON, points[fqindex].LAT], positioning: 'center-bottom', element: nameDom, // 绑定上面添加的元素 stopEvent: false, offset: [-15, -15]// 图片偏移量 }) this.viewer.addOverlay(nameOverlay) this._tfenterCollection[key]['areaoverlay'] = nameOverlay }
让台风轨迹动起来
加载的时候利用定时器,一个点位一个点位的绘制,这样看起来就有动画效果啦
this._typhoonPlayFlag[key] = setInterval(() => { 去干些事请 }, 50)
结尾
这里我只是大致的描述了我绘制台风轨迹的一些思路和大致方法,具体项目中,我把整个过场都封装成一个class 类,毕竟台风可能是有多条的,而且还需要做一些显示隐藏等的一些操作,我这里不做过多描述,仅做为一些思路分享,更多关于vue openlayers台风轨迹的资料请关注其它相关文章!
加载全部内容