openlayers introductory tutorial

1. Openlayers Basics

If you don’t understand or are familiar with openlayers, I suggest you read these two articles first. They are written in great detail and will help you get started:
https://www.yuque.com/qstar-vrosu/fe /auhoye
https://blog.csdn.net/tk08888/article/details/127053451
Here I will make some brief descriptions:
openlayers is mainly developed in an object-oriented way, mainly because there are many configuration items, similar to echarts smell. However, in view of the fact that the openlayers documentation is very unfriendly, and it is an English document, here we will focus on a few more important map components.

1. Map (Map), the corresponding class is ol.Map:

Function: Create the entrance of the map. If you need to create a map, then you need this class. Similar to ps software, you need p pictures, first you need a ps software.

2. View (View), the corresponding class is ol.View

Function: control the center position, range, level, etc. of the map display

3. Layer (Layer, need to focus on mastering)

Function: It is a layer. If you initialize a map, then if you want to add something to this map, you can add it by adding a layer. (Similar to layer overlay in ps, the last added layer will overwrite the previously added layer.)

a. How to add layers to the map? :

  • Add the specified layer: map.addLayer(layer);
  • Remove the specified layer: map.removeLayer(layer);

b. How to define layers?:

(1) ol.layer.Tile()
tiles the layer.
For layer sources that provide pre-rendered, tiled images of grids, these grids are organized by resolution-specific zoom levels.
(2) ol.layer.Image()
image layer.
A server-rendered image, available in arbitrary ranges and resolutions.
(3) ol.layer.Vector() is very commonly used
for vector layers.
(4) ol.layer.VectorTile ()
vector tile layer.
Layers are used for client-side rendering of vector tile data.

c. How to add elements on the layer? (important):

1) Feature (that is, the geometric object on the map)
defines the vector element: new ol.Feature()
vector element style:
set the style: new ol.style.Style(), you can also use feature.setStyle(style), if it is not defined , you can use the style of its container layer;
get the style: feature.getStyle()
2) Style (this is mainly for the above feature service, setting styles and the like)
the container of the vector feature presentation style.
How to define: newol.style.Style()

d. What are Layer and Feature? and the difference between them

Reference: https://www.gserdqy.com/secdev/openlayers/22042/

4. Interaction

It is used less, but without it, we have no way to directly use the mouse to control the map to zoom in, zoom out, and move. openlayers is integrated by default, but if you want to open up certain capabilities, you need to use this, such as user drawing points, Lines, surfaces, etc.
Add interactive actions using: map.addInteraction(interaction);

5. Control (Control)

It is rarely used, mainly to provide some functions such as scale, eagle eye, and obtaining the latitude and longitude of the mouse. If necessary, just add it directly.

6. Overlay Overlay (important)

Function: Overlay briefly describes the meaning of overlay. As the name suggests, it is to appear on the map in another form. Here, many students will confuse them with layers. The main purpose is to place some elements related to the location of the map. Common There are three types of map overlays, such as: popup window, label annotation information, text text information, etc., and these overlays are equivalent to elements in html, and are bound to html elements through the overlay attribute element At the same time, coordinate parameters are set to reach the position where the html element is placed on the map. When panning and zooming, the html element will also move with the movement of the map.

<div id="map">
  <div id="popup">

  </div>
  </div>
let popup = new ol.Overlay({
    
    
  element:document.getElementById('popup'),
  ...
});
popup.setPosition(coordinate);
map.addOverlay(popup);

7. Projections

The view projection system is required for all coordinates and extents (default is EPAG:3857).
Mainly used to transform the projection system, use ol.proj.transform() and ol.proj.transformExtendt to convert

a. Note: About the map coordinate system:

