z-index没有按预期工作

18

我正在使用Leaflet和Mapbox创建自定义地图。一切正常,直到我开始处理弹出窗口。

我的问题:我有一个自定义的导航/控制面板,但它需要在任何打开的弹出窗口后面(而它目前不是)。

我已经准备了JSFiddle和这个截图

进入图片描述此处

我的CSS部分是

#map-nav {
  position: absolute;
  left: 10px;
  top: 10px;
  z-index: 2;
}
.leaflet-popup-pane, .leaflet-popup {
  z-index: 1000 !important;
}
默认的leaflet类具有7(我想是)的z-index,我只是覆盖它以确保它被设置为100%。在浏览器(FF / Chrome)中检查代码时,我看到z-index已正确设置,并且.leaflet-popup中没有任何其他元素设置了z-index
我已经阅读到负的z-index可能解决这个问题,但由于我正在处理多个元素,所以我真的很希望有一个不太“hacky”的解决方案 - 如果有的话。 (欢迎JavaScript解决方案,因此标记)
从代码检查中可以看出,Leaflet将一些属性设置为.leaflet-popup,这些属性在位置方面是:transform: translate3d(..)bottomleft
任何帮助都会受到赞赏。
编辑:
我可以将#map-nav放在#map-content中,它仍然无法正常工作fiddle。 但是,当我尝试模仿此操作而不使用所有地图内容时,它确实起作用

1
z-index 仅在显式设置 position 时有效。在这种情况下是否设置了? - AntiHeadshot
4
我明白你的问题。它无法正常工作,因为这些元素处于不同的父级中。如果你给#map-content设置z-index:5;,就可以了。你明白我的意思。 - Alex
2
我认为这是不可能的,因为leaflet弹出窗口是你的<div id="map-content"></div>的内容,而map-content的z-index在map-nav div下面。 - B. Kemmer
1
@kingkero 这是做不到的。阅读此文以了解原因:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context - godfrzero
1
你应该将它添加到“.leaflet-popup-pane”中才能正常工作。 - Alex
显示剩余8条评论
1个回答

11
问题在于#map-nav与标记及其弹出窗口处于完全不同的堆叠上下文中。

目前的设置方式是,整个地图都在#map-nav后面。因此,在#map-nav.leaflet-popup-pane上更改z-index并不能真正帮助解决问题。

免责声明: 这是一种可怕的、可怕的黑客行为。如果您查阅Leaflet的文档并找到添加自己的部件的方法,强烈建议您使用那种方法而不是这种方法。

尽管如此,我有一些看起来有点用的东西(你的效果可能会有所不同):

  1. #map-nav移动到.leaflet-map-pane
  2. 创建一个MutationObserver并观察.leaflet-map-pane属性的变化。
  3. 每当.leaflet-map-panestyle属性发生变化时,获取其style.transform属性并提取x和y值。将这些值反转并应用到#map-nav上。

var map = L.map('map-content', {
  zoomControl: false
}).setView([51.505, -0.09], 13);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
  attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
  maxZoom: 18,
  id: 'rauschundrausch.cih3gisks00r8rlly0ob5s2me',
  accessToken: 'pk.eyJ1IjoicmF1c2NodW5kcmF1c2NoIiwiYSI6ImNpaTYyeW14MTAwNml2eW0zcmR6aHIzdDcifQ.6T8nzYq49rFnvcqk6lgYPg'
}).addTo(map);

var marker = L.marker([51.5, -0.09]).addTo(map);
marker.bindPopup("this is a<br>large<br>popup<br>in<br>terms of height");

var mapNav = document.getElementById("map-nav");

var mapPane = document.querySelector(".leaflet-map-pane");

var rxTranslate = /translate(?:3d)?\(([^\)]+)\)/i;

mapPane.appendChild(mapNav);

var observer = new MutationObserver(function(mutations) {
  if (mutations.some(m => m.attributeName === "style")) {
    // apply an inverse transform
    mapNav.style.transform = "translate(" + mapPane
      .style
      .transform
      .match(rxTranslate)[1]
      .split(",")
      .slice(0, 2) /* extract only x and y; discard z */
      .map(n => parseFloat(n) * -1 + "px") /* invert values */ + ")";
  }
});

observer.observe(mapPane, {
  attributes: true
});
#map {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
#map-nav {
  position: absolute;
  left: 10px;
  top: 10px;
  width: 100px;
  height: 100px;
  background-color: #ccc;
  z-index: 200;
  box-shadow: inset 0 0 0 1px #f00;
}
#map-content {
  width: 100%;
  height: 100%;
}
.leaflet-popup-pane {
  z-index: 3;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" />
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"></script>
<div id="map">
  <div id="map-content">
    <div id="map-nav"></div>
  </div>
</div>

在拖动时,某些客户端可能会出现延迟。您可以使用超时来推迟更新,但这意味着导航菜单会在您停止拖动之前移动。


1
抢先一步了。听起来有点粗糙,但据我所知这是唯一的方法。不错的解决方案。 - isick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接