Mapbox GL JS:将地图导出为 PNG 或 PDF?

Posted

技术标签:

【中文标题】Mapbox GL JS:将地图导出为 PNG 或 PDF?【英文标题】:Mapbox GL JS: Export map to PNG or PDF? 【发布时间】:2017-07-17 22:19:58 【问题描述】:

我使用的是 Mapbox GL JS 0.32 版。有没有办法将地图导出为高分辨率 PNG 或 PDF?

显然,我可以截图,但如果有更正式的方式会很好。

我找到了this repo,但它看起来很旧并且不清楚它是如何工作的。

我尝试使用the preserveDrawingBuffer option:

var map = new mapboxgl.Map(
    container: 'map',
    style: 'mapbox://styles/mapbox/light-v9',
    minZoom: 4,
    maxZoom: 14,
    center: [-2.0, 53.3],
    preserveDrawingBuffer: true
);
console.log(map.getCanvas().toDataURL());

这会在控制台中输出一个长数据 URL,但将其复制并粘贴到 a base64 converter 似乎只会产生一个空图像。

更新:这是我的新代码,完整:

mapboxgl.accessToken = 'pk.eyXXX';
var map = new mapboxgl.Map(
    container: 'map',
    style: 'mapbox://styles/mapbox/light-v9',
    minZoom: 4,
    maxZoom: 14,
    center: [-2.0, 53.3],
    preserveDrawingBuffer: true
);
var dpi = 300;
Object.defineProperty(window, 'devicePixelRatio', 
    get: function() return dpi / 96
);

map.on('load', function () 
    var content = map.getCanvas().toDataURL();
    console.log(content)
);

控制台的输出是这样的:http://pastebin.com/raw/KhyJkJWJ

【问题讨论】:

嗯,它正在工作。 content 的控制台输出在我看来像爱尔兰、英国和西欧。大多数浏览器都可以通过在地址栏中简单地 c&p 来查看它。要保存 png,请使用 toBlob() 而不是 toDataURL()。最后同样重要的是:要以高分辨率渲染该地图,请查看 github.com/mpetroff/print-maps 了解详细信息。 谢谢。我最终发现 Firefox 会这样做,但 Chrome 不会——因此我很困惑! 有没有办法做到这一点'无头'我不需要在浏览器中绘制任何实际地图,我只想循环通过一堆图层拍摄快照以用作缩略图/预览? 【参考方案1】:

有两个主要问题:

1.如何将地图画布作为图像获取?

实际上,您做的事情是正确的,但还为时过早。当load 事件被触发时,给该地图一些时间来加载和获取图像数据:

map.on('load', () => console.log(map.getCanvas().toDataURL()));

2。如何获得高分辨率图像?

通过根据您的目标 dpi 更改 window.devicePixelRatio,您可以欺骗您的浏览器生成高分辨率输出。我在 Matthew Petroff 创建的实现中找到了该解决方案,请参阅他在 https://github.com/mpetroff/print-maps 上的代码。 这是他用来生成高分辨率输出的技巧:

Object.defineProperty(window, 'devicePixelRatio', 
    get: function() return dpi / 96
);

Source

【讨论】:

谢谢!即使将线路移动到图像加载后,我仍然遇到同样的问题。如果我将输出粘贴到在线解码器中,它会说它无效:如果我将其粘贴到文本文件中并使用.png 扩展名保存,我将无法打开该文件。其他人是否能够成功使用此方法获取 PNG? 对于想知道为什么图像为空白的人...确保您在 mapbox gl 选项中有 preserveDrawingBuffer: true【参考方案2】:

我为偶然发现此线程的任何人创建了一个简单的工作示例:

(感谢@Vic 指出 Mapbox GL JS 中的 preserveDrawingBuffer-option)

<!DOCTYPE html>
<html>

<head>
    <meta charset='utf-8' />
    <title>Display a map</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css' rel='stylesheet' />
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <style>
    #map 
        margin: auto;
        width: 400px;
        height: 400px;
    
    </style>
</head>

<body>
    <div id='map'></div>
    <a id="downloadLink" href="" download="map.png">Download ↓</a>
    <div id="image"></div>
    <script>
    mapboxgl.accessToken = 'your-token-here';
    var map = new mapboxgl.Map(
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v9',
        center: [-74.50, 40],
        zoom: 9,
        preserveDrawingBuffer: true
    );

    $('#downloadLink').click(function() 
        var img = map.getCanvas().toDataURL('image/png')
        this.href = img
    )
    </script>
</body>

</html>

【讨论】:

最大的秘密是 preserveDrawingBuffer: true 之后它对我有用,谢谢!

以上是关于Mapbox GL JS:将地图导出为 PNG 或 PDF?的主要内容,如果未能解决你的问题,请参考以下文章

如何将自定义字段传递到 mapbox-gl js 以在地图上创建点?

如何实现mapbox-gl的tile源码

通过 mapbox gl js 向 mapbox 中的地图添加一些基本标记

为啥我的 Mapbox GL JS 地图在通过 Turbolinks 首次访问时无法正确显示?

Mapbox GL JS:如果单击标记,则忽略地图单击事件

mapbox-gl:从中心点、缩放级别和尺寸计算地图边界