Below is the code I am currently using. With 0
rotation, the image is correctly scaled to fill the canvas. (similar to background-size: cover
, except u
+1 to Blindman67's answer for this to work.
I shortened the code and simplified for my use case. You should be able to just include function drawBestFit()
into your app and use it to fill any canvas with any loaded image.
For a better understanding of how this works, view Blindman67's original answer - especially the demonstration snippet at the bottom.
var canvas = document.querySelector('canvas')
var context = canvas.getContext('2d')
var image = new Image()
image.src = 'http://i.stack.imgur.com/7FsbT.jpg'
image.onload = function() {
var degrees = 0
loop()
function loop() {
degrees += .5
drawBestFit(context, degrees * Math.PI / 180, image)
requestAnimationFrame(loop)
}
function drawBestFit(ctx, angle, image) {
var dist = Math.sqrt(Math.pow(canvas.width, 2) + Math.pow(canvas.height, 2))
var diagAngle = Math.asin(canvas.height / dist)
var a1 = ((angle % (Math.PI * 2)) + Math.PI * 4) % (Math.PI * 2)
if (a1 > Math.PI)
a1 -= Math.PI
if (a1 > Math.PI / 2 && a1 <= Math.PI)
a1 = (Math.PI / 2) - (a1 - (Math.PI / 2))
var ang1 = Math.PI / 2 - diagAngle - Math.abs(a1)
var ang2 = Math.abs(diagAngle - Math.abs(a1))
var scale1 = Math.cos(ang1) * dist / image.height
var scale2 = Math.cos(ang2) * dist / image.width
var scale = Math.max(scale1, scale2)
var dx = Math.cos(angle) * scale
var dy = Math.sin(angle) * scale
ctx.setTransform(dx, dy, -dy, dx, canvas.width / 2, canvas.height / 2)
ctx.drawImage(image, -image.width / 2, -image.height / 2, image.width, image.height)
ctx.setTransform(1, 0, 0, 1, 0, 0) // reset transformations when done
}
}
<canvas width="350" height="200" style="border: solid 1px black"></canvas>