This is the sixth day of my participation in the November Gwen Challenge. See details: The Last Gwen Challenge 2021.

preface

Due to the recent needs of the project, I need to use OpenLayers in the VUE project to develop GIS map. The article on OpenLayers is not too big on the Internet, so I take this opportunity to share some of my experience in the actual use of the project.

This series will share some of the feature points implemented over the course of the project.

This article mainly explains the trajectory drawing on the map, and some related functions.

The specific implementation

Functions to be implemented in this article:

  • Modify the pop-up card in article 1 to add a history button
  • Click on the historical track to pop up the track map window
  • Add time filter. You can query by time filter
  • Draw the trajectory

Ok, next step to implement:

1. Add a button

Modify vUE +OpenLayers project Practice (1) : Basically draw and click the popover realized in the popover, and add the button.

// Home.vue<! -- Info popup --><div ref="popup" class="popup" v-show="showPopup">
  <div class="info">
    <ul>
      <li>Message 1: XXX</li>
      <li>Message 2: XXX</li>
      <li>Message 3: XXX</li>
    </ul>
    <div class="btns-box">
      <el-button @click.native="handleOperate('dialog-route')">history</el-button>
    </div>
  </div>
</div>
Copy the code

In the actual project, it is also necessary to pass point id and other parameters, and obtain different track routes according to different point points. Since this is only a teaching demo, it will not be implemented in detail. Students can improve the code according to their actual needs of the project.

Here you need to pass the left-click position to position for popup view center Settings and modify the mouseClick method in home.vue

2. Add a pop-up component

Next, implement the popover component dialog-route, create a route. vue file in the Components folder and import it in the home.vue folder.

components: {
  DialogFence: () = > import("@/components/Fences"),
  DialogRoute: () = > import("@/components/Route"),},Copy the code

The new Route. Vue

<! -- * @Author: Shao Tao * @Date: 2021-11-18 10:28:33
 * @LastEditTime: 2021-11-18 10:47:59
 * @LastEditors: Shao Tao
 * @Description: 
 * @FilePath: \vue-openlayers\src\components\Route.vue
-->
<template>
  <el-dialog
    title="Historical track"
    :visible="dialogVisible"
    custom-class="route"
    append-to-body
    @close="handleClose"
    width="1200px"
    destroy-on-close
  >
    <div id="fence-map" class="map-box"></div>
    <div class="map-area">
      <el-card class="tool-window" style="width: 380px"> </el-card>
    </div>
  </el-dialog>
</template>

<script>
import { Map, View } from "ol";
import { Tile as TileLayer } from "ol/layer";

import { getMap } from "@/utils/webStorage";
import mapType from "@/utils/openlayers/maptype";
export default {
  props: {
    visible: {
      type: Boolean.default: false,},location: {
      type: Array.default: () = > {
        return[]; }},},data() {
    return {
      dialogVisible: false.locaMap: null.openMap: null.routeSource: null}; },watch: {
    visible: {
      handler: function (value) {
        if (value) {
          this.dialogVisible = true;
          this.locaMap = getMap() || "0";
          this.$nextTick(() = > {
            this.initMap(); }); }},immediate: true,}},mounted() {},
  methods: {
    initMap() {
      const _maplist = mapType;
      const _tileLayer = new TileLayer({
        source: _maplist.find((e) = > e.id === this.locaMap).value,
      });
      this.openMap = new Map({
        target: "fence-map".layers: [_tileLayer],
        view: new View({
          center: this.location,
          zoom: 10,}).controls: [],}); },handleClose() {
      this.$emit("close"); ,}}};</script>

<style lang="scss" scoped>
.route {
  .el-dialog__header {
    padding: 20px;
  }
  .el-dialog__body {
    padding: 0;
    .map-area {
      box-shadow: inset 5em 1em # 000000;
      position: relative;
      .tool-window {
        width: 200px;
        position: absolute;
        bottom: 20px;
        right: 20px;
        .button {
          font-size: 20px;
        }
      }
    }
  }
}
.map-box {
  width: 100%;
  height: 60vh;
}
</style>

Copy the code

OK, click the button to realize the popup function. Next, modify the card in the lower left corner of the popup and add a time selection.

3. Add time filtering

In the time project, the historical track often has a large amount of data, if the one-time request rendering is obviously not realistic, so it needs to be segmented by time, according to the time interval request.

Added a time selector component and a query button to el-Card.

<el-card class="tool-window" style="width: 380px">
    <el-date-picker
      v-model="dateRange"
      type="daterange"
      value-format="yyyy-MM-dd"
      start-placeholder="Start time"
      end-placeholder="End time"
      style="width: 100%"
    >
    </el-date-picker>
    <div style="margin-top: 15px">
      <el-button type="primary" @click="getList">The query</el-button>
    </div>
</el-card>
Copy the code

Add the getList method to request the data, which is directly demonstrated with fake data.

getList() {
  let _data = [
    [108.945951.34.465262],
    [109.04724.34.262504],
    [108.580321.34.076162],
    [110.458983.35.071209],
    [105.734862.35.49272]];this.routes = _data.map((item) = > {
    return olProj.fromLonLat(item);
  });
  this.drawRoute();
},
// Draw the trajectory
drawRoute() {},
Copy the code

Next, implement the drawRoute method.

4. Trace

To draw the track, call the LineString class, and draw the Point mark on the track. Point is also needed.

// Draw the trajectory
drawRoute() {
  if (this.routeGeometry) {
    this.routeSource.clear();
  }
  this.routeGeometry = new LineString(this.routes);
  let route = new Feature(this.routeGeometry);
  / / draw point
  let opints = this.drawPoint();
  this.routeSource.addFeatures([route, ...opints]);
},
/ / draw point
drawPoint() {
  let iconFeatures = [];
  this.routes.forEach((item) = > {
    let _feature = new Feature(new Point(item));
    let _style = new Style({
      image: new sCircle({
        radius: 10.stroke: new Stroke({
          color: "#fff",}).fill: new Fill({
          color: "#3399CC",})})}); _feature.setStyle(_style); iconFeatures.push(_feature); });return iconFeatures;
},
Copy the code

Finally, the view is positioned to the position of the track, so that the whole track can be displayed in the center of the map.

// Draw the trajectory
drawRoute(){...// Scale according to trajectory boundaries
  this.mapFit();
},
mapFit() {
  let view = this.openMap.getView();
  view.fit(this.routeGeometry, {
    padding: [120.120.120.120]}); },Copy the code

Ok, now the entire track is on the map.

Note that in getList, the latitude and longitude array must be converted by olProj. FromLonLat, otherwise it will not be displayed on the map.

The final result

Past Catalogue:

  1. Vue +OpenLayers Project Practice (I) : Basic drawing and clicking pop-ups

  2. Vue +OpenLayers Project Practice (2) : Switching between multiple maps

  3. Vue +OpenLayers Project Practice (3) : Cluster

  4. Vue +OpenLayers Project Practice 4: Set up a fence

  5. Vue +OpenLayers Project Practice 5: Historical fencing

The last

Gitee address: gitee.com/shtao_056/v…

Thank you for reading

It would be a great honor if I could help you.

In the future, more functions will be updated, as well as some problems encountered in the project, interested partners can click favorites/follow.