“This is the first day of my participation in the Gwen Challenge in November. See details of the event: The last Gwen Challenge in 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 during the project. The following sections are covered in this article:

  1. Project introduction
  2. Render reproduction
  3. Mark drawing
  4. The label information is displayed in the pop-up window

Openlayers

Second, concrete implementation

This project is developed based on VUE. First of all, prepare a VUE project and build one directly with VUE2 + SASS as the project version

1. Introduce Openlayers

The NPM package of Openlayers is called OL, so we can directly introduce OL into the project

npm install ol
// or
yarn add ol
Copy the code

Change the initial file default route page

// app.vue
<template>
  <div id="app">
    <router-view />
  </div>
</template>

<style lang="scss">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>

// Home.vue
<template>
  <div class="home">
  </div>
</template>

<script>
export default {
  name: "Home".components: {}};</script>
Copy the code

2. Base rendering

Map rendering is carried out in home.vue file. This paper adopts the slice map mode of Amap.

// Home.vue
<template>
  <div class="home">
    <div id="map" class="map-home"></div>
  </div>
</template>

<script>
import { Map, View } from "ol";
import * as olProj from "ol/proj";
import TileLayer from "ol/layer/Tile";
import XYZ from "ol/source/XYZ";

export default {
  name: "Home".components: {},
  data() {
    return {
      openMap: null}; },mounted() {
    this.initMap();
  },
  methods: {
    initMap() {
      this.openMap = new Map({
        target: "map".layers: [
          new TileLayer({
            source: new XYZ({
              url: "https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}",})})],view: new View({
          // Make Xi 'an the center of the map
          center: olProj.fromLonLat([108.945951.34.465262]),
          zoom: 1,}).controls: [],}); ,}}};</script>
<style lang="scss" scoped>
.map-home {
  width: 100vw;
  height: 100vh;
}
</style>
Copy the code

There are four main classes in Openlayers:

  • Map: Map container, using target to specify the id of the container to draw the Map, such as Map in code;
  • A map has one or more layers, which can be understood as the concept of layers in PS drawing. The whole map is stacked one by one.
  • View: visual area, this class is mainly to control the interaction between the map and people, such as zoom, adjust the resolution, the rotation of the map and other controls. At the same time, projection can be set, the default is spherical Mercator, olProj. FromLonLat method in the code is also to convert latitude and longitude into corresponding coordinates, this part is not extended, students who need to learn GIS theory by themselves.
  • Source: data source, namely the data component of Layers. In the code above, TileLayer is drawn by using slice data in THE XYZ format of Amap.

The map display is now visible when running the project.

3. Mark drawing

The most common requirement in maps is to make point marks. Similarly, we just need to add a Layer of point marks on top of the previous map Layer, using a VectorLayer, VectorSource, VectorLayer and a vector data

import { Vector as VectorLayer} from 'ol/layer';
import { Vector as VectorSource} from 'ol/source';
Copy the code

We simply add a point to openMap’s Layers array.

// import
import { Map, View, Feature } from "ol";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { XYZ, Vector as VectorSource } from "ol/source";
import * as olProj from "ol/proj";
import { Point } from "ol/geom";
import { Style, Fill, Stroke, Circle as sCircle } from "ol/style";

// methods add setMarker
mounted() {
  this.initMap();
  this.setMarker();
},

// setMarker
setMarker() {
  let _style = new Style({
    image: new sCircle({
      radius: 10.stroke: new Stroke({
        color: "#fff",}).fill: new Fill({
        color: "#3399CC",})})});let _feature = new Feature({
    geometry: new Point(olProj.fromLonLat([108.945951.34.465262]}))), _feature.setStyle(_style);let _marker = new VectorLayer({
    source: new VectorSource({
      features: [_feature],
    }),
  });
  this.openMap.addLayer(_marker);
},
Copy the code

Successfully added a point to the map.

Several new classes are imported in the above code: Feature, Point, Style, etc., which are mainly vector objects with geometric geographical elements and specific styles. Then, setStyle is used to assign styles to Feature, and a coordinate Point is mainly drawn on the map.

4. Click the popover

Next, we need to add click events to the coordinate points in section 3 and display a popup box on the map to show some information about the points.

First add the click event, using singleclick

singleclick() {
  this.openMap.on("singleclick".(e) = > {
    // Determine whether to click on the dot
    let feature = this.openMap.forEachFeatureAtPixel(
      e.pixel,
      (feature) = > feature
    );
    console.log(feature);
  });
},
Copy the code

When we do not click on the point, undefined will be printed, and the corresponding feature information will be printed when we click on the point

Here we also add an event called PointerMove that changes the style of the cursor when the mouse moves over the point.

pointermove() {
  this.openMap.on("pointermove".(e) = > {
    if (this.openMap.hasFeatureAtPixel(e.pixel)) {
      this.openMap.getViewport().style.cursor = "pointer";
    } else {
      this.openMap.getViewport().style.cursor = "inherit"; }}); },Copy the code

Next to the click event above, when we click we want to be able to display the popover of that point above the vue first add a popover component, we need to introduce a new class Overlay

