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>