vue?openlayers實現(xiàn)臺風(fēng)軌跡示例詳解

功能描述
- 臺風(fēng)軌跡點實時繪制,根據(jù)不同點的類型繪制不同的軌跡點顏色
- 軌跡線繪制,涉及實時軌跡線段與預(yù)報軌跡線,根據(jù)臺風(fēng)類型繪制成不同顏色
- 當(dāng)前正在發(fā)生的臺風(fēng)還需增加當(dāng)前臺風(fēng)所風(fēng)圈位置
- 臺風(fēng)軌跡點點擊彈框顯示軌跡點信息
openlayers(簡稱ol)這里不做介紹,剛開始寫此類文章,直接上代碼
創(chuàng)建一個地圖容器
引入地圖相關(guān)對象
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';
創(chuàng)建地圖對象
都是一些基本活
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()
監(jiān)聽地圖點擊事件
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
// 監(jiān)聽地圖點擊事件
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')
// 臺風(fēng)點點擊
// && 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">風(fēng)速: ${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'
}
}
}
)
})
}
開始繪制
準(zhǔn)備臺風(fēng)數(shù)據(jù)和圖層
臺風(fēng)數(shù)據(jù)我是用的JSON。這里就簡單描述一下數(shù)據(jù)中只要用到的字段信息
[
{
CODE: "202122",//臺風(fēng)編號
DB7: null,//七級東北
DB10: null,//十級東北
DB12: null,//十二級東北
DN7: null,//七級東南
DN10: null,//十級東南
DN12: null,//十二級東南
LAT: 5.5,//維度
LON: 140.9,//經(jīng)度
MOVE_DIR: null,//風(fēng)向
MOVE_SPEED: null,//風(fēng)向速度
OBJECTID: 27848,//id
PRESS: 998,//中心氣壓
SHIJIAN: null,
STRENGTH: "臺風(fēng)(熱帶風(fēng)暴級)",//強度
TH: null,
TIME: "2021-12-13-14",//日期
WIND: 18,//最大風(fēng)速
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)
繪制臺風(fēng)名稱
// 利用第一個點 創(chuàng)建名稱Overlay層 顯示臺風(fēng)名稱
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)
繪制臺風(fēng)軌跡點和軌跡線
//point 為數(shù)組對象中每一個點數(shù)據(jù)
// 點顏色 根據(jù)強度區(qū)分不同點的顏色
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] 結(jié)束點
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 一堆重復(fù)性的樣式堆棧,消耗內(nèi)存
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函數(shù)判別點類型
setPointFillColor (type) {
let pointFillColor = '#eed139'
let index = 0
switch (type) {
case '臺風(fēng)(熱帶低壓)':
case '熱帶低壓':
pointFillColor = '#eed139'
index = 0
break
case '熱帶風(fēng)暴':
case '熱帶風(fēng)暴級':
case '臺風(fēng)(熱帶風(fēng)暴)':
case '臺風(fēng)(熱帶風(fēng)暴級)':
pointFillColor = '#0000ff'
index = 1
break
case '臺風(fēng)(強熱帶風(fēng)暴級)':
case '強熱帶風(fēng)暴級':
case '強熱帶風(fēng)暴':
pointFillColor = '#0f8000'
index = 2
break
case '臺風(fēng)':
pointFillColor = '#fe9c45'
index = 3
break
case '強臺風(fēng)':
case '臺風(fēng)(強臺風(fēng)級)':
case '臺風(fēng)(強臺風(fēng))':
pointFillColor = '#fe00fe'
index = 4
break
case '超強臺風(fēng)':
case '臺風(fēng)(超強臺風(fēng)級)':
case '臺風(fēng)(超強臺風(fēng))':
pointFillColor = '#fe0000'
index = 5
break
}
return {pointFillColor, index}
}
以上代碼很完整,我加了注釋,整體思路總結(jié)如下:
- 先獲取臺風(fēng)數(shù)據(jù)
- 構(gòu)造臺風(fēng)軌跡圖層并添加到地圖容器
- 循環(huán)構(gòu)造點、線及名稱要素對象 添加到臺風(fēng)圖層數(shù)據(jù)源中
- 添加風(fēng)圈動畫
添加臺風(fēng)風(fēng)圈動畫
根據(jù)判斷臺風(fēng)類型是否是實時臺風(fēng)還是歷史臺風(fēng)進(jìn)行添加臺風(fēng)風(fēng)圈,在數(shù)據(jù)中獲取到最后一個實時點位數(shù)據(jù),利用Overlay添加一個動態(tài)圖標(biāo),我是利用的gif圖片
let key = LX + '-' + tfbh
const points = this._typhoonData[key].point
let fqindex = points.findIndex(item => !item.predict)
// 添加風(fēng)圈
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
}
讓臺風(fēng)軌跡動起來
加載的時候利用定時器,一個點位一個點位的繪制,這樣看起來就有動畫效果啦
this._typhoonPlayFlag[key] = setInterval(() => {
去干些事請
}, 50)
結(jié)尾
這里我只是大致的描述了我繪制臺風(fēng)軌跡的一些思路和大致方法,具體項目中,我把整個過場都封裝成一個class 類,畢竟臺風(fēng)可能是有多條的,而且還需要做一些顯示隱藏等的一些操作,我這里不做過多描述,僅做為一些思路分享,更多關(guān)于vue openlayers臺風(fēng)軌跡的資料請關(guān)注腳本之家其它相關(guān)文章!
- 在Vue?3中使用OpenLayers加載GPX數(shù)據(jù)并顯示圖形效果
- vue+openlayers+nodejs+postgis實現(xiàn)軌跡運動效果
- Vue使用openlayers加載天地圖
- Vue+OpenLayers?創(chuàng)建地圖并顯示鼠標(biāo)所在經(jīng)緯度(完整代碼)
- vue利用openlayers實現(xiàn)動態(tài)軌跡
- Vue結(jié)合openlayers按照經(jīng)緯度坐標(biāo)實現(xiàn)錨地標(biāo)記及繪制多邊形區(qū)域
- Vue openLayers實現(xiàn)圖層數(shù)據(jù)切換與加載流程詳解
- Vue利用openlayers實現(xiàn)點擊彈窗的方法詳解
- Vue使用openlayers實現(xiàn)繪制圓形和多邊形
- 在Vue 3中使用OpenLayers讀取WKB數(shù)據(jù)并顯示圖形效果
相關(guān)文章
Vue3+Element+Ts實現(xiàn)表單的基礎(chǔ)搜索重置等功能
本文主要介紹了Vue3+Element+Ts實現(xiàn)表單的基礎(chǔ)搜索重置等功能,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12

