OpenLayers:怎样控制Overlay的层级?

打印 上一主题 下一主题

主题 1616|帖子 1616|积分 4848

我最近在使用Overlay的时候碰到了一个问题,我向地图中添加了两种不同的Overlay(下图中的蓝色标牌和粉色标牌),我渴望粉色标牌可以显示在最上层,可偏偏蓝色标牌却将其遮挡住了。于是我对Overlay的层级开始起了兴趣,渴望可以找到控制Overlay层级顺序的方法。


一、Overlay的原始层级顺序

决定Overlay原始层级的因素

起首得搞清楚一个问题,为什么粉色标牌的层级会比蓝色标牌低呢?
我观察了一番发现缘故原由是由于我是先将蓝色标牌添加到地图中,后将粉色标牌添加到地图中。


如果调换一下代码顺序,先添加粉色标牌,那么就变成了粉色标牌的层级更高了




因此可以得出结论:
决定Overlay原始层级的因素是添加Overlay的先后顺序,先添加到地图中的Overlay层级高,后添加到地图中的Overlay层级低。
为什么是“先高后低”的顺序?

为什么会有这种“先高后低”的层级顺序呢?难道Elment元素就是按照这种顺序排列的吗?
于是我便举行了一次测试,依次插入蓝色、粉色两个元素,这两个元素都脱标且z-index属性值相同,结果发生后插入的粉色元素覆盖了先插入的蓝色元素。
这说明在默认情况下Element元素的层级实际上遵循的是“先低后高”的原则,这个与Overlay的情况是不符的。


于是我查看了一下OpenLayers地图元素中的DOM数据,居然发现粉色标牌的元素在最前面,而蓝色标牌的元素在后面。这说明其实粉色标牌的元素才是先被插入到地图元素中的,这与我们编程的时候使用map.addOverlay插入的顺序是相反的。


那我大概就明白了,OpenLayers的地图中用于存储Overlay的应该是一个栈结构,由于栈结构遵循着“后进先出”的原则,因此在渲染Overlay时,后插入的Overlay会先从存储栈中弹出举行渲染,因此才出现了层级“先高后低”的情况。


我用代码模拟了一下这种方式:
  1.   // 点击添加overlay
  2. function handleClick(event) {
  3.     // 添加蓝色标牌
  4.     const el_blue = document.createElement("div");
  5.     el_blue.className = "test-overlay blue";
  6.     el_blue.innerHTML = "蓝色overlay";
  7.     addOverlay(el_blue);
  8.     // 添加粉色标牌
  9.     const el_pink = document.createElement("div");
  10.     el_pink.className = "test-overlay pink";
  11.     el_pink.innerHTML = "粉色overlay";
  12.     addOverlay(el_pink);
  13.   }
  14.   //地图的Overlay存储栈
  15.   const overlayStack = [];
  16.   function addOverlay(overlay) {
  17.     //将overlay添加到存储栈中
  18.     overlayStack.push(overlay);
  19.     // 渲染overlay到地图上
  20.     const map = document.getElementById("map");
  21.     for (let i = overlayStack.length - 1; i >= 0; i--) {
  22.       const el = overlayStack[i];
  23.       map.appendChild(el);
  24.     }
  25.   }
复制代码


二、控制Overlay层级的方法

上面的理论探索纯属个人兴趣,其实我真正要办理的照旧怎样控制Overlay层级的问题。
固然最简单的方法就是控制添加Overlay的顺序,包管想要展示在上层的Overlay先添加。但是这种方法显得有些“蠢萌”了,在许多复杂的项目中我们是无法保障Overlay的插入顺序的,因此我认为需要找到更加有效的方法。
提到控制显示层级我们很轻易就能想到CSS中的z-index属性,这似乎是一个不错的思绪,但是z-index属性究竟应该加在哪儿呢?
z-index的错误使用

一开始我想的很简单,我认为只要给每个Overlay所绑定的element设置z-index就可以了。
  1. .test-overlay {
  2.   position: relative;
  3.   padding: 10px;
  4.   cursor: pointer;
  5.   /* 蓝色overlay样式 */
  6.   &.blue {
  7.      z-index: 1;
  8.     background-color: skyblue;
  9.   }
  10.   /* 粉色overlay样式 */
  11.   &.pink {
  12.     z-index: 2; /* 给粉色标牌设置更高的层级 */
  13.     background-color: pink;
  14.   }
  15. }
复制代码
但是设置之后发现好像没有任何的作用。为什会如许呢?
缘故原由是由于,添加到DOM树中的Overlay的element还会被包装一层,所以我设置z-index的div.blue元素和div.pink元素实际上是表兄弟元素(它们的父元素是兄弟元素)


表兄弟元素之间的层级关系就不由它们的z-index属性决定,而是要看它们父元素的层级。也就是说z-index应该设置在div.blue元素和div.pink的父元素也就是Overlay的包装元素上。


怎样正确的使用z-index控制Overlay的层级

那么怎样给Overlay的包装元素设置z-index属性呢?我找到了两种方法。
方法一,通过Overlay的className属性给包装元素添加一个类名。


起首在创建Overlay时设置className属性,给蓝色标牌和粉色标牌设置不同的类名
  1. // 添加蓝色overlay
  2. positions.forEach((position, index) => {
  3.   addOverlay(window.map, {
  4.     id: `blue-${index}`,
  5.     groupId: "blue",
  6.     element: createBlueElement(),
  7.     position,
  8.     className: "ol-overlay-container ol-selectable blue-container",
  9.   });
  10. });
  11. // 添加粉色overlay
  12. positions
  13.   .filter((_, index) => index % 2 === 0)
  14.   .forEach((position, index) => {
  15.     addOverlay(window.map, {
  16.       id: `pink-${index}`,
  17.       groupId: "pink",
  18.       element: createPinkElement(),
  19.       offset: [20, 20],
  20.       position,
  21.       className: "ol-overlay-container ol-selectable pink-container",
  22.     });
  23.   });
复制代码
然后再通过类名给不同的Overlay的包装元素设置不同的层级
  1. .blue-container {
  2.   z-index: 1;
  3. }
  4. .pink-container {
  5.   z-index: 2;
  6. }
复制代码
最终就可以实现粉色标牌不被蓝色标牌遮挡。


方法二,通过:has选择器给包装元素添加样式
:has选择器可以让你在选择元素上更佳机动,也就是可以让你选中本元素之前的兄弟级别的元素大概是父元素亦大概是先人元素。
它的使用方法是:当前元素之前的元素:has(当前元素)
因此我们就可以利用:has选择器分别选中div.blue元素和div.pink元素的父元素,然后给它们设置层级。
  1. .ol-overlay-container.ol-selectable:has(>.blue){
  2.   z-index: 1;
  3. }
  4. .ol-overlay-container.ol-selectable:has(>.pink){
  5.   z-index: 2;
  6. }
复制代码


参考资料


  • OpenLayers v10.5.0 API - Class: Overlay
  • OpenLayers之 OverLay问题汇总_openlayers overlay zindex-CSDN博客
  • :has() - CSS:层叠样式表 | MDN
  • 伪类选择器中的:has_has选择器-CSDN博客

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

羊蹓狼

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表