import { Overlay } from "ol";
Copy the code
// template<! - play box - ><div ref="popup" class="popup" v-show="shopPopup">
  <div class="info">
    <ul>
      <li>Message 1: XXX</li>
      <li>Message 2: XXX</li>
      <li>Message 3: XXX</li>
    </ul>
  </div>
</div>

// script
addOverlay() {
  / / create Overlay
  let elPopup = this.$refs.popup;
  this.popup = new Overlay({
    element: elPopup,
    positioning: "bottom-center".stopEvent: false.offset: [0, -20]});this.openMap.addOverlay(this.popup);
},

// style
.popup {
  width: 200px;
  background-color: white;
  padding: 18px;
  border-radius: 10px;
  box-shadow: 0 0 15px rgb(177.177.177);
  .info {
    font-size: 14px;
    text-align: left;
    ul {
      padding-left: 0; }}}Copy the code

Use OL’s addOverlay method to add a pop-up layer to the Map Overlay and then modify the previous click event function

singleclick() {
  / / click
  this.openMap.on("singleclick".(e) = > {
    // Determine whether to click on the dot
    let feature = this.openMap.forEachFeatureAtPixel(
      e.pixel,
      (feature) = > feature
    );
    console.log(feature);
    if (feature) {
      this.shopPopup = true;
      // Set the popover position
      let coordinates = feature.getGeometry().getCoordinates();
      this.popup.setPosition(coordinates);
    } else {
      this.shopPopup = false; }}); },Copy the code

You can see the code that sets the popover position

// Set the popover position
let coordinates = feature.getGeometry().getCoordinates();
this.popup.setPosition(coordinates);
Copy the code

Gets the coordinates of the current click point and sets it to the popover, which has an offset of -30 on the Y-axis to avoid overwriting the drop mark. At this point, we click the popover to complete the implementation.

Finally, attach the complete code, mainly changes to home.vue

<template>
  <div class="home">
    <div id="map" class="map-home"></div>
    <! - play box - >
    <div ref="popup" class="popup" v-show="shopPopup">
      <div class="info">
        <ul>
          <li>Message 1: XXX</li>
          <li>Message 2: XXX</li>
          <li>Message 3: XXX</li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
import { Map, View, Feature, Overlay } from "ol";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { XYZ, Vector as VectorSource } from "ol/source";
import * as olProj from "ol/proj";
import { Point } from "ol/geom";
import { Style, Fill, Stroke, Circle as sCircle } from "ol/style";

export default {
  name: "Home".components: {},
  data() {
    return {
      openMap: null.popup: null.shopPopup: false}; },mounted() {
    this.initMap();
  },
  methods: {
    initMap() {
      this.openMap = new Map({
        target: "map".layers: [
          new TileLayer({
            source: new XYZ({
              url: "https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}",})})],view: new View({
          center: olProj.fromLonLat([108.945951.34.465262]),
          zoom: 1,}).controls: [],});this.setMarker();
      this.addOverlay();
      this.singleclick();
      this.pointermove();
    },
    setMarker() {
      let _style = new Style({
        image: new sCircle({
          radius: 10.stroke: new Stroke({
            color: "#fff",}).fill: new Fill({
            color: "#3399CC",})})});let _feature = new Feature({
        geometry: new Point(olProj.fromLonLat([108.945951.34.465262]}))), _feature.setStyle(_style);let _marker = new VectorLayer({
        source: new VectorSource({
          features: [_feature],
        }),
      });
      this.openMap.addLayer(_marker);
    },
    addOverlay() {
      / / create Overlay
      let elPopup = this.$refs.popup;
      this.popup = new Overlay({
        element: elPopup,
        positioning: "bottom-center".stopEvent: false.offset: [0, -20]});this.openMap.addOverlay(this.popup);
    },
    singleclick() {
      / / click
      this.openMap.on("singleclick".(e) = > {
        // Determine whether to click on the dot
        let feature = this.openMap.forEachFeatureAtPixel(
          e.pixel,
          (feature) = > feature
        );
        console.log(feature);
        if (feature) {
          this.shopPopup = true;
          // Set the popover position
          let coordinates = feature.getGeometry().getCoordinates();
          this.popup.setPosition(coordinates);
        } else {
          this.shopPopup = false; }}); },pointermove() {
      this.openMap.on("pointermove".(e) = > {
        if (this.openMap.hasFeatureAtPixel(e.pixel)) {
          this.openMap.getViewport().style.cursor = "pointer";
        } else {
          this.openMap.getViewport().style.cursor = "inherit"; }}); ,}}};</script>
<style lang="scss" scoped>
.map-home {
  width: 100vw;
  height: 100vh;
}
.popup {
  width: 200px;
  background-color: white;
  padding: 18px;
  border-radius: 10px;
  box-shadow: 0 0 15px rgb(177.177.177);
  .info {
    font-size: 14px;
    text-align: left;
    ul {
      padding-left: 0; }}}</style>

Copy the code

Three, the last

Gitee address: gitee.com/shtao_056/v…

Next article address:

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

This article is mainly the introduction of OpenLayers tutorial, complete the OpenLayers map import rendering, and coordinate point click events.

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.