data-toggle tab无法下载Leaflet地图

21
我正在使用选项卡来显示清晰的内容,但其中一个选项卡在下载时出现了问题,因为它是一个data-toggle选项卡。它是一个Leaflet地图。 以下是代码:
导航栏代码:
<ul class="nav nav-tabs">
    <li class="active"><a data-toggle="tab" href="#home">Données principales</a></li>
    <li><a data-toggle="tab" href="#carte">Carte</a></li>
</ul>
<div class="tab-content">
    <div id="home" class="tab-pane fade in active">Lorem ipsum</div>
    <div id="carte" class="tab-pane fade"> **//see script below\\** </div>
</div>

脚本:

<div id="carteBenef"></div>
      <script type="text/javascript">
          $(document).ready(function () {
              var map = new L.Map('carteBenef');
              var cloudmadeUrl = 'http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png',
                     subDomains = ['otile1', 'otile2', 'otile3', 'otile4'],
                     cloudmadeAttrib = 'Data, imagery and map information provided by <a href="http://open.mapquest.co.uk" target="_blank">MapQuest</a>, <a href="http://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> and contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>';
              var cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18, attribution: cloudmadeAttrib, subdomains: subDomains});
              var iades = new L.LatLng(<?php echo $beneficiaire->latitude . ', ' . $beneficiaire->longitude; ?>)
              map.addLayer(cloudmade).setView(iades, 15);
              var benefLocation = new L.LatLng(<?php echo $beneficiaire->latitude . ', ' . $beneficiaire->longitude; ?>);
              var benef = new L.Marker(benefLocation);
              map.addLayer(benef);
              benef.bindPopup("<?php echo htmlspecialchars($beneficiaire->nom) . ' ' . htmlspecialchars($beneficiaire->prenom); ?>").openPopup();
          });
      </script>

地图在我放入选项卡之前就显示正常了,有人知道为什么现在不起作用吗?
4个回答

63
如果你在调整浏览器窗口大小后,发现你的Leaflet地图突然正常工作,那么你遇到了经典的“地图容器大小在地图初始化时无效”的问题:为了正确工作,Leaflet在初始化地图时会读取地图容器的大小(L.map("mapContainerId"))。
如果你的应用程序隐藏了该容器(通常通过CSS的display: none;或一些框架的选项卡/模态框等方式),或者后来改变了容器的尺寸,Leaflet将不会意识到新的大小。因此,它将无法正确渲染。通常情况下,它只会为它认为显示的容器部分下载瓦片。对于在地图初始化时完全隐藏的容器,可能只会下载左上角的一个瓦片。
这种错误经常发生在将地图容器嵌入到“选项卡”或“模态框”面板中,可能使用了流行的框架(Bootstrap、Angular、Ionic等)。
Leaflet监听浏览器窗口大小调整事件,并在发生时重新读取容器大小。这就解释了为什么在调整窗口大小时地图突然正常工作。
你还可以通过在选项卡面板显示时手动调用map.invalidateSize()来触发此更新(例如,在选项卡按钮点击时添加一个监听器),至少在容器首次以正确的尺寸渲染时这样做。
至于实现选项卡按钮点击监听器,你可以在SO上进行新的搜索,关于这个主题应该有很多资源可用,适用于大多数流行的框架。

2
这正是我遇到的问题,谢谢! - Ned
3
@Ned,请在你的问题中附上修复代码,并加上map.invalidateSize() - HAYMbl4
嗨,我添加了map.invalidateSize()但是它给了我一个错误:无法读取未定义的属性'_leaflet_pos',你有什么想法吗? - akshay kishore
嗨@akshayKishore,请随意打开一个新问题,并提供您特定问题的详细信息。 - ghybs
谢谢,现在明白了!现在完美运行。 在我的情况下,我使用带有“display:none”的地图div来隐藏它。 (leaflet地图的javascript函数名为initialize(),因此我可以单独调用它)。因此,将链接取消隐藏以进行全屏调用:object.style.display:'block'; initialize(); 然后首先可见,在初始化地图并在移动设备上完美运行。 - user2033838

22

首先,感谢 @ghybs 对于为什么 Leaflet 地图在这些情况下不能正常显示的很好的解释。

对于那些尝试过不成功 @ghybs 答案的人,你们应该尝试调整浏览器大小而不是调用地图对象的方法:

window.dispatchEvent(new Event('resize'));

正如@MarsAndBack所说,这个修复可能会对Leaflet的invalidateSize提供的平移/动画等特性造成问题。


2
这是一个方便的修复,但您将错过Leaflet的invalidateSize提供的pan/animation等功能。 - Kalnode

2
我遇到了一个问题,因为我使用了 modal bootstarp。无论如何都没有解决。我尝试了 map.invalidateSize()window.dispatchEvent(new Event('resize')); 但是没有解决。
最后通过以下方式解决: $('#map-modal').on('shown.bs.modal', function(event) {}); 'shown.bs.modal' 事件表示模态框完全加载完成且大小没有任何混淆,现在在其中编写您的代码。

2

对于像我这样无法通过@ghybs的解释(map.invalidateSize())解决挑战但能够通过@gangai-johann的解释解决的人,仍有可能以正确的方式完成。将无效指令放入setTimeout中,因为此时调度该指令可能还为时过早。

setTimeout(() => {
    this.$refs.mymap.mapObject.invalidateSize()
}, 100)

请参考https://dev59.com/xLTma4cB1Zd3GeqP2S1w#56364130 的回答,获取详细的指导。

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