HTML2Canvas将两个捕获的画布合并为一个。

6
使用HTML2Canvas,我正在尝试捕获Google地图的截图(可以正常工作),然后捕获覆盖在其上方的#overlay div(用于允许人们在特定位置放置图片)(也可以正常工作)。
然后页面会显示这两个canvas元素,然后我想再次捕获它们,将两个画布合并成一个图像,然后用户可以下载。
到目前为止,我的问题是当我尝试捕获#preview div时,HTML2Canvas似乎没有捕获它创建的canvas元素。
HTML:
<div id="mainPanel">
    <div id="overlay">

    </div>
    <button class="download">Download as PDF</button>
    <button onclick="startEdit();" class="edit_button">Start Editing</button>
    <div id="map">
        <input id="pac-input" class="controls" type="text" placeholder="Search Box">
        <div id="map-canvas"></div>
    </div>
    <div id="preview">

    </div>
</div>

HTML2Canvas JQuery:

$(".download").click(function() {
        html2canvas($("#map"), {
            logging: true,
            proxy: "https://html2canvas.appspot.com/query",
            onrendered: function(canvas) {
                // var img = canvas.toDataURL("image/png");
                $(canvas).css({"position" : "absolute", "z-index" : "999"});
                document.getElementById("preview").appendChild(canvas);

                html2canvas($("#overlay"), {
                    logging: true,
                    onrendered: function(canvas1) {

                        // var img = canvas.toDataURL("image/png");
                        $(canvas1).css({"position" : "absolute", "z-index" : "1000"});
                        document.getElementById("preview").appendChild(canvas1);

                        setTimeout(function() {downloadURI()}, 5000);
                    }
                });
            }
        });
});

function downloadURI() {
    html2canvas($("#preview"), {
        logging: true,
        onrendered: function(canvas2) {

            var img = canvas2.toDataURL("image/png");
                window.open(img);
                // var link = document.createElement("a");
                // link.download = "image-download.png";
                // link.href = img;
                // link.click();
            }
        });
    }

如您所见,我已经尝试延迟DownloadURI函数以防止画布未能及时加载,但这不是问题所在。我不确定是否有关于canvas元素的问题导致插件无法正常工作。

工作原理:我的上述代码相当简单。当一个HTML2Canvas完成后,它运行另一个HTML2Canvas。这两个画布都被添加到#preview元素中,以便我可以捕获该元素和其上面的2个画布。完成后,它会运行另一个函数来拍摄#preview元素,我希望将2张图片叠加成一张用户可以下载的单张图片,但结果只显示了一张空白图片。

如果需要更多信息,请告诉我,谢谢。


为什么不通过它们的数据将两个图像简单合并,而不是创建第三个预览 DIV?如果可能的话,我可以提交一份包含代码的答案。 - EvilZebra
我不确定那是否可能。如果你能做到,那将是惊人的!:D - Mallander
1个回答

6

这个函数接受两个参数topbottom。两个参数都应该是ImageData对象,可以通过ctx.getImageData()获得。底部的ImageData将与顶部数据合并。此函数使用Porter-Duff方法合并颜色。

function mergeData(top, bottom){
    var tD = top.data,
        bD = bottom.data,
        l = tD.length;
    for(var i = 0; i < l; i += 4){
        //source alpha
        var alphaSrc = tD[i+3] / 255, //source alpha
            alphaDst = bD[i+3] / 255, //destination alpha
            alphaSrcO = 1 - alphaSrc, //(1 - x)
            alpha = alphaSrc + alphaDst * alphaSrcO; //if destination alpha is opaque
        //merge colors
        bD[i] = ((tD[i]*alphaSrc) + (bD[i]*alphaDst*alphaSrcO)) / alpha,
        bD[i+1] = ((tD[i+1]*alphaSrc) + (bD[i+1]*alphaDst*alphaSrcO)) / alpha,
        bD[i+2] = ((tD[i+2]*alphaSrc) + (bD[i+2]*alphaDst*alphaSrcO)) / alpha,
        bD[i+3] = 255*alpha;
    }
    //return bottom
    return bottom;
}

要使用此功能及其返回的数据,请按照以下方式操作:
var merged = mergeData(ctx1.getImageData(), ctx2.getImageData());
ctx2.putImageData(merged, 0, 0);

显然,如果需要,您可以将结果数据放入第三个隐藏的上下文中。

关于传递到函数中的变量,我可以直接使用已注释掉的 var img = canvas.toDataURL("image/png"); 吗?还是需要在两个变量上都使用 ctx.getImageData(); - Mallander
你需要使用 getImageData(),因为 toDataURL() 返回的是一个 base64 字符串,而不是一个可操作的对象。 - EvilZebra
更新了我的回答,希望有所帮助。 - EvilZebra
感谢您更新答案,帮了我很多!我已经让您的代码工作了(至少没有错误),现在我只是想将 ctx2.putImageData(merged, 0, 0) 转换成一个 DataURL,以便我可以在我的下载函数中使用。这可行吗? - Mallander
没错!那会起作用。确保你不只是复制粘贴。getImageData()还需要x/y和width/height参数。 - EvilZebra
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接