ol uses the 3857 coordinate system by default (because the data is stored in EPSG:4326 and displayed in EPSG:3857 ), then when setting the center point, you need to convert the EPSG:4326 geographic coordinates to EPSG:3857 Mercator Projected coordinates
But if you are using Baidu map, take a point on Baidu map, such as the point of Tiananmen Square in Beijing: [116.403, 39.924]. You need to convert the point of the bd-09 coordinate system to the point of the wgs84 coordinate system first, and then take the converted point to convert it into PSG:3857 Mercator projection coordinate
EPSG:4326 (WGS84).
As mentioned earlier, WGS84 is currently The most popular geographic coordinate system. Internationally, each coordinate system is assigned an EPSG code, and EPSG:4326 is the code of WGS84. GPS is based on WGS84, so usually the coordinate data we get is WGS84. Generally, when we store data, we still store it according to WGS84.
Summary: EPSG:4326 = point in the WGS84 coordinate system, but it needs to be converted to Mercator projection coordinates when displayed. Other maps need to be converted to the wgs84 coordinate system first, and then converted

Two: openlayers actual combat

1.openlayers initializes Baidu map:

image.png

mounted() {
  // 生成地图
  this.initMap()
},
  initMap() {
    var projection = ol.proj.get('EPSG:3857')
    //分辨率
    var resolutions = []
    for (var i = 0; i < 19; i++) {
      resolutions[i] = Math.pow(2, 18 - i)
    }
    var tilegrid = new ol.tilegrid.TileGrid({
      origin: [0, 0],
      resolutions: resolutions,
    })
    //拼接百度地图出图地址
    var baidu_source = new ol.source.TileImage({
      //设置坐标参考系
      projection: projection,
      //设置分辨率
      tileGrid: tilegrid,
      //出图基地址
      tileUrlFunction: function (tileCoord, pixelRatio, proj) {
        if (!tileCoord) {
          return ''
        }
        var z = tileCoord[0]
        var x = tileCoord[1]
        var y = tileCoord[2]

        if (x < 0) {
          x = 'M' + -x
        }
        if (y < 0) {
          y = 'M' + -y
        }
        return 'http://online3.map.bdimg.com/onlinelabel/?qt=tile&x=' + x + '&y=' + y + '&z=' + z + '&styles=pl&udt=20151021&scaler=1&p=1'
      },
    })
    //百度地图
    var baidu_layer = new ol.layer.Tile({
      source: baidu_source,
    })
    //地图容器
    this.map = new ol.Map({
      target: 'map',
      layers: [baidu_layer],
      view: new ol.View({
        center: ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857'),
        zoom: 12,
        minZoom: 3,
      }),
    })
  }

Here is only the process of initializing the Baidu map. Other maps are not bad. You can refer to:
https://blog.csdn.net/liu2004051957/article/details/127929790?spm=1001.2014.3001.5506
Refer to previous articles for offline maps:
https://blog.csdn.net/weixin_43239880/article/details/129247279?spm=1001.2014.3001.5502

2.openlayers add points:

image.png

addPoint() {
      //创建一个点
      var point = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857')),
      })
      //设置点1的样式信息
      point.setStyle(
        new ol.style.Style({
          //填充色
          fill: new ol.style.Fill({
            color: 'rgba(255, 255, 255, 0.2)',
          }),
          //边线颜色
          stroke: new ol.style.Stroke({
            color: '#ffcc33',
            width: 2,
          }),
          //形状
          image: new ol.style.Circle({
            radius: 17,
            fill: new ol.style.Fill({
              color: '#ffcc33',
            }),
          }),
        })
      )

      //实例化一个矢量图层Vector作为绘制层
      var source = new ol.source.Vector({
        features: [point],
      })
      //创建一个图层
      var vector = new ol.layer.Vector({
        source: source,
      })
      //将绘制层添加到地图容器中
      this.map.addLayer(vector)
    },

3.openlayers add line:

