一、Overlay

1、简介

主要是放置一些和地图位置相关的元素,如:infowindow、点标记、图片等,而这些覆盖物都是和html中的element等价的,通过overlay的属性element和html元素绑定同时设定坐标参数——达到将html元素放到地图上的位置,在平移缩放的时候html元素也会随着地图的移动而移动。

2、属性

letoverLay = new ol.Overlay(options),此处的 options 便是参数键值对构成的对象字面量。可配置的键值对,定义如下:

• id,为对应的 overlay 设置一个 id,便于使用 ol.Map 的 getOverlayById 方法取得相应的 overlay;
• element,overlay 包含的 DOM element;
• offset,偏移量,像素为单位,overlay 相对于放置位置(position)的偏移量,默认值是 [0, 0],正值分别向右和向下偏移;
• position,在地图所在的坐标系框架下,overlay 放置的位置;
• positioning,overlay 对于 position 的相对位置,可能的值包括 bottom-left、bottom-center、bottom-right 、center-left、center-center、center-right、top-left、top-center、top-right,默认是 top-left,也就是 element 左上角与 position 重合;
• stopEvent,地图的事件传播是否停止,默认是 true,即阻止传播,可能不太好理解,举个例子,当鼠标滚轮在地图上滚动时,会触发地图缩放事件,如果在 overlay 之上滚动滚轮,并不会触发缩放事件,如果想鼠标在 overlay 之上也支持缩放,那么将该属性设置为 false 即可;
• insertFirst,overlay 是否应该先添加到其所在的容器(container),当 stopEvent 设置为 true 时,overlay 和 openlayers 的控件(controls)是放于一个容器的,此时将 insertFirst 设置为 true ,overlay 会首先添加到容器,这样,overlay 默认在控件的下一层(CSS z-index),所以,当 stopEvent 和insertFirst 都采用默认值时,overlay 默认在 控件的下一层
• autoPan,当触发 overlay setPosition 方法时触发,当 overlay 超出地图边界时,地图自动移动,以保证 overlay 全部可见;
• autoPanAnimation,设置 autoPan 的效果动画,参数类型是 olx.animation.panOptions
• autoPanMargin,地图自动平移时,地图边缘与 overlay 的留白(空隙),单位是像素,默认是 20像素

3、overlay常用方法

• getElement,取得包含 overlay 的 DOM 元素;
• getId,取得 overlay 的 id;
• getMap,获取与 overlay 关联的 map对象;
• getOffset,获取 offset 属性;
• getPosition,获取 position 属性;
• getPositioning,获取 positioning 属性;
• setElement;设置 overlay 的 element;
• setMap,设置与 overlay 的 map 对象;
• setOffset,设置 offset;
• setPosition,设置 position 属性;
• setPositioning,设置 positioning 属性。

4、问题以及解决方案

一、

问题描述:创建一个overlay以后,该dom默认是 display:none

原因: openlays6的版本的 id写成默认值时,会出现这个问题

解决方案:将id设置成变量

二、

问题描述:创建多个overlay以后,修改展示顺序,比如:在一个图标上展示一个弹框

解决方案:创建Overlay事,属性保持一致,防止openlayers内部将这些overlay按属性分组放,这样所有的overlay在同一个dom里边。根据图标还是文字框设置不通的classname,然后设置z-index值

overlay2能否清理 overlays_缩放

let popup = new Overlay({
        id: id,
        element: el,
        positioning: 'top-center',
        // stopEvent: true,
        // insertFirst: true,
        autoPan: autoPan || false,
        offset: [textX || 0, textY || 0],
        className: className ? `ol-overlay-container ol-selectable ${className}` : 'ol-overlay-container ol-selectable'
      })

三、

问题描述:封装overlay模糊查询删除方法时,直接在forEach循环中进行删除,会有删除不尽的问题

解决方案:将模糊查询出来的overlay放在一个数组,再集中删除

5. 方法封装

/**
     * 创建图层的tip框
     * @param {*} tipId overlayId
     * @param {*} eleClassName 创建的元素的class
     * @param {*} text tip框展示的内容
     * @param {*} component 引用的组件
     * @param {*} offset overlay的偏移
     */
    addIconTips({ tipId, eleClassName = 'tips-wrap', text = '', component = '', infoObj = {}, offset = [0, 0], position = undefined }) {
      let el
      if (text) {
        el = document.createElement('div')
        el.style.cssText = `min-width:30px;width:${text.length * 12 + 10}px;`
        el.className = `${eleClassName}`

        let nameEle = document.createElement('div')
        nameEle.className = 'tip-name'
        el.innerText = `${text}`
      }

      if (component) {
        const Marker = Vue.extend(component)
        el = new Marker({
          propsData: {
            item: infoObj
          }
        }).$mount(document.createElement('div')).$el
      }
      let popup = this.CURRENT_MAP.getOverlayById(tipId)
      if (popup) {
        this.CURRENT_MAP.removeOverlay(popup)
      }

      popup = new Overlay({
        id: tipId,
        element: el,
        positioning: 'bottom-center',
        stopEvent: false,
        autoPan: false,
        position,
        offset // 正值分别向右和向下偏移
      })
      this.CURRENT_MAP.addOverlay(popup)
    },
/**
     * 设置overlay显示与隐藏
     * @param {*} title: 根据title模糊查询   overlayId可具体查询  二者选其一
     */
    setOverlayVisible({ title = '', overlayId, state }) {
      if (overlayId) {
        let overlay = this.CURRENT_MAP.getOverlayById(overlayId)
        if (overlay?.get('element')) {
          overlay.get('element').parentElement.style.display = state ? 'flex' : 'none'
        }
        return
      }

      if (title) {
        let overlays = this.CURRENT_MAP.getOverlays()
        overlays.forEach(overlay => {
          const id = overlay?.getId() || ''
          if (id?.includes(title)) {
            if (overlay?.get('element')) {
              overlay.get('element').parentElement.style.display = state ? 'flex' : 'none'
            }
          }
        })
      }
    },
    /**
     * 移除overlay
     * @param {*} title === '' 时,移除全部overlay 根据title模糊查询   overlayId可具体查询  二者选其一
     */
    removeOverLayInMap({ title = '', overlayId }) {
      if (overlayId) {
        let overlay = this.CURRENT_MAP.getOverlayById(overlayId)
        this.CURRENT_MAP.removeOverlay(overlay)
        return
      }
      let overlays = this.CURRENT_MAP.getOverlays()
      if (title) {
        let matches = []
    
        overlays.forEach(overlay => {
          const id = overlay?.getId() || ''
          if (id?.includes(title)) {
            
            // 直接删除会有删不干净的问题,解决办法:先放到一个数组中在进行删除
            //  this.CURRENT_MAP.removeOverlay(overlay)
            matches.push(overlay)
          }
        })
         matches.forEach(m => {
          map.removeOverlay(m)
        })
      } else {
        overlays.clear()
      }
    },