一、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值
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()
}
},