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

One, foreword

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. 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

Today, we are going to learn the function of fence. Fence is to draw a regular or irregular area on the map and deal with the relationship between position and area by judging whether coordinates are in the area. Common application scenarios are as follows:

  • Check in and punch in. Before punching in, judge whether the user is already in the corresponding geographical fenced area;
  • Range monitoring, such as whether shared bikes drive outside the designated geofenced area;
  • And so on…

As usual, let’s see if the authorities have provided a basic case:

draw-shapes

draw-features

Second, concrete implementation

Analyze the functions we need to implement:

  1. Realize the right menu, open the new fence pop-up window
  2. The new fence
  3. Check the enclosure
  4. Determine whether the point is within the fenced area

This section introduces the first half.

1. Right-click the menu

First of all to achieve a right-click menu, right-click on the map, directly with the right location as the center of the pop-up fence drawing shell layer.

Specific implementation steps:

  • Add overlay to map from right-click menu
  • Get the Dom of the map with getViewport() and override its right-click event

Vue +OpenLayers Project Practice (1) : Basic drawing and clicking popover, here is not much explanation, here mainly provides the code related to the right click

// Right click
this.openMap.getViewport().oncontextmenu = (e) = > {
  // Cancel the default right-click event
  e.preventDefault();
  this.showMenuPopup = true;
  // Set the popover position to follow the mouse
  let coordinates = this.openMap.getEventCoordinate(e);
  this.position = coordinates;
  this.menuPopup.setPosition(coordinates);
};
Copy the code

2. Add fences

Click on the new fence to pop up the pop-up window. Add Fences. Vue under Components.

<template>
  <el-dialog
    title=Edit fence
    :visible="dialogVisible"
    custom-class="fence"
    append-to-body
    @close="handleClose"
    width="1200px"
    destroy-on-close
  >
    <div id="fence-map" class="map-box"></div>
  </el-dialog>
</template>

<script>
import { Map, View } from "ol";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { Vector as VectorSource } from "ol/source";
import { Style, Fill, Stroke, Circle as sCircle } from "ol/style";
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.fenceSource: 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.fenceSource = new VectorSource({ wrapX: false });

      const _vector = new VectorLayer({
        source: this.fenceSource,
        style: new Style({
          fill: new Fill({
            color: "Rgba (49173252, 0.2)",}).stroke: new Stroke({
            color: "#0099FF".width: 3,}).image: new sCircle({
            radius: 7.fill: new Fill({
              color: "#0099FF",}),}),}),});this.openMap = new Map({
        target: "fence-map".layers: [_tileLayer, _vector],
        view: new View({
          center: this.location,
          zoom: 10,}).controls: [],}); },handleClose() {
      this.$emit("close"); }}};</script>

<style lang="scss" scoped>
.fence {
  .el-dialog__header {
    padding: 20px;
  }
  .el-dialog__body {
    padding: 0; }}.map-box {
  width: 100%;
  height: 60vh;
}
</style>
Copy the code

You also need to set the popover in home.vue:

<template> ... <! -- Component container --><component
  v-if="operateDialogVisible"
  :is="currentComponent"
  :visible="operateDialogVisible"
  :location="position"
  @close="handleOperateClose"
></component>. </template>data(){...operateDialogVisible: false.currentComponent: null.position: null,}// Add method
// Open the popover
handleOperate(component) {
  this.showMenuPopup = false;
  this.operateDialogVisible = true;
  this.currentComponent = component;
},
// Close the popover
handleOperateClose() {
  this.operateDialogVisible = false;
},
Copy the code

Add fences in the fences component. The main API is “OL/Interaction /Draw”. First add a button to set fences on the page to Draw circles and polygons.

<div class="map-area">
  <el-card class="tool-window" style="width: 380px">
    <el-form label-width="80px">
      <el-form-item label="Name of fence">
        <el-input
          size="small"
          v-model="name"
          placeholder="Please enter fence name"
        ></el-input>
      </el-form-item>
      <el-form-item label="Fence style">
        <el-radio-group v-model="tool" size="small" @change="setType">
          <el-radio-button label="Circle">circular</el-radio-button>
          <el-radio-button label="Polygon">polygon</el-radio-button>
        </el-radio-group>
      </el-form-item>
      <el-form-item>
        <el-button type="warning" size="small" @click="handleClear"
          >Remove < / el - button ><el-button type="primary" size="small" @click="handleSave"
          >Save < / el - button ><el-button size="small" @click="handleClose">cancel</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</div>
Copy the code

The page style is shown below. Now let’s implement the fence drawing.

First, Draw

import Draw from "ol/interaction/Draw";
Copy the code
// Add attributes to data
data() {
    return{...fenceSource: null.fenceDraw: null.tool: "Circle".name: ""}; },// Implement addInteraction methods
addInteraction() {
  this.fenceDraw = new Draw({
    source: this.fenceSource,
    type: this.tool,
  });
  this.openMap.addInteraction(this.fenceDraw);
},
// Switch the type
setType() {
  this.fenceSource.clear();
  this.openMap.removeInteraction(this.fenceDraw);
  this.addInteraction();
},
// Button method
handleClear() {
  this.fenceSource.clear();
},
handleSave() {
  / / save
},
// called in initMap
initMap(){...this.addInteraction();
}
Copy the code

OK, this chapter has realized the preliminary drawing function of the fence, and the next chapter will continue to introduce other function points of the fence.

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.