如何从 Mapbox GL JS 获得可用 canvas
How to get usable canvas from Mapbox GL JS
我正在使用 Mapbox GL,并尝试获取它的快照,然后将快照与另一个覆盖的图像合并以进行输出。
我有一个 HTMLCanvasElement
关闭屏幕,我首先将 Map.getCanvas()
返回的 canvas 写入它,然后写入第二个(alpha 透明) canvas 在上面。
问题是,虽然我在 Map 实例中清楚地看到屏幕上的元素,但结果只显示第二个 image/canvas 写入,其余为空白。
所以我只导出地图的 canvas,我看到这是因为地图 canvas 是空白的,尽管 console.log()
显示其中的图像数据很大大量信息。
这是我的导出函数:
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
}
这是一个错误,还是我遗漏了什么?
更新:我有点明白这是怎么回事,并且有可能的选择。
在偶然发现 Mapbox feature request 后,我了解到如果将 preserveDrawingBuffer
选项设置为 false
(默认值)来实例化 Map
,您将不会能够获得具有可用图像数据的 canvas。但是将此选项设置为 true
会降低性能。但是在 Map 实例化后你不能改变这个设置...
我希望 Map 尽可能发挥最佳性能!!!!
所以,在 我无意中发现了一个关于 three.js 的问题,我了解到如果我在渲染后立即截取屏幕截图,我将得到我想要的 canvas/data需要。
我尝试在捕获 canvas 之前调用 this.host.map['_rerender']()
,但它仍然返回空白。
然后在源代码中四处搜索,我发现了一个名为_requestRenderFrame
的函数,看起来它可能是我需要的,因为我可以要求Map到运行一个函数后立即下一个渲染周期。但由于某种原因,我发现该功能是 omitted in the compiled code, whilst present in the source,显然是因为它仅在母版中,而不是发行版的一部分。
所以我还没有真正令人满意的解决方案,所以请让我知道任何见解。
正如您在更新的问题中提到的,解决方案是在地图初始化时设置 preserveDrawingBuffer: true
。
为了回答你更新的问题,我认为@jfirebaugh 在 https://github.com/mapbox/mapbox-gl-js/issues/6448#issuecomment-378307311 的回答总结得很好:
preserveDrawingBuffer
can't be modified on the fly. It has to be set at the time the WebGL context is created, and that can have a negative effect on performance.
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.
因此,尽管可能会在渲染后立即抓取 canvas 数据 URL,但规范并不能保证这一点。
我正在使用 Mapbox GL,并尝试获取它的快照,然后将快照与另一个覆盖的图像合并以进行输出。
我有一个 HTMLCanvasElement
关闭屏幕,我首先将 Map.getCanvas()
返回的 canvas 写入它,然后写入第二个(alpha 透明) canvas 在上面。
问题是,虽然我在 Map 实例中清楚地看到屏幕上的元素,但结果只显示第二个 image/canvas 写入,其余为空白。
所以我只导出地图的 canvas,我看到这是因为地图 canvas 是空白的,尽管 console.log()
显示其中的图像数据很大大量信息。
这是我的导出函数:
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
}
这是一个错误,还是我遗漏了什么?
更新:我有点明白这是怎么回事,并且有可能的选择。
在偶然发现 Mapbox feature request 后,我了解到如果将 preserveDrawingBuffer
选项设置为 false
(默认值)来实例化 Map
,您将不会能够获得具有可用图像数据的 canvas。但是将此选项设置为 true
会降低性能。但是在 Map 实例化后你不能改变这个设置...
我希望 Map 尽可能发挥最佳性能!!!!
所以,在
我尝试在捕获 canvas 之前调用 this.host.map['_rerender']()
,但它仍然返回空白。
然后在源代码中四处搜索,我发现了一个名为_requestRenderFrame
的函数,看起来它可能是我需要的,因为我可以要求Map到运行一个函数后立即下一个渲染周期。但由于某种原因,我发现该功能是 omitted in the compiled code, whilst present in the source,显然是因为它仅在母版中,而不是发行版的一部分。
所以我还没有真正令人满意的解决方案,所以请让我知道任何见解。
正如您在更新的问题中提到的,解决方案是在地图初始化时设置 preserveDrawingBuffer: true
。
为了回答你更新的问题,我认为@jfirebaugh 在 https://github.com/mapbox/mapbox-gl-js/issues/6448#issuecomment-378307311 的回答总结得很好:
preserveDrawingBuffer
can't be modified on the fly. It has to be set at the time the WebGL context is created, and that can have a negative effect on performance.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.
因此,尽管可能会在渲染后立即抓取 canvas 数据 URL,但规范并不能保证这一点。