Leaflet加载OpenStreetMap瓦片问题:PDF导出时地图未完全加载如何解决
问题:打印PDF时Leaflet地图瓦片未完全加载,出现NS_BINDING_ABORTED错误
使用Laravel 8.83和PHP 7.4制作PDF导出视图,包含图片、文本和OpenStreetMap地图区域,页面加载正常,但浏览器打印预览中地图瓦片未完全加载,Firefox控制台报NS_BINDING_ABORTED错误,如何强制瓦片完全加载?
原视图代码
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>TEST</title> <style> body { font-size: 12px; color: #000; max-width: 720px; } * { font-family: 'muli', sans-serif; font-style: normal; box-sizing: border-box; margin: 0; padding: 0; } .article-pdf { padding: 10px; max-width: 720px; margin: 0 auto; } .row { display: flex; width: 100%; align-items: flex-start; margin: 0 -15px; } .col-6 { width: 50%; padding: 0 15px; } .image-container { position: relative; } .image-container::after { content: ""; display: block; padding-bottom: 100%; border: 0.5px solid grey; } .image { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); padding: 7px; } .card { position: relative; z-index: 0; } .card .map-container { margin-left: 0; margin-right: 0; position: absolute; left: 0; width: 100%; height: 100%; } .card::after { content: ""; display: block; padding-bottom: 100%; } .topic { font-size: 12px; font-style: normal; line-height: 30px; border-bottom: solid 1px #000; } .title { margin-bottom: 10px; font-size: 30px; line-height: 38px; } .subtitle em { font-weight: normal; } </style> <link href="{{ asset('css/site/leaflet.css') }}" rel="stylesheet"> </head> <body class="lang-fr" onload="window.print()"> <article class="article-pdf"> <p class="topic">---[ TEST PDF ]---</p> <h1 class="title">Archive title</h1> <div class="row"> <div class="col-6"> <div class="image-container"> <img class="image img-portrain}" src="{{ asset('storage/images/medium/' . $archive->resource) }}" alt=""> </div> </div> <div class="col-6"> <div class="card"> <div class="map-container" id="map"></div> </div> </div> </div> </article> <script src="{{ asset('js/site/leaflet.js') }}" defer></script> <script src="{{ asset('js/site/article.js') }}" defer></script> </body> </html>
原JS代码
const search_map = L.map('map').setView([28.787, 4.043], 5) const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {minZoom: 4, maxZoom: 19}).addTo(search_map)
解决方案
核心问题是window.print()在地图瓦片加载完成前触发,导致浏览器中断瓦片请求。可通过以下方式解决:
监听瓦片加载完成事件再触发打印
Leaflet的TileLayer提供load事件,所有可见瓦片加载完成时触发,监听该事件确保瓦片加载完毕后再调用打印。移除提前触发的打印事件
删除<body>标签的onload="window.print()",避免页面刚加载就触发打印。
修改后的JS代码
const search_map = L.map('map').setView([28.787, 4.043], 5); const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { minZoom: 4, maxZoom: 19 }).addTo(search_map); // 监听所有可见瓦片加载完成事件 tiles.on('load', function() { // 加100ms延迟确保地图渲染完全,再触发打印 setTimeout(() => { window.print(); }, 100); });
修改后的视图代码
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>TEST</title> <style> body { font-size: 12px; color: #000; max-width: 720px; } * { font-family: 'muli', sans-serif; font-style: normal; box-sizing: border-box; margin: 0; padding: 0; } .article-pdf { padding: 10px; max-width: 720px; margin: 0 auto; } .row { display: flex; width: 100%; align-items: flex-start; margin: 0 -15px; } .col-6 { width: 50%; padding: 0 15px; } .image-container { position: relative; } .image-container::after { content: ""; display: block; padding-bottom: 100%; border: 0.5px solid grey; } .image { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); padding: 7px; } .card { position: relative; z-index: 0; } .card .map-container { margin-left: 0; margin-right: 0; position: absolute; left: 0; width: 100%; height: 100%; } .card::after { content: ""; display: block; padding-bottom: 100%; } .topic { font-size: 12px; font-style: normal; line-height: 30px; border-bottom: solid 1px #000; } .title { margin-bottom: 10px; font-size: 30px; line-height: 38px; } .subtitle em { font-weight: normal; } </style> <link href="{{ asset('css/site/leaflet.css') }}" rel="stylesheet"> </head> <body class="lang-fr"> <article class="article-pdf"> <p class="topic">---[ TEST PDF ]---</p> <h1 class="title">Archive title</h1> <div class="row"> <div class="col-6"> <div class="image-container"> <img class="image img-portrain" src="{{ asset('storage/images/medium/' . $archive->resource) }}" alt=""> </div> </div> <div class="col-6"> <div class="card"> <div class="map-container" id="map"></div> </div> </div> </div> </article> <script src="{{ asset('js/site/leaflet.js') }}" defer></script> <script src="{{ asset('js/site/article.js') }}" defer></script> </body> </html>
额外说明
- 100ms延迟是为了处理Leaflet最后的渲染步骤,避免地图未完全绘制就进入打印预览,可根据实际加载速度调整。
- 若瓦片加载仍不稳定,可尝试增加延迟时间,或检查地图容器的尺寸是否在初始化时已明确(当前代码中容器尺寸通过CSS伪元素设置,是可行的)。
内容的提问来源于stack exchange,提问作者Steph74
相关产品推荐
相关产品推荐