image.png

 addLine() {
      //创建一个线
      var Line = new ol.Feature({
        geometry: new ol.geom.LineString([ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857'), ol.proj.transform([116.503, 39.994], 'EPSG:4326', 'EPSG:3857')]),
      })

      //设置线的样式
      Line.setStyle(
        new ol.style.Style({
          //填充色
          fill: new ol.style.Fill({
            color: 'rgba(255, 255, 255, 0.2)',
          }),
          //边线颜色
          stroke: new ol.style.Stroke({
            color: '#ffcc33',
            width: 5,
          }),
          //形状
          image: new ol.style.Circle({
            radius: 7,
            fill: new ol.style.Fill({
              color: '#ffcc33',
            }),
          }),
        })
      )

      //实例化一个矢量图层Vector作为绘制层
      var source = new ol.source.Vector({
        features: [Line],
      })
      //创建一个图层
      var vector = new ol.layer.Vector({
        source: source,
      })
      //将绘制层添加到地图容器中
      this.map.addLayer(vector)
    },

4.openlayers add faces

image.png

addArea() {
      //根据范围获取多边形
      var Rectangle = new ol.Feature({
        geometry: new ol.geom.Polygon.fromExtent([16208725.0, 3035304.0, 9841418.0, 5068487.0]),
      })

      Rectangle.setStyle(
        new ol.style.Style({
          fill: new ol.style.Fill({
            color: 'rgba(33,33,33,0.5)',
          }),
          stroke: new ol.style.Stroke({
            color: '#ffcc33',
            width: 4,
          }),
          image: new ol.style.Circle({
            radius: 7,
            fill: new ol.style.Fill({
              color: '#ffcc33',
            }),
          }),
        })
      )

      //实例化一个矢量图层Vector作为绘制层
      var source = new ol.source.Vector({
        features: [Rectangle],
      })
      //创建一个图层
      var vector = new ol.layer.Vector({
        source: source,
      })
      //将绘制层添加到地图容器中
      this.map.addLayer(vector)
    },

5. openlayers positioned to a certain point

Animation.gif

toPoint() {
      //这里给动画设置一个初始值
      this.map.getView().animate({
        //将地理坐标转为投影坐标
        center: ol.proj.transform([117.403, 42.924], 'EPSG:4326', 'EPSG:3857'),
        duration: 1000,
        zoom: 12,
      })
    },

6. openlayers add image annotation

image.png

addPic() {
      var createLabelStyle = function (feature) {
        return new ol.style.Style({
          /**{olx.style.IconOptions}类型*/
          image: new ol.style.Icon({
            anchor: [0.5, 60],
            anchorOrigin: 'top-right',
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            offsetOrigin: 'top-right',
            // offset:[0,10],
            //图标缩放比例
            // scale:0.5,
            //透明度
            opacity: 0.75,
            //图标的url
            src: require('@/assets/logo.png'),
          }),
        })
      }
      //实例化Vector要素,通过矢量图层添加到地图容器中
      var iconFeature = new ol.Feature({
        // geometry: new ol.geom.Point(ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857')),
        geometry: new ol.geom.Point(ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857')),
      })

      iconFeature.setStyle(createLabelStyle(iconFeature))
      //矢量标注的数据源
      var vectorSource = new ol.source.Vector({
        features: [iconFeature],
      })
      //矢量标注图层
      var vectorLayer = new ol.layer.Vector({
        source: vectorSource,
      })
      this.map.addLayer(vectorLayer)
    },

7.openlayers add text annotation

image.png

 addText() {
      /**
       * 创建矢量标注样式函数,设置image为图标ol.style.Icon
       * @param {ol.Feature} feature 要素
       */
      var createLabelStyle = function (feature) {
        return new ol.style.Style({
          text: new ol.style.Text({
            //位置
            textAlign: 'center',
            //基准线
            textBaseline: 'middle',
            //文字样式
            font: 'normal 14px 微软雅黑',
            //文本内容
            text: feature.get('name'),
            //文本填充样式(即文字颜色)
            fill: new ol.style.Fill({ color: '#aa3300' }),
            stroke: new ol.style.Stroke({ color: '#ffcc33', width: 2 }),
          }),
        })
      }

      //实例化Vector要素,通过矢量图层添加到地图容器中
      var iconFeature = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857')),
        //名称属性
        name: '北京市',
        //大概人口数(万)
        population: 2115,
      })
      iconFeature.setStyle(createLabelStyle(iconFeature))
      //矢量标注的数据源
      var vectorSource = new ol.source.Vector({
        features: [iconFeature],
      })
      //矢量标注图层
      var vectorLayer = new ol.layer.Vector({
        source: vectorSource,
      })
      this.map.addLayer(vectorLayer)
    },

8. openlayers adds graphic and text annotations

image.png

addPicAndText() {
      /**
       * 创建矢量标注样式函数,设置image为图标ol.style.Icon
       * @param {ol.Feature} feature 要素
       */
      var createLabelStyle = function (feature) {
        return new ol.style.Style({
          image: new ol.style.Icon(
            /** @type {olx.style.IconOptions} */
            ({
              anchor: [0.5, 60],
              anchorOrigin: 'top-right',
              anchorXUnits: 'fraction',
              anchorYUnits: 'pixels',
              offsetOrigin: 'top-right',
              // offset:[0,10],
              //图标缩放比例
              // scale:0.5,
              //透明度
              opacity: 0.75,
              //图标的url
              src: require('@/assets/logo.png'),
            })
          ),
          text: new ol.style.Text({
            //位置
            textAlign: 'center',
            //基准线
            textBaseline: 'middle',
            //文字样式
            font: 'normal 14px 微软雅黑',
            //文本内容
            text: feature.get('name'),
            //文本填充样式(即文字颜色)
            fill: new ol.style.Fill({ color: '#aa3300' }),
            stroke: new ol.style.Stroke({ color: '#ffcc33', width: 2 }),
          }),
        })
      }

      //实例化Vector要素,通过矢量图层添加到地图容器中
      var iconFeature = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857')),
        //名称属性
        name: '北京市',
        //大概人口数(万)
        population: 2115,
      })
      iconFeature.setStyle(createLabelStyle(iconFeature))
      //矢量标注的数据源
      var vectorSource = new ol.source.Vector({
        features: [iconFeature],
      })
      //矢量标注图层
      var vectorLayer = new ol.layer.Vector({
        source: vectorSource,
      })
      this.map.addLayer(vectorLayer)
    },

