简体   繁体   English

如何从 Mapbox GL JS 获取可用的画布

[英]How to get usable canvas from Mapbox GL JS

I'm using Mapbox GL , and trying to get a snapshot of it, and merge the snapshot with another image overlaid for output.我正在使用Mapbox GL ,并尝试获取它的快照,并将快照与覆盖输出的另一个图像合并。

I have a HTMLCanvasElement off screen, and I'm first writing the canvas returned from Map.getCanvas() to it, then writing the second (alpha transparent) canvas over that.我在屏幕外有一个HTMLCanvasElement ,我首先将从Map.getCanvas()返回的画布写入它,然后在其上写入第二个(alpha 透明)画布。

The problem is that, though I clearly see elements onscreen in the Map instance, the result only shows the second image/canvas written, and the rest is blank.问题是,虽然我在 Map 实例中清楚地看到屏幕上的元素,但结果只显示了第二个图像/画布,其余的都是空白的。

So I export just the map's canvas, and I see it is because the map canvas is blank, although a console.log() shows the image data from it to be a large chunk of information.所以我只导出地图的画布,我看到这是因为地图画布是空白的,尽管console.log()显示来自它的图像数据是一大块信息。

Here's my export function:这是我的导出功能:

  onExport(annotationCanvas: HTMLCanvasElement) {

    const mergeCanvas: HTMLCanvasElement = document.createElement('canvas');
    const mapCanvas: HTMLCanvasElement = this.host.map.getCanvas();
    const mergeCtx: CanvasRenderingContext2D = mergeCanvas.getContext('2d');

    mergeCanvas.height = annotationCanvas.height;
    mergeCanvas.width = annotationCanvas.width;
    mergeCtx.drawImage(mapCanvas, 0, 0);
    mergeCtx.drawImage(annotationCanvas, 0, 0);

    const mergedDataURL = mergeCanvas.toDataURL();
    const mapDataURL = mapCanvas.toDataURL();
    const annotationDataURL = annotationCanvas.toDataURL();

    console.log(mapDataURL); // Lots of data

    download(mapDataURL, 'map-data-only.png'); // Blank image @ 1920x1080
    download(mergedDataURL, 'annotation.png'); // Only shows annotation (the second layer/canvas) data

  }

Is this a bug, or am I missing something?这是一个错误,还是我错过了什么?

UPDATE: I sort of figured out what this is about, and have possible options.更新:我有点想通了这是关于什么的,并且有可能的选择。

Upon stumbling upon a Mapbox feature request , I learned that if you instantiate your Map with the preserveDrawingBuffer option set to false (the default), you wont be able to get a canvas with usable image data.在偶然发现Mapbox 功能请求时,我了解到,如果您在将preserveDrawingBuffer选项设置为false (默认值)的情况下实例化您的Map ,您将无法获得带有可用图像数据的画布。 But setting this option to true degrades performance.但是将此选项设置为true会降低性能。 But you can't change this setting after a Map is instantiated...但是在实例化 Map 后您无法更改此设置...

I want the Map to perform the best it possibly can!!!!我希望地图尽可能发挥最佳性能!!!!

So, on this answer I stumbled on, regarding a question about three.js, I learned that if I take the screenshot immediately after rendering, I will get the canvas/data that I need.所以,在这个我偶然发现的答案中,关于一个关于three.js的问题,我了解到如果我在渲染后立即截取屏幕截图,我将获得我需要的画布/数据。

I tried just calling this.host.map['_rerender']() right before I capture the canvas, but it still returned blankness.我尝试在捕获画布之前调用this.host.map['_rerender']() ,但它仍然返回空白。

Then searching around in the source code, I found a function called _requestRenderFrame , that looks like it might be what I need, because I can ask the Map to run a function immediately after the next render cycle.然后在源代码中搜索,我找到了一个名为_requestRenderFrame的函数,看起来它可能是我需要的,因为我可以要求 Map 在下一个渲染周期后立即运行一个函数。 But as I come to find out, for some reason, that function is omitted in the compiled code, whilst present in the source , apparently because it is only in the master, and not part of the release.但是当我发现,出于某种原因,该函数在编译代码中省略,而在源代码中存在,显然是因为它只存在于 master 中,而不是发布的一部分。

So I don't really have a satisfactory solution yet, so please let me know of any insights.所以我还没有真正满意的解决方案,所以请让我知道任何见解。

As you mentioned in your updated question the solution is to set preserveDrawingBuffer: true upon Map initialisation.正如您在更新的问题中提到的,解决方案是在 Map 初始化时设置preserveDrawingBuffer: true

To answer your updated question I think @jfirebaugh's answer at https://github.com/mapbox/mapbox-gl-js/issues/6448#issuecomment-378307311 sums it up very well:为了回答你更新的问题,我认为@jfirebaugh 在https://github.com/mapbox/mapbox-gl-js/issues/6448#issuecomment-378307311的回答总结得很好:

preserveDrawingBuffer can't be modified on the fly.不能即时修改preserveDrawingBuffer It has to be set at the time the WebGL context is created, and that can have a negative effect on performance.它必须在创建 WebGL 上下文时设置,这会对性能产生负面影响。

It's rumored that you can grab the the canvas data URL immediately after rendering, without needing preserveDrawingBuffer , but I haven't verified that, and I suspect it's not guaranteed by the spec.有传言说,您可以在渲染后立即获取画布数据 URL,而无需preserveDrawingBuffer ,但我尚未验证这一点,我怀疑规范无法保证这一点。

So although it might be possible to grab the canvas data URL immediately after rendering, it's not guaranteed by the spec.因此,尽管可以在渲染后立即获取画布数据 URL,但规范并不能保证这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM