我们不需要任何canvas.width/2-image.width/2 代码,因此只需使用ctx.drawImage(image,0,0, canvas.width, canvas.height) 将您的onload 更改为。除此之外,您还可以定义一个全局 ratio 变量,当您横向旋转并需要向上缩放时,该变量将用于正确缩放:
var ratio = 1;
image.onload=function(){
canvas.width = 100;
canvas.height = 150;
ratio = canvas.height/canvas.width; // We will use this for scaling the image to fit
ctx.drawImage(image,0,0, canvas.width, canvas.height);
}
现在按中心旋转图像的最佳方法是将图像中心转换为画布的(0,0) 点。然后您可以旋转并将其移回原来的位置。这是因为当应用旋转时,画布(0,0) 点就是旋转点。
function drawRotated(degrees){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(canvas.width/2,canvas.height/2); // Move image center to 0,0
ctx.rotate(degrees*Math.PI/180); // Rotate will go from center
ctx.translate(-canvas.width/2,-canvas.height/2); // Move image back to normal spot
ctx.drawImage(image,0,0, canvas.width, canvas.height)
ctx.restore();
}
到目前为止,正常和 180 度图像看起来都很好。但是横向的需要向上缩放,为此添加一些逻辑来检测图像是向左还是向右翻转,然后通过ratio 变量进行缩放(1.5 在这种情况下 em>)。
function drawRotated(degrees){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(canvas.width/2,canvas.height/2);
ctx.rotate(degrees*Math.PI/180);
if((degrees - 90) % 180 == 0) // Is the image sideways?
ctx.scale(ratio, ratio); // Scale it up to fill the canvas
ctx.translate(-canvas.width/2,-canvas.height/2);
ctx.drawImage(image,0,0, canvas.width, canvas.height)
ctx.restore();
}
Updated Fiddle
更新:
水平图像看起来很奇怪的原因有两个。目前,缩放假定图像在横向时需要放大,以防逻辑翻转的水平图像。相反,我们希望在正常翻转或倒置时放大:
function drawRotated(degrees) {
ctx.clearRect(0,0,canvas.width,canvas.height);
...
if(imgRatio < 1) angleToScale += 90
if(angleToScale % 180 == 0)
ctx.scale(ratio, ratio);
ctx.translate(-canvas.width/2,-canvas.height/2);
...
}
这里我们根据imgRatio < 1 来确定我们是否会声称图像是水平的。否则它将是垂直的。虽然这在声称垂直与水平方面有点宽泛,但假设我们只有垂直或水平图像,它就可以达到目的。
即使在进行了这些更改之后,仍然存在一些问题 (see this fiddle)。这是因为当我们绘制图像时,我们会将其拟合到垂直的画布上,导致图像在绘制到画布上时会拉伸。
这可以通过更改我们绘制图像目标的位置来解决。对于水平图像,我们希望将其水平绘制:
注意一点是对onload 方法的一些更改:
var ratio = 0;
var xImgOffset = 0;
var yImgOffset = 0;
image.onload=function(){
canvas.width = 100;
canvas.height = 150;
ratio = canvas.height/canvas.width;
var imgRatio = image.height/image.width;
if(imgRatio < 1) { // Horizonal images set Height then proportionally scale width
var dimDiff = image.height/canvas.width;
image.height = canvas.width; // This keeps in mind that the image
image.width = image.width / dimDiff; // is rotated, which is why width is used
} else { // Verticle images set Height then proportionally scale height
var dimDiff = image.width/canvas.width;
image.width = canvas.width;
image.height = image.height / dimDiff;
}
xImgOffset = -(image.width - canvas.width) / 2;
yImgOffset = -(image.height - canvas.height) / 2;
drawRotated(0);
}
立即调用drawRotated 方法以应用缩放更改。除了 xImgOffset 和 yImgOffset 之外,还有与原始图像尺寸成比例的水平和垂直画布尺寸的起始位置之间的位置差异。
视觉上看起来像这样:
在上图中,我们需要在画布中绘制水平图像作为绿色水平矩形。对于垂直图像,图像的宽度设置为画布宽度,高度与偏移成比例缩放,因此图像居中。同样,这对于水平图像也是如此,我们只需要记住,我们正在绘制它,就好像画布最初是水平的(参见第一张图)。
最后整个方法是这样的:
function drawRotated(degrees){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(canvas.width/2,canvas.height/2);
ctx.rotate(degrees*Math.PI/180);
var angleToScale = degrees - 90;
var imgRatio = image.height/image.width;
if(imgRatio < 1) angleToScale += 90
if(angleToScale % 180 == 0)
ctx.scale(ratio, ratio);
ctx.translate(-canvas.width/2,-canvas.height/2);
ctx.drawImage(image, xImgOffset, yImgOffset, image.width, image.height);
ctx.restore();
}
Updated Fiddle For both horizontal and vertical images with original image ratio and cropping
此设置适用于任何画布尺寸和大小。