vue openlayers【十】动态加载人员轨迹的效果,设置起点终点图标详解

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>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章