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

问题描述 投票:0回答:2

我正在使用 Mapbox GL,并尝试获取它的快照,并将快照与另一个叠加的图像合并以进行输出。

我在屏幕外有一个

HTMLCanvasElement
,我首先将从
Map.getCanvas()
返回的画布写入到它,然后在其上写入第二个(alpha 透明)画布。

问题是,虽然我在 Map 实例中清楚地看到屏幕上的元素,但结果只显示了写入的第二个图像/画布,其余的都是空白。

所以我只导出地图的画布,我发现这是因为地图画布是空白的,尽管

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 功能请求时,我了解到,如果您将

Map
选项设置为
preserveDrawingBuffer
(默认值)来实例化您的
false
,您将无法获得包含可用图像数据的画布。但将此选项设置为
true
会降低性能。但是在实例化 Map 后您无法更改此设置...

我希望地图能够发挥出最佳性能!!!!

所以,在这个答案上,我偶然发现,关于三个.js的问题,我了解到,如果我在渲染后立即截取屏幕截图,我将获得我需要的画布/数据。

我尝试在捕获画布之前调用

this.host.map['_rerender']()
,但它仍然返回空白。

然后在源代码中搜索,我发现了一个名为

_requestRenderFrame
的函数,看起来它可能就是我需要的,因为我可以要求 Map 在下一个渲染周期后立即运行一个函数。但我发现,由于某种原因,该函数在编译的代码中被忽略,而在源代码中却存在,显然是因为它只存在于主版本中,而不是发布版本的一部分。 所以我还没有真正满意的解决方案,所以请让我知道任何见解。

正如您在更新的问题中提到的,解决方案是在地图初始化时设置
javascript canvas html5-canvas mapbox mapbox-gl-js
2个回答
3
投票

为了回答您更新的问题,我认为 @jfirebaugh 在 
https://github.com/mapbox/mapbox-gl-js/issues/6448#issuecomment-378307311

的回答总结得很好:

preserveDrawingBuffer
无法即时修改。它必须在创建 WebGL 上下文时设置,这可能会对性能产生负面影响。

有传言说你可以在渲染后立即获取画布数据 URL,而不需要 
preserveDrawingBuffer

,但我还没有验证这一点,并且我怀疑规范并不能保证这一点。

因此,尽管可能可以在渲染后立即获取画布数据 URL,但规范并不能保证这一点。

这是函数式代码。请注意,Mapbox 使用 WebGl 进行渲染,因此

1
投票
返回

null

。最好创建一个画布元素,获取上下文,并使用 
drawImage
 函数设置地图。我希望这有帮助。
  let mapEl = document.querySelector('.mapboxgl-canvas');
    let resizedCanvas = document.createElement("canvas");
    let resizedContext = resizedCanvas.getContext("2d");


    const isMapEmpty = mapEl.toDataURL() === "data:,";
    if (isMapEmpty) {
        console.log("The map is void");
    } else {
        console.log("The map has information");
    }

    resizedCanvas.height = "1035";
    resizedCanvas.width = "755";

    resizedContext.drawImage(mapEl, 0, 0, 755, 1035);
    let b64 = await mergeImages([
            {
                src: resizedCanvas.toDataURL(),
                x: 297,
                y: 16
            },
            {
                src: "/assets/anotherImage.png"
            }
        ]
    )


© www.soinside.com 2019 - 2024. All rights reserved.