9.openlayers add popup

Animation.gif

<div ref="popup_content" class="popup_content" v-show="popupContentShow">
      <div class="fater">
        <div class="son">这里是注解文字</div>
      </div>
    </div>
methods:{
  addPic() {
      var createLabelStyle = function (feature) {
        return new ol.style.Style({
          /**{olx.style.IconOptions}类型*/
          image: new ol.style.Icon({
            anchor: [0.5, 60],
            anchorOrigin: 'top-right',
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            offsetOrigin: 'top-right',
            // offset:[0,10],
            //图标缩放比例
            // scale:0.5,
            //透明度
            opacity: 0.75,
            //图标的url
            src: require('@/assets/logo.png'),
          }),
        })
      }
      //实例化Vector要素,通过矢量图层添加到地图容器中
      var iconFeature = new ol.Feature({
        // geometry: new ol.geom.Point(ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857')),
        geometry: new ol.geom.Point(ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857')),
      })

      iconFeature.setStyle(createLabelStyle(iconFeature))
      //矢量标注的数据源
      var vectorSource = new ol.source.Vector({
        features: [iconFeature],
      })
      //矢量标注图层
      var vectorLayer = new ol.layer.Vector({
        source: vectorSource,
      })
      this.map.addLayer(vectorLayer)
    },
  addPopup() {
      this.addPic()
      /**
       * 为map添加鼠标移动事件监听,当指向标注时改变鼠标光标状态
       */
      this.map.on('pointermove', e => {
        var pixel = this.map.getEventPixel(e.originalEvent)
        var hit = this.map.hasFeatureAtPixel(pixel)
        this.map.getTargetElement().style.cursor = hit ? 'pointer' : ''
      })
      /**
       * 为map添加点击事件监听,渲染弹出popup
       */
      this.map.on('click', evt => {
        //判断当前单击处是否有要素,捕获到要素时弹出popup
        var feature = this.map.forEachFeatureAtPixel(evt.pixel, (feature, layer) => {
          return feature
        })
        if (feature) {
          let popup = new ol.Overlay(
            /** @type {olx.OverlayOptions} */
            ({
              //要转换成overlay的HTML元素
              element: this.$refs.popup_content,
              //当前窗口可见
              autoPan: true,
              //Popup放置的位置
              positioning: 'center-center',
              //是否应该停止事件传播到地图窗口
              stopEvent: false,
              autoPanAnimation: {
                //当Popup超出地图边界时,为了Popup全部可见,地图移动的速度
                duration: 250,
              },
            })
          )
          this.popupContentShow = true
          popup.setPosition(evt.coordinate)
          this.map.addOverlay(popup)
        }
      })
    },
}

11. openlayers track playback

Animation.gif

addPointAndView() {
      var Coordinates = new Array()
      Coordinates.push(
        ol.proj.transform([117.403, 42.924], 'EPSG:4326', 'EPSG:3857'),
        ol.proj.transform([117.403, 41.924], 'EPSG:4326', 'EPSG:3857'),
        ol.proj.transform([117.403, 40.924], 'EPSG:4326', 'EPSG:3857'),
        ol.proj.transform([117.403, 38.924], 'EPSG:4326', 'EPSG:3857'),
        ol.proj.transform([117.403, 37.924], 'EPSG:4326', 'EPSG:3857'),
        ol.proj.transform([117.403, 32.924], 'EPSG:4326', 'EPSG:3857'),
        ol.proj.transform([127.403, 42.924], 'EPSG:4326', 'EPSG:3857'),
        ol.proj.transform([127.403, 52.924], 'EPSG:4326', 'EPSG:3857'),
        ol.proj.transform([137.403, 49.924], 'EPSG:4326', 'EPSG:3857')
      )
      let passCoordinate = []
      //将离散点构建成一条折线
      var route = new ol.geom.LineString(Coordinates)
      // -----------主要是把其中的经过的点都拿出来-----------------------------
      let trackLineLen = route.getLength()
      let pointCount = trackLineLen / (this.map.getView().getResolution() * 15)
      for (let i = 1; i < pointCount; i++) {
        passCoordinate.push(route.getCoordinateAt(i / pointCount))
      }
      passCoordinate.unshift(Coordinates[0])
      passCoordinate.push(Coordinates[Coordinates.length - 1])
      //获取直线的坐标
      // var routeCoords = route.getCoordinates()
      var routeCoords = passCoordinate
      // -----------主要是把其中的经过的点都拿出来-----------------------------
      var routeLength = routeCoords.length

      var routeFeature = new ol.Feature({
        type: 'route',
        geometry: route,
      })
      var geoMarker = new ol.Feature({
        type: 'geoMarker',
        geometry: new ol.geom.Point(routeCoords[0]),
      })
      var startMarker = new ol.Feature({
        type: 'icon',
        geometry: new ol.geom.Point(routeCoords[0]),
      })
      var endMarker = new ol.Feature({
        type: 'icon',
        geometry: new ol.geom.Point(routeCoords[routeLength - 1]),
      })

      var styles = {
        route: new ol.style.Style({
          stroke: new ol.style.Stroke({
            width: 6,
            color: [237, 212, 0, 0.8],
          }),
        }),
        icon: new ol.style.Style({
          image: new ol.style.Icon({
            anchor: [0.5, 1],
            src: require('@/assets/[email protected]'),
          }),
        }),
        geoMarker: new ol.style.Style({
          image: new ol.style.Circle({
            radius: 7,
            // snapToPixel: false,
            fill: new ol.style.Fill({ color: 'black' }),
            stroke: new ol.style.Stroke({
              color: 'white',
              width: 2,
            }),
          }),
        }),
      }

      var animating = false
      var speed, now
      var vectorLayer = new ol.layer.Vector({
        source: new ol.source.Vector({
          features: [routeFeature, geoMarker, startMarker, endMarker],
        }),
        style: function (feature) {
          //如果动画是激活的就隐藏geoMarker
          if (animating && feature.get('type') === 'geoMarker') {
            return null
          }
          return styles[feature.get('type')]
        },
      })
      this.map.addLayer(vectorLayer)
      var moveFeature = event => {
        var vectorContext = event.vectorContext
        var frameState = event.frameState
        if (animating) {
          var elapsedTime = frameState.time - now
          //通过增加速度,来获得lineString坐标
          var index = Math.round((speed * elapsedTime) / 1000)

          if (index >= routeLength) {
            stopAnimation(true)
            return
          }

          var currentPoint = new ol.geom.Point(routeCoords[index])
          var feature = new ol.Feature(currentPoint)
          vectorContext.drawFeature(feature, styles.geoMarker)
        }
        //继续动画效果
        this.map.render()
      }
      const startAnimation = () => {
        if (animating) {
          stopAnimation(false)
        } else {
          animating = true
          now = new Date().getTime()
          speed = 400
          // startButton.textContent = '结束运动'
          //隐藏geoMarker
          geoMarker.setStyle(null)
          //设置显示范围
          this.map.getView().setCenter(ol.proj.transform([116.403, 39.924], 'EPSG:4326', 'EPSG:3857'))
          this.map.on('postcompose', moveFeature)
          this.map.render()
        }
      }
      const stopAnimation = ended => {
        animating = false
        // startButton.textContent = '开始运动'

        //如果动画取消就开始动画
        var coord = ended ? routeCoords[routeLength - 1] : routeCoords[0]
        /** @type {ol.geom.Point} */
        geoMarker.getGeometry().setCoordinates(coord)
        //移除监听
        this.map.un('postcompose', moveFeature)
      }
      setTimeout(() => {
        startAnimation()
      }, 2000)
    },

12. openlayers add heat map

Animation.gif

 addHeatmap() {
      this.moveToPosition([116.403, 39.924], 4)
      //创建一个Heatmap图层
      var vector = new ol.layer.Heatmap({
        source: new ol.source.Vector({
          features: new ol.format.GeoJSON().readFeatures(heatData, {
            dataProjection: 'EPSG:4326',
            featureProjection: 'EPSG:3857',
          }),
        }),
        //热点半径
        radius: parseInt(15, 10),
        //模糊尺寸
        blur: parseInt(25, 10),
      })
      this.map.addLayer(vector)
      // 将已添加的图层装起来
      this.layerList.push(vector)
    },

13.openlayers add point aggregation map

Animation.gif

 addManyPoints() {
      //此示例创建10000个要素
      var count = 1000
      var features = new Array(count)
      for (var i = 0; i < count; ++i) {
        // var coordinates = [2 * e * Math.random() - e, 2 * e * Math.random() - e]
        var coordinates = ol.proj.transform([Math.random() * 100 + 100, Math.random() * 10 + 35], 'EPSG:4326', 'EPSG:3857')
        console.log(coordinates)
        features[i] = new ol.Feature(new ol.geom.Point(coordinates))
      }
      //矢量要素数据源
      var source = new ol.source.Vector({
        features: features,
      })
      //聚合标注数据源
      var clusterSource = new ol.source.Cluster({
        distance: 40,
        source: source,
      })
      //加载聚合标注的矢量图层
      var styleCache = {}
      var clusters = new ol.layer.Vector({
        source: clusterSource,
        style: function (feature, resolution) {
          var size = feature.get('features').length
          var style = styleCache[size]
          if (!style) {
            style = [
              new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 20,
                  stroke: new ol.style.Stroke({
                    color: '#fff',
                  }),
                  fill: new ol.style.Fill({
                    color: '#3399CC',
                  }),
                }),
                text: new ol.style.Text({
                  text: size.toString(),
                  fill: new ol.style.Fill({
                    color: '#fff',
                  }),
                }),
              }),
            ]
            styleCache[size] = style
          }
          return style
        },
      })
      this.map.addLayer(clusters)
      // 下面的代码是让鼠标变成小手,并且有点击事件
      this.map.on('pointermove', e => {
        var pixel = this.map.getEventPixel(e.originalEvent)
        var hit = this.map.hasFeatureAtPixel(pixel)
        this.map.getTargetElement().style.cursor = hit ? 'pointer' : ''
      })
      /**
       * 为map添加点击事件监听,渲染弹出popup
       */
      this.map.on('click', evt => {
        //判断当前单击处是否有要素,捕获到要素时弹出popup
        var feature = this.map.forEachFeatureAtPixel(evt.pixel, (feature, layer) => {
          return feature
        })
        if (feature) {
          let popup = new ol.Overlay(
            /** @type {olx.OverlayOptions} */
            ({
              //要转换成overlay的HTML元素
              element: this.$refs.popup_content,
              //当前窗口可见
              autoPan: true,
              //Popup放置的位置
              positioning: 'bottom-center',
              //是否应该停止事件传播到地图窗口
              stopEvent: false,
              autoPanAnimation: {
                //当Popup超出地图边界时,为了Popup全部可见,地图移动的速度
                duration: 250,
              },
            })
          )
          this.popupContentShow = true
          popup.setPosition(evt.coordinate)
          this.map.addOverlay(popup)
        }
      })
    },

