Reputation: 12534
I have a canvas element that is a set size. I would like to set a background image in the canvas that takes up the entire height and width of the canvas, but the image maintains it's aspect ratio. There will obviously be some clipping or parts of the image that aren't viewable since the aspect ratio of the image and the canvas are different. This is simple when I'm dealing with a div - I can just set background-size:cover.
How can I achieve the same effect with a canvas element, presumably using context.drawImage.
context.drawImage(image, 0, 0);
Here is a fiddle that shows what I want to happen as well as what's happening when I'm attempting to do this with css: http://jsfiddle.net/66Xfd/1/
Info on background-size:cover if required - https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
Upvotes: 0
Views: 2839
Reputation:
I created this function which at the time gave a bit of headache. But in any case does what you ask for, scales the image inside the destination rectangle proportionally to fill the whole space.
/**
* By Ken Fyrstenberg
*
* drawImageProp(context, image [, x, y, width, height [,offsetX, offsetY]])
*
* If image and context are only arguments rectangle will equal canvas
*/
function drawImageProp(ctx, img, x, y, w, h, offsetX, offsetY) {
if (arguments.length === 2) {
x = y = 0;
w = ctx.canvas.width;
h = ctx.canvas.height;
}
/// default offset is center
offsetX = offsetX ? offsetX : 0.5;
offsetY = offsetY ? offsetY : 0.5;
/// keep bounds [0.0, 1.0]
if (offsetX < 0) offsetX = 0;
if (offsetY < 0) offsetY = 0;
if (offsetX > 1) offsetX = 1;
if (offsetY > 1) offsetY = 1;
var iw = img.width,
ih = img.height,
r = Math.min(w / iw, h / ih),
nw = iw * r, /// new prop. width
nh = ih * r, /// new prop. height
cx, cy, cw, ch, ar = 1;
/// decide which gap to fill
if (nw < w) ar = w / nw;
if (nh < h) ar = h / nh;
nw *= ar;
nh *= ar;
/// calc source rectangle
cw = iw / (nw / w);
ch = ih / (nh / h);
cx = (iw - cw) * offsetX;
cy = (ih - ch) * offsetY;
/// make sure source rectangle is valid
if (cx < 0) cx = 0;
if (cy < 0) cy = 0;
if (cw > iw) cw = iw;
if (ch > ih) ch = ih;
/// fill image in dest. rectangle
ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h);
}
Upvotes: 3