1. 根據請求接口,動態返回經緯度在map地圖上渲染人員軌跡效果
參考官方文檔:https://openlayers.org/en/latest/examples/feature-move-animation.html
初級版參考:vue openlayers【九】基於LineString和Point實現流動軌跡的效果展示
2. 思路詳解 (下面就可以實現動態加載軌跡信息了,已經講得很詳細了,一些細節不懂的可以看我其他博客,這裏就沒有具體闡述了,如果看不懂打死我好吧)
寫在前面:你需要了解或簡單使用過 openlayers 會更理解
2.1首先初始化一個 map 地圖,我們不做任何其他操作,只是簡單加載map地圖
mounted 鉤子中加載
mounted() {
this.initMap(); //初始化地圖
this.getTrack(); //請求軌跡的接口
}
initMap() {
let _that = this;
let target = "map";
let tileLayer = [
new TileLayer({
source: new XYZ({
url:
"http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}"
})
})
];
let view = new View({
center: fromLonLat([120.9800615193, 29.1326618704]),
zoom: 14 //縮放級別
});
this.map = new Map({
target: target,
layers: tileLayer,
view: view
});
},
2.2 加載 getTrack()
方法,請求接口,渲染軌跡信息
動態請求接口數據,經緯度數據存放在
routeCoords
變量中
數據獲取完成後調用 添加軌跡圖層addLayers
方法
/**
* 動態獲取軌跡信息接口(根據開始結束時間獲取該人員這時間段的動態軌跡信息)
* 接口參數三個字段:
* userName:用戶名(這裏是固定的)
* startTime:開始時間
* endTime:結束時間
*/
async getTrack() {
let _that = this;
let obj = {
userName: "rzxwg",
startTime: this.startTime
? this.startTime
: "2020-05-21 00:00:00",
endTime: this.endTime ? this.endTime : "2020-05-21 22:59:59"
};
let res = await axiosRest(
`${Settings.MapTrack}${obj.userName}&startTime=${obj.startTime}&endTime=${obj.endTime}`,
{},
"get"
);
if (res.code == "0") {
let TrackData = res.data;
// 請求的軌跡經緯度數據添加到 this.routeCoords 中
TrackData.forEach(e => {
this.routeCoords.push([
parseFloat(e.centerLon),
parseFloat(e.centerLat)
]);
});
// 加載軌圖層
this.addLayers();
}
},
接口請求參數和返回數據截圖
2.3 添加 軌跡 和(起點終點)方法
① 判斷如果上次的圖層存在,先刪除上次的圖層
② 根據獲取的routeCoords
創建線LineString
③ 創建開始的標註Point
圖標(這裏設置一個type屬性,方便後面判斷設置img)
④ 同理創建結束的標註圖標,這裏的 值是取this.routeCoords.length - 1
,就是結尾的經緯度點
⑤ 寫一個styles
設置樣式的對象,後面調用
⑥ 創建圖層,把線LineString
和 圖標Point
添加到圖層裏面,style 屬性的返回值是styles
對象的key做匹配,獲取對應的樣式
⑦ 加載完成之後就基本完成了,根據經緯度軌跡設置自適應窗口fit
/**
* 添加 軌跡 和(起點終點)方法
*/
addLayers() {
// 1. 第二次以後渲染軌跡的時候把上次的圖層先刪除
if (this.vectorLayer) {
this.map.removeLayer(this.vectorLayer);
}
let _that = this;
// 2. 根據經緯度點位創建線
var routeFeature = new Feature({
type: "route",
geometry: new LineString(this.routeCoords).transform(
"EPSG:4326",
"EPSG:3857"
)
});
// 3. 創建開始圖標
let startMarker = new Feature({
type: "startMarker",
geometry: new Point(this.routeCoords[0]).transform(
"EPSG:4326",
"EPSG:3857"
)
});
// 4. 創建結束圖標
let endMarker = new Feature({
type: "endMarker",
geometry: new Point(
this.routeCoords[this.routeCoords.length - 1]
).transform("EPSG:4326", "EPSG:3857")
});
let markerStyleInfo = {
startImg: require("../../assets/images/start.png"),
endImg: require("../../assets/images/end.png"),
anchor: [0.5, 1.1]
};
// 5. 設置樣式
var styles = {
// 如果類型是 route,startMarker,endMarker 的樣式
route: new Style({
stroke: new Stroke({
width: 2,
color: "#ffc641"
})
}),
startMarker: new Style({
image: new Icon({
src: markerStyleInfo.startImg,
anchor: markerStyleInfo.anchor //設置偏移
})
}),
endMarker: new Style({
image: new Icon({
src: markerStyleInfo.endImg,
anchor: markerStyleInfo.anchor //設置偏移
})
})
};
// 6. 把小車和線添加到圖層
this.vectorLayer = new VectorLayer({
source: new VectorSource({
features: [routeFeature, startMarker, endMarker]
}),
style: function(feature) {
if (
_that.animating &&
feature.get("type") === "geoMarker"
) {
return null;
}
return styles[feature.get("type")];
}
});
this.map.addLayer(this.vectorLayer);
// 7. 重置窗口視圖的位置
this.map
.getView()
.fit(
new Polygon([this.routeCoords]).transform(
"EPSG:4326",
"EPSG:3857"
),
{ padding: [100, 100, 100, 100] }
);
},
2.4 選擇日期後,重新繪製軌跡
/**
* 選擇日期後重新調用接口,重新獲取經緯度點位數據,重新繪製軌跡
*/
timeChange(params) {
if (params) {
this.startTime = params[0];
this.endTime = params[1];
this.getTrack();
}
}
3. vue 完整代碼
<template>
<div id="content">
<div id="map" ref="map"></div>
<div id="box">
<el-date-picker
v-model="time"
type="daterange"
range-separator="至"
start-placeholder="開始日期"
end-placeholder="結束日期"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
@change="timeChange"
></el-date-picker>
</div>
</div>
</template>
<script>
import "ol/ol.css";
import { Map, View, Feature, ol } from "ol";
import Proj from "ol/proj/Projection";
import Units from "ol/proj/Units";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Style, Stroke, Fill, Icon } from "ol/style";
import { LineString, Point, Polygon } from "ol/geom";
import XYZ from "ol/source/XYZ";
import { fromLonLat, transformExtent } from "ol/proj";
import Settings from "@/lib/Setting";
import { axiosRest } from "@/api/api.js";
export default {
name: "track-run",
data() {
return {
map: null,
animating: false,
vectorLayer: null, //圖層
routeCoords: [], // 存放軌跡經緯度數據
time: "",
startTime: "",
endTime: ""
};
},
methods: {
/**
* 初始化一個map地圖
*/
initMap() {
let _that = this;
let target = "map";
let tileLayer = [
new TileLayer({
source: new XYZ({
url:
"http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}"
// url:
// "http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m3!1e0!2sm!3i345013117!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0" //Roadmap SATELLITE satellite
})
})
];
let view = new View({
center: fromLonLat([120.9800615193, 29.1326618704]),
zoom: 14 //縮放級別
});
this.map = new Map({
target: target,
layers: tileLayer,
view: view
});
},
/**
* 刪除圖層
*/
removeVectorLayer(vectorLayer) {
if (vectorLayer) this.map.removeLayer(vectorLayer);
},
/**
* 添加 軌跡 和(起點終點)方法
*/
addLayers() {
// 第二次以後渲染軌跡的時候把上次的圖層先刪除
this.removeVectorLayer(this.vectorLayer);
let _that = this;
// 根據經緯度點位創建線
var routeFeature = new Feature({
type: "route",
geometry: new LineString(this.routeCoords).transform(
"EPSG:4326",
"EPSG:3857"
)
});
// 創建開始圖標
let startMarker = new Feature({
type: "startMarker",
geometry: new Point(this.routeCoords[0]).transform(
"EPSG:4326",
"EPSG:3857"
)
});
// 創建結束圖標
let endMarker = new Feature({
type: "endMarker",
geometry: new Point(
this.routeCoords[this.routeCoords.length - 1]
).transform("EPSG:4326", "EPSG:3857")
});
let markerStyleInfo = {
startImg: require("../../assets/images/start.png"),
endImg: require("../../assets/images/end.png"),
anchor: [0.5, 1.1]
};
// 設置樣式
var styles = {
// 如果類型是 route,startMarker,endMarker 的樣式
route: new Style({
stroke: new Stroke({
width: 2,
color: "#ffc641"
})
}),
startMarker: new Style({
image: new Icon({
src: markerStyleInfo.startImg,
anchor: markerStyleInfo.anchor //設置偏移
})
}),
endMarker: new Style({
image: new Icon({
src: markerStyleInfo.endImg,
anchor: markerStyleInfo.anchor //設置偏移
})
})
};
// 把小車和線添加到圖層
this.vectorLayer = new VectorLayer({
source: new VectorSource({
features: [routeFeature, startMarker, endMarker]
}),
style: function(feature) {
if (
_that.animating &&
feature.get("type") === "geoMarker"
) {
return null;
}
return styles[feature.get("type")];
}
});
this.map.addLayer(this.vectorLayer);
// 重置窗口視圖的位置
this.map
.getView()
.fit(
new Polygon([this.routeCoords]).transform(
"EPSG:4326",
"EPSG:3857"
),
{ padding: [100, 100, 100, 100] }
);
},
/**
* 動態獲取軌跡信息接口(根據開始結束時間獲取該人員這時間段的動態軌跡信息)
* 接口參數三個字段:
* userName:用戶名(這裏是固定的)
* startTime:開始時間
* endTime:結束時間
*/
async getTrack() {
let _that = this;
let obj = {
userName: "rzxwg",
startTime: this.startTime
? this.startTime
: "2020-05-21 00:00:00",
endTime: this.endTime ? this.endTime : "2020-05-21 22:59:59"
};
let res = await axiosRest(
`${Settings.MapTrack}${obj.userName}&startTime=${obj.startTime}&endTime=${obj.endTime}`,
{},
"get"
);
if (res.code == "0") {
let TrackData = res.data;
TrackData.forEach(e => {
this.routeCoords.push([
parseFloat(e.centerLon),
parseFloat(e.centerLat)
]);
});
this.addLayers();
}
},
/**
* 選擇日期後重新調用接口,重新獲取經緯度點位數據,重新繪製軌跡
*/
timeChange(params) {
if (params) {
this.startTime = params[0];
this.endTime = params[1];
this.getTrack();
}
}
},
mounted() {
this.initMap();
this.getTrack();
}
};
</script>
<style lang="scss" scoped>
html,
body {
height: 100%;
#content {
min-height: calc(100vh - 50px);
width: 100%;
position: relative;
overflow: none;
#map {
height: 888px;
min-height: calc(100vh - 50px);
}
#box {
position: absolute;
z-index: 11;
right: 10px;
top: 10px;
background-color: #0d9bf2;
opacity: 0.7;
border-radius: 3px;
padding: 10px;
font-size: 12px;
#startButton,
#pauseButton {
cursor: pointer;
}
}
}
}
</style>