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>

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