How do I extract a portion of an image in canvas and use it as background image for a div?
Asked Answered
S

1

7

This is how my code looks:

document.addEventListener('DOMContentLoaded', function () {
        var canvas = document.querySelector('canvas');
        var ctx = canvas.getContext("2d");
        var imageData = ctx.getImageData(0, 0, 300, 300);
        var tile = {
                        'id': 1,
                        'data': imageData,
                        'dataUrl': imageData.toDataUrl()
                    };
        var div = document.createElement('div');
                div.classList.add('tile');
                grid.appendChild(div);
                div.style.backgroundImage = ('url(' + tile.dataUrl + ')');
});

I'm trying to extract portion of the image on canvas, from (0,0) with height and width 300px, and convert that imageData object into a dataUrl to be used as a background of a div.

I get an error: imageData.toDataUrl() is not a function. How can I achieve this?

Thanks in advance!

Silvana answered 27/1, 2016 at 9:26 Comment(0)
A
20

toDataURL is an HTMLCanvasElement method you have to call it from the canvas element itself.

You could draw back your resulted imageData to the canvas after you changed its size to the wanted one, but the easiest solution is to use a second, off-screen canvas, where you will draw the first canvas thanks to the context.drawImage method:

// The crop function
var crop = function(canvas, offsetX, offsetY, width, height, callback) {
  // create an in-memory canvas
  var buffer = document.createElement('canvas');
  var b_ctx = buffer.getContext('2d');
  // set its width/height to the required ones
  buffer.width = width;
  buffer.height = height;
  // draw the main canvas on our buffer one
  // drawImage(source, source_X, source_Y, source_Width, source_Height, 
  //  dest_X, dest_Y, dest_Width, dest_Height)
  b_ctx.drawImage(canvas, offsetX, offsetY, width, height,
                  0, 0, buffer.width, buffer.height);
  // now call the callback with the dataURL of our buffer canvas
  callback(buffer.toDataURL());
};


// #main canvas Part

var canvas = document.getElementById('main');
var img = new Image();
img.crossOrigin = "Anonymous";

img.onload = function() {
  canvas.width = this.width;
  canvas.height = this.height;
  canvas.getContext('2d').drawImage(this, 0, 0);
  // set a little timeout before calling our cropping thing
  setTimeout(function() {
    crop(canvas, 100, 70, 70, 70, callback)
  }, 1000);
};

img.src = "https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png";

// what to do with the dataURL of our cropped image
var callback = function(dataURL) {
  document.body.style.backgroundImage = 'url(' + dataURL + ')';
}
<canvas id="main" width="284" width="383"></canvas>
Anisometropia answered 27/1, 2016 at 9:38 Comment(4)
My requirement is that the target must be a div element. I cannot over-write the source canvas as well. Is there a way to extract a portion of the image on source canvas into the destination div? Thanks!Silvana
Here I used the <body> element has a target, you can change it to whatever element you want (even the main canvas) or a <div> (check the callback function at the end of my snippet.Anisometropia
Oops! I guess I missed to see that. I think this will work. I'll wait to see if I get an answer that avoids the buffer canvas, if not, I'll accept your answer. Thanks!Silvana
Well in my answer you also have the way to do it without the buffer canvas (basically : resize your canvas to the cropped size, then putImageData(yourImageData, 0,0) then canvas.toDataURL(), but this is heavier for the cpu than a buffer canvas, that's why I only wrote to you the best of the two solutions. ( getImageData and putImageData are really slow, and if you need to keep your original canvas as it was before, you'll have to call twice these two methods...)Anisometropia

© 2022 - 2024 — McMap. All rights reserved.