使用HTML5 Canvas旋转上传图片后出现裁切,如何获取完整图像?
解决Canvas旋转图片后裁切/变形的问题
嘿,我完全懂你遇到的这个头疼问题——旋转后的头像要么被裁切,要么莫名其妙变成方形,核心问题其实出在两个地方:旋转后画布的尺寸没跟上图片的新尺寸,还有drawImage的坐标计算错了。我来帮你把代码改对,顺便解释清楚每个关键点:
核心问题分析
当你把图片旋转270度(也就是逆时针旋转90度)时,图片的宽高会完全互换:比如原本宽400、高600的图片,旋转后实际需要的画布尺寸应该是宽600、高400。但你原来的代码还是用了原图的宽高作为画布尺寸,这就导致一部分内容超出画布被裁切;另外drawImage的偏移参数也没对应旋转后的坐标系统,进一步加剧了裁切问题。
修改后的完整代码
function preview_image(event) { var fileReader = new FileReader(); fileReader.readAsDataURL(event.target.files[0]); fileReader.onload = function(event) { var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); var image = new Image(); image.src = event.target.result; image.onload = function() { // 关键1:旋转270度后,画布尺寸要互换(原图宽高对调) canvas.width = image.height; canvas.height = image.width; // 保存画布状态,准备变换 context.save(); // 关键2:将坐标原点移到新画布的中心 context.translate(canvas.width / 2, canvas.height / 2); // 旋转270度(转换为弧度) context.rotate(270 * Math.PI / 180); // 关键3:修正drawImage的偏移,让图片中心与画布中心对齐 // 旋转后,图片的宽高逻辑上已互换,所以偏移用-image.height/2和-image.width/2 context.drawImage(image, -image.height / 2, -image.width / 2); // 恢复画布原始状态 context.restore(); // 添加预览图到页面 $('#img_div').prepend('<img id="main_img" src="' + canvas.toDataURL("image/jpeg", 0.9) + '">'); document.getElementById("img_div").style.display = "inline-block"; document.getElementById("img_div").style.visibility = "visible"; } }; }
关键修改点详解
- 移除冗余代码:删掉了原来无意义的
context.drawImage和context.clearRect,刚绘制就清除完全没必要。 - 适配旋转后的画布尺寸:旋转270度后,图片的宽高会互换,所以把
canvas.width设为原图的高度,canvas.height设为原图的宽度,确保画布能容纳下完整的旋转后图片。 - 修正绘制坐标:旋转后坐标系统已经改变,这时候要让图片中心与画布中心对齐,偏移参数需要用
-image.height/2和-image.width/2,而不是原来的-image.width/2重复两次。 - 优化图片质量:调用
toDataURL时添加了质量参数0.9(范围0-1),避免默认生成的JPG图片质量过低。
通用扩展提示
如果以后需要支持其他旋转角度(比如90度、180度),可以参考这个逻辑:
- 旋转90/270度:画布宽高互换,调整
drawImage的偏移参数 - 旋转180度:画布尺寸不变,偏移参数还是
-image.width/2和-image.height/2,只是旋转角度改为Math.PI
这样修改后,旋转后的图片就不会再出现裁切或者变形的问题啦!
内容的提问来源于stack exchange,提问作者donm
相关产品推荐
相关产品推荐