14. Openlayers users draw various graphics on the map

Animation.gif

mounted() {
    // 生成地图
    this.initMap()
    // 生成一个绘制层,用于地图绘制
    this.initDraw()
  },
initDraw() {
  //实例化一个矢量图层Vector作为绘制层
  this.source = new ol.source.Vector({ wrapX: false })
  this.vector = new ol.layer.Vector({
    source: this.source,
    style: new ol.style.Style({
      fill: new ol.style.Fill({
        color: 'rgba(255, 255, 255, 0.2)',
      }),
      stroke: new ol.style.Stroke({
        color: '#ffcc33',
        width: 10,
      }),
      image: new ol.style.Circle({
        radius: 7,
        fill: new ol.style.Fill({
          color: '#ffcc33',
        }),
      }),
    }),
  })
  //将绘制层添加到地图容器中
  this.map.addLayer(this.vector)
},
  //根据绘制类型进行交互绘制图形处理
addInteraction() {
    let type
    //绘制对象
    if (this.selectValue !== 'None') {
      type = this.selectValue
      if (this.source == null) {
        this.source = new ol.source.Vector({ wrapX: false })
        //添加绘制层数据源
        this.vector.setSource(this.source)
      }
      var geometryFunction, maxPoints
      if (this.selectValue === 'Square') {
        type = 'Circle'
        //正方形图形(圆)
        geometryFunction = ol.interaction.Draw.createRegularPolygon(4)
      } else if (this.selectValue === 'Box') {
        type = 'LineString'
        maxPoints = 2
        geometryFunction = function (coordinates, geometry) {
          if (!geometry) {
            //多边形
            geometry = new ol.geom.Polygon(null)
          }
          var start = coordinates[0]
          var end = coordinates[1]
          geometry.setCoordinates([[start, [start[0], end[1]], end, [end[0], start[1]], start]])
          return geometry
        }
      }
      //实例化交互绘制类对象并添加到地图容器中
      this.draw = new ol.interaction.Draw({
        //绘制层数据源
        source: this.source,
        /** @type {ol.geom.GeometryType}几何图形类型 */
        type: type,
        //几何信息变更时调用函数
        geometryFunction: geometryFunction,
        //最大点数
        maxPoints: maxPoints,
      })
      this.map.addInteraction(this.draw)
    } else {
      // console.log(111)
      this.source = null
      //清空绘制图形
      this.vector.setSource(this.source)
    }
  },
selectChange() {
    //移除绘制图形
    this.map.removeInteraction(this.draw)
    //添加交互绘制功能控件
    this.addInteraction()
  },

Practical reference website:

http://develop.smaryun.com:81/API/JS/OL5InterfaceDemo/index.htm

demo address:

demo address: https://github.com/rui-rui-an/openlayersMap

Guess you like

Origin blog.csdn.net/weixin_43239880/article/details/131073418