openlayer - 气泡浮动窗口
核心问题
如果你正常尝试使用 overlay 实现浮动窗口,大概率会遇到这个问题:
使用 overlay 的时候,不论怎样调整 html 的 z-index 都不会生效。
这是因为源码中,父级元素已经固定填 0,子元素无法突破父级的元素堆叠层级。
下一行是关键代码,设置 overlay 的时候,需要调整父级元素的 z-index。
element.parentElement.style.zIndex = 1;
样例代码
VUE3 环境,语法差别不大,按照实际情况调整
<template>
<div id="map_container" style="width: 100%; height: 100%">
<div id="map" class="map" style="width: 100%; height: 100%;"></div>
</div>
</template>
<script setup lang="ts">
import Map from 'ol/Map';
import View from 'ol/View';
import Overlay from 'ol/Overlay';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import Style from 'ol/style/Style';
import {onMounted} from "vue";
// 上一次点击的浮动窗口
let pre_overlay = undefined;
/**
* 创建一个用于浮动的窗口
*
* 这里需要复杂设计,每次点击浮动的时候,需要重新渲染内容
*
* @returns 浮动窗口
*/
const createPopover: HTMLElement = () => {
const element = document.createElement('div');
element.classList.add('float-bottom');
element.classList.add('sea-arrow-after-top');
element.innerHTML = '<span>浮动窗口</span>';
return element;
}
const popover = createPopover();
/**
* 创建一个浮动层
*
* @param map -
* @param position -
* @param model -
* @param zIndex -
*/
const createOverlay = (map, position, model, zIndex: number = 1) => {
// create overlay
const element = document.createElement('div');
element.classList.add('sea-float-box');
element.innerHTML = `<button class="el-button">${model}</button>`;
const htmlOverlay = new Overlay({
position: position,
element: element,
positioning: 'top-left'
});
map.addOverlay(htmlOverlay);
// event
element.addEventListener('click', () => {
// 恢复上一次浮动层的 z-index
if (pre_overlay !== undefined) {
pre_overlay.parentElement.style.zIndex = 0;
}
// 记录浮动层,并切换气泡窗口的父级容器
pre_overlay = element;
element.appendChild(popover);
// 重点是这一行代码
element.parentElement.style.zIndex = zIndex;
});
}
onMounted(() => {
let map = new Map({
view: new View({
center: [12950000, 4860000],
zoom: 4
}),
layers: [
// 底图
new TileLayer({
source: new XYZ({url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}'})
})
],
target: 'map'
});
// 鼠标点击事件
map.on('click', function (evt) {
console.log(evt.pixel);
});
createOverlay(map, [12950000, 4860000], 'popover1', 1);
createOverlay(map, [12950000, 4970000], 'popover2', 1);
})
</script>
<style>
.map {
width: 100%;
height: 400px;
}
</style>
气泡窗口的 css 样式
scss语法,可以让 AI 帮忙转换成其他格式
/**
* 通过 css 相对布局实现的吸附窗口
* -------------------------------------------------------
* 优点:通过 css 样式实现的,性能相对较好,更加实用的方式;
* 缺点:是增加了一层 div,特定场合下,可能会影响界面布局。
*/
// attribute
$float-box-z-index: 100;
$float-box-bg: white;
$float-box-border: 1px solid #ddd;
$float-box-radius: 4px;
$float-box-padding: 12px;
// 阴影预留值
$float-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
$float-box-shadow: $sea-box-shadow;
// base-setting
@mixin float-panel {
position: absolute;
padding: $float-box-padding;
background: $float-box-bg;
border: $float-box-border;
border-radius: $float-box-radius;
box-shadow: $float-box-shadow;
z-index: $float-box-z-index;
}
.sea-float-box {
position: relative;
display: inline-block;
.float-top {
@include float-panel;
left: 0; // 左对齐
//right: 0; // 右对齐
bottom: 100%; // 底边对齐
margin-bottom: 10px;
}
.float-bottom {
@include float-panel;
left: 0; // 左对齐
//right: 0; // 右对齐
top: 100%; // 顶部对齐
margin-top: 10px;
}
.float-left {
@include float-panel;
top: 0;
right: 100%;
margin-right: 10px;
}
.float-right {
@include float-panel;
top: 0;
left: 100%;
margin-left: 10px;
}
}
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!