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:
-
Vue +OpenLayers Project Practice (I) : Basic drawing and clicking pop-ups
-
Vue +OpenLayers Project Practice (2) : Switching between multiple maps
-
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:
- Realize the right menu, open the new fence pop-up window
- The new fence
- Check the enclosure
- 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.