Rails中wicked_pdf生成PDF加载MapboxGL JS失败,求解决方案
我之前也碰到过wicked_pdf和前端地图库兼容的类似问题,咱们一步步来排查解决:
一、修复MapboxGL JS在wicked_pdf中的加载问题
你遇到的ReferenceError: Can't find variable: mapboxgl,大概率是wkhtmltopdf在MapboxGL JS完全加载/初始化前就开始渲染PDF了,或者配置上没开启足够的JS支持。试试下面几个步骤:
1. 确保正确引入资源并等待DOM/地图加载完成
MapboxGL需要先加载CSS再加载JS,而且必须等DOM就绪后再初始化地图。修改你的视图代码:
<!-- 先引入MapboxGL的样式 --> <%= wicked_pdf_stylesheet_link_tag 'https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css' %> <!-- 再引入MapboxGL的JS --> <%= wicked_pdf_javascript_include_tag 'https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js' %> <!-- 地图容器 --> <div id="map" style="width: 800px; height: 600px;"></div> <script> // 等待DOM完全加载后再初始化地图 document.addEventListener('DOMContentLoaded', function() { // 替换成你的Mapbox Access Token mapboxgl.accessToken = 'YOUR_MAPBOX_TOKEN'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/streets-v12', center: [-74.5, 40], // 示例中心点 zoom: 9 }); // 等待地图加载完成后再添加GeoJSON图层 map.on('load', function() { // 加载你的GeoJSON数据 map.addSource('custom-geojson', { type: 'geojson', data: <%= @geo_json_data.to_json.html_safe %> }); // 添加图层样式 map.addLayer({ id: 'geojson-layer', type: 'fill', source: 'custom-geojson', paint: { 'fill-color': '#2ecc71', 'fill-opacity': 0.6 } }); // 可选:用window.status告诉wicked_pdf地图已加载完成(比固定延迟更可靠) window.status = 'map_rendered'; }); }); </script>
2. 调整wicked_pdf的配置参数
在config/initializers/wicked_pdf.rb里添加/修改配置,给JS足够的加载和渲染时间:
WickedPdf.config = { enable_javascript: true, # 确保JS支持开启 javascript_delay: 5000, # 初始设置5秒延迟(可根据GeoJSON大小调整) window_status: 'map_rendered' # 等待我们在JS里设置的状态 }
用window_status比固定延迟更精准,只有当地图完全加载并渲染好后,wicked_pdf才会生成PDF。
3. 尝试本地引入MapboxGL JS
如果CDN加载有网络或跨域问题(虽然wkhtmltopdf一般支持CDN),可以把MapboxGL的JS文件下载到app/assets/javascripts目录,然后用本地路径引入:
<%= wicked_pdf_javascript_include_tag 'mapbox-gl.js' %>
二、替代地图工具推荐
如果还是搞不定MapboxGL,可以试试这些更易在wicked_pdf中兼容的地图库:
1. Leaflet
轻量开源地图库,对wkhtmltopdf的兼容性更好,支持GeoJSON图层,用法简单:
<%= wicked_pdf_stylesheet_link_tag 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css' %> <%= wicked_pdf_javascript_include_tag 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js' %> <div id="map" style="width: 800px; height: 600px;"></div> <script> document.addEventListener('DOMContentLoaded', function() { const map = L.map('map').setView([40, -74.5], 9); // 添加底图 L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); // 添加GeoJSON图层 L.geoJSON(<%= @geo_json_data.to_json.html_safe %>).addTo(map); window.status = 'map_rendered'; }); </script>
Leaflet的JS加载更快,渲染逻辑更简单,很少出现wicked_pdf抓不到变量的问题。
2. OpenLayers
功能更强大的开源地图库,支持复杂的GeoJSON样式和交互,兼容性也不错,适合需要更专业地图功能的场景。
3. 后端生成地图图片
如果前端库始终有问题,可以考虑用Ruby后端直接生成地图图片(比如结合RMagick和GeoJSON渲染库),然后把图片嵌入PDF。这种方式不需要依赖前端JS,但需要处理地图渲染的细节,灵活性稍差。
内容的提问来源于stack exchange,提问作者kkk

