3

I have 3 canvas i.e. canvasTarget, canvasTarget2, canvasTarget3 as shown below:

        var canvas = document.getElementById("canvasTarget");
        var img = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
        var canvas2 = document.getElementById("canvasTarget2");
        var img2 = canvas2.toDataURL("image/png").replace("image/png", "image/octet-stream");
        var canvas3 = document.getElementById("canvasTarget3");
        var img3 = canvas3.toDataURL("image/png").replace("image/png", "image/octet-stream");

I want to combine these canvas elements into one and download as JPEG or PDF file. I am using /html2canvas.js for downloading this. Any immediate response will be appreciated.

markE
  • 102,905
  • 11
  • 164
  • 176
  • Can you provide a [mcve]? Add HTML and populate canvas with some example images. As it stands, we have very little to go on. Also, in what way do you want to combine them? Will this help: http://stackoverflow.com/questions/6787899/combining-two-or-more-canvas-elements-with-some-sort-of-blending ? – AgataB Aug 09 '16 at 13:39

1 Answers1

9

So you've rendered your canvases, but it's not clear how you want to combine them - overlaid, side-by-side? In either case you can use Canvas.context.drawImage() to add them to a new canvas object, and then use the Canvas.toDataURL() method to return the, erm, dataURL of the new canvas.

Something like this perhaps...

/* assumes each canvas has the same dimensions */
var overlayCanvases = function(cnv1, cnv2, cnv3) {
    var newCanvas = document.createElement('canvas'),
        ctx = newCanvas.getContext('2d'),
        width = cnv1.width,
        height = cnv1.height;

    newCanvas.width = width;
    newCanvas.height = height;

    [cnv1, cnv2, cnv3].forEach(function(n) {
        ctx.beginPath();
        ctx.drawImage(n, 0, 0, width, height);
    });

    return newCanvas.toDataURL();
};

/* assumes each canvas has the same width */
var verticalCanvases = function(cnv1, cnv2, cnv3) {
    var newCanvas = document.createElement('canvas'),
        ctx = newCanvas.getContext('2d'),
        width = cnv1.width,
        height = cnv1.height + cnv2.height + cnv3.height;

    newCanvas.width = width;
    newCanvas.height = height;

    [{
        cnv: cnv1,
        y: 0
    },
    {
        cnv: cnv2,
        y: cnv1.height
    },
    {
        cnv: cnv3,
        y: cnv1.height + cnv2.height
    }].forEach(function(n) {
        ctx.beginPath();
        ctx.drawImage(n.cnv, 0, n.y, width, n.cnv.height);
    });

    return newCanvas.toDataURL();
};

/* USAGE */
var dURL1 = overlayCanvases(canvas1,canvas2,canvas3);
var dURL2 = verticalCanvases(canvas1,canvas2,canvas3);

The overlayCanvases() function will place the canvases on top of each other, so the order of the arguments is important. The verticalCanvases() will align the canvas vertically and in descending order. The important thing to notice here is that Canvas.context.drawImage() allows you to paint one canvas into another - relative positioning can be jiggled to suit your purposes.

Functions above Fiddled : https://jsfiddle.net/BnPck/cyLrmpjy/

Brian Peacock
  • 1,801
  • 16
  • 24
  • Chuckle, great minds think alike... :-) But you do need to allow for adequate width for the widest of the 3 canvases. ;-) – markE Aug 09 '16 at 17:16
  • @markE. Yeah, but the question was a little on the vague side eh? ;-) – Brian Peacock Aug 09 '16 at 17:27
  • Yep, I almost voted the question as "unclear", but they likely mean either of 2 things: 1-overlay all canvases or 2-stack all canvases so the question is unclear but self-scoping. – markE Aug 09 '16 at 17:34
  • @Mark & Brian: Apologies for not making it clear. My intention is to take download a screenshot of my aspx page. I am having multiple canvas elements in the page and i want to combine all (side by side, not overlay) into one and download it. – Mrutyunjaya Mohapatra Aug 10 '16 at 05:52
  • @MrutyunjayaMohapatra. Fair enough ... both answers will combine 3 canvases into a single canvas for export. :-) – markE Aug 10 '16 at 05:56
  • @BrianPeacock Are the lines `ctx.beginPath();` neccessary? – John Jan 06 '20 at 02:23
  • @John Not strictly necessarily with the `canvasContext.drawImage` function on its own, but it's a good habit generally that doesn't cost much. ;) – Brian Peacock Jan 11 '20 at 13:53