“This is the fifth day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.
preface
Due to the recent needs of the project, IT is necessary to use OpenLayers in the VUE project to develop GIS map. There are not many articles on OpenLayers on the Internet, so I would like to 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 continues with the previous vue+OpenLayers project practice (4) : Setting up the fence, and continues to explain the function points of the fence.
The specific implementation
Functions to be implemented in this article:
- Design and parse the data storage format of the fence
- Handling repeated drawing
- View the History fence
Design data formats
The function of drawing the fence has been completed in the last article, so how to store the drawn fence information for subsequent use? In the last article, we reserved a method to save the fence data, so we will continue to improve this part of the code.
handleSave() {
/ / save
},
Copy the code
Here we add a new method called drawEnd that listens to parse the data when the drawing is complete:
// Finish drawing the parse structure
drawEnd(evt) {
let geo = evt.feature.getGeometry();
let type = geo.getType(); // Get the type
const handle = {
Circle: () = > {
// Get the center point and radius
let center = geo.getCenter();
let radius = geo.getRadius();
this.circleInfo = {
center: center,
radius: parseInt(radius),
};
},
Polygon: () = > {
// get the coordinates
let points = geo.getCoordinates();
this.polygonPath = points[0]; }};if (handle[type]) handle[type]();
},
Copy the code
A handle object is defined to handle the drawn data. The circle stores the center point and radius to this.circleInfo, and the polygon stores the point path to this.polygonPath. Register listening in addInteraction:
this.fenceDraw.on("drawend".(e) = > {
// Draw the completed callback
this.drawEnd(e);
});
Copy the code
Take a look at the print:
It can be seen that the fence information has been obtained, but the coordinates are not common longitude and latitude information, so we will conduct data processing when saving.
Start by defining the data handler function
import * as olProj from "ol/proj";
// Data processing
formatFenceData() {
const handle = {
Circle: () = > {
if (!this.circleInfo) {
this.$message.error(this.$t("lan_map.lan_map_fences.pdrwf"));
return;
}
const center = this.circleInfo.center;
const radius = this.circleInfo.radius;
const p = olProj.toLonLat(center);
return `Circle (${p[0]} ${p[1]}.${radius}) `;
},
Polygon: () = > {
if (this.polygonPath.length === 0) {
this.$message.error(this.$t("lan_map.lan_map_fences.pdrwf"));
return;
}
const path = this.polygonPath;
const pathArr = [];
path.forEach((item) = > {
const p = olProj.toLonLat(item);
pathArr.push(`${p[0]} ${p[1]}`);
});
return `Polygon (${pathArr.join(",")}) `; }};const type = this.tool;
if (handle[type]) {
returnhandle[type](); }},Copy the code
Circle (${p[0]} ${p[1]}, ${radius}) and Polygon (${patharr.join (“, “)})
Circle (107.62493031295215, 33.55224298744986, 21716)
Polygon (107.60051625976537 33.56038110614992, 107.71404159451102 33.612243570978194, 107.77995947944197, 33.47591089982609)
Finally modify the handleSave method, here is stored locally, XDM can directly adjust the back end of the interface to store the fence information, this paper is directly stored in the local VUex, vuex added without more explanation, front-end base operation. Interested can directly look at the source code.
handleSave() {
/ / save
if (!this.name) {
this.$message.error("Please enter fence name");
return;
}
const area = this.formatFenceData();
if (area) {
let data = {
name: this.name,
area: area,
};
// Can call the backend API to save, this article directly stored in the local vuex
this.addFences(data); }},Copy the code
Handling repeated drawing
In the process of using it, we found that multiple overlapping areas could be drawn when drawing the fence, which was obviously not what we wanted. For example, when we finished drawing a circle, we did not allow overlap to draw a circle, but empty and draw a new one.
The method mapOnly needs to be added
addInteraction() {
this.fenceDraw = new Draw({
source: this.fenceSource,
type: this.tool,
});
this.openMap.addInteraction(this.fenceDraw);
this.fenceDraw.on("drawend".(e) = > {
// Draw the completed callback
this.drawEnd(e);
});
// Check for duplicate drawing
this.mapOnly();
},
mapOnly() {
this.fenceDraw.on("drawstart".() = > {
if (this.tool === "Polygon") {
Delete the previous geometry if it already exists
if (this.polygonPath)
this.fenceSource.clear() && (this.polygonPath = []);
} else {
if (this.circleInfo)
this.fenceSource.clear() && (this.circleInfo = null); }}); },Copy the code
Only one circle/polygon can be drawn when the fence is drawn.
View the History fence
OK, the above are the functions of the newly added fence, so the new purpose is to view the historical fence records after storage, and the function of viewing will be implemented now.
// Home.vue obtains fence data from vuex
computed: {
...mapGetters(["fences"]),},Copy the code
We need to add a drop down in the bottom right corner to toggle the display fence as we did with the map. Refer to vue+OpenLayers project practice (2) : Switching between multiple maps
<! -- Map fence --><el-select v-model="fence" style="width: 150px">
<el-option
label="Do not show the fence"
value="1"
key="1"
@click.native="handleSelectFence(null)"
></el-option>
<el-option
v-for="(item, index) in fences"
:label="item.name"
:value="item.name"
:key="index"
@click.native="handleSelectFence(item)"
></el-option>
</el-select>
Copy the code
data(){
return{...fence: null,}}...// Display the fence
handleSelectFence() {},
Copy the code
Next, implement handleSelectFence and draw the fence on the map.
First add the data conversion function
// Fence data conversion
areaFomart(area) {
// eslint-disable-next-line
const point = area.match(/ [^ \] (\) + (? =\))/g) [0].split(",");
if (area.match("Circle")) {
return {
type: "Circle".center: olProj.fromLonLat(point[0].split("")),
radius: Number(point[1]),}; }if (area.match("Polygon")) {
const path = [];
point.forEach((item) = > {
path.push(olProj.fromLonLat(item.split("")));
});
return {
type: "Polygon".path: path, }; }}Copy the code
Modify the handleSelectFence method
// Display the fence
handleSelectFence(data) {
// Clear the previous fence when switching
if (this.fenceVector) {
this.openMap.removeLayer(this.fenceVector);
}
if(! data) {this.fence = null;
return false;
}
// Data conversion
const area = this.areaFomart(data.area);
// Draw the fence
this.setFenceSource(area);
},
Copy the code
setFenceSource
// Draw the fence
setFenceSource(area) {
let feature;
switch (area.type) {
case "Circle": {
feature = new Feature(new gCircle(area.center, area.radius));
break;
}
case "Polygon": {
feature = new Feature(new Polygon([area.path]));
break;
}
default:
break;
}
// Zoom to the fenced area
this.mapFit(feature.getGeometry());
// Vector layer
let source = new VectorSource({
features: [feature],
});
let vector = new VectorLayer({
source,
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.fenceVector = vector;
this.openMap.addLayer(vector);
},
// Scale by boundaries
mapFit(extent) {
this.openMap
.getView()
.fit(extent, { duration: 1000.padding: [200.200.200.200]}); },Copy the code
The mapFit method can automatically zoom the map to the fence.
OK, all functions related to the fence have been implemented. The following is the final effect:
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
-
Vue +OpenLayers Project Practice 4: Set up a 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.