[英]canvas rotates of 180 degrees instead of 90 when I use context.rotate
更新 - 第二部分
我注意到在旋转图像之前执行 ajax 调用时会出现问题。
我这样做:
$.ajax({
type:'POST',
beforeSend: function(request) {
request.setRequestHeader("Authorization", "Bearer {{ app('request')->token }}");
},
url: "my-url-to-rotate-image-on-server/90",
success:function(data) {
$('#my_id').rotate(90); // the rotate function is the code I wrote below
},
error: function(data) { }
});
如果我删除 ajax 调用并只旋转图像,它就可以工作。
我需要将图像旋转 90 度,但图像旋转了 180 度。
这是我在网上找到的代码(一个 jquery 插件),我使用:
var p = this.get(0);
p.angle = 90;
if (p.angle >= 0) {
var rotation = Math.PI * p.angle / 180;
} else {
var rotation = Math.PI * (360+p.angle) / 180;
}
var costheta = Math.cos(rotation);
var sintheta = Math.sin(rotation);
var canvas = document.createElement('canvas');
var onLoad = false;
if (!p.oImage) {
canvas.oImage = new Image();
canvas.oImage.src = p.src;
canvas.oImage.width = p.width;
canvas.oImage.height = p.height;
onLoad = true;
} else {
canvas.oImage = p.oImage;
}
canvas.style.width = canvas.width = Math.abs(costheta*canvas.oImage.width) + Math.abs(sintheta*canvas.oImage.height);
canvas.style.height = canvas.height = Math.abs(costheta*canvas.oImage.height) + Math.abs(sintheta*canvas.oImage.width);
var context = canvas.getContext('2d');
context.save();
if (rotation <= Math.PI/2) {
context.translate(sintheta*canvas.oImage.height,0);
} else if (rotation <= Math.PI) {
context.translate(canvas.width,-costheta*canvas.oImage.height);
} else if (rotation <= 1.5*Math.PI) {
context.translate(-costheta*canvas.oImage.width,canvas.height);
} else {
context.translate(0,-sintheta*canvas.oImage.width);
}
context.rotate(rotation);
if (onLoad) {
canvas.oImage.onload = function() {
context.drawImage(canvas.oImage, 0, 0, canvas.oImage.width, canvas.oImage.height);
context.restore();
};
} else {
context.drawImage(canvas.oImage, 0, 0, canvas.oImage.width, canvas.oImage.height);
context.restore();
}
我得到的是画布尺寸正确旋转(我的意思是,旧宽度变成新高度,反之亦然),但图像旋转了 180 度而不是 90 度。
我不知道如何调试它。
更新
我注意到当图像 src 是 http url 时会发生奇怪的行为。
如果图像 src 是 blob,则代码完美运行。
window.addEventListener('load', onDocLoaded, false); function onDocLoaded(evt) { let img = document.querySelector('img'); let width = img.naturalWidth, height=img.naturalHeight; let canvas = document.createElement('canvas'); canvas.width = height; canvas.height = width; let ctx = canvas.getContext('2d'); ctx.rotate(Math.PI/2); ctx.translate(0,-height); ctx.drawImage(img,0,0); document.body.appendChild(canvas); }
body { background-color: #333; }
<img id='theImage' src='https://i.stack.imgur.com/Zqh6Am.png'/>
使用 cos(0)、sin(0) 而不是北时,0 度指向东,这就是为什么您认为这在实际上正确时不起作用。
当您向东添加 90 度时,它正确地指向南,给人的印象是它旋转了 180 度。
如果您希望 0 度指向北。 我们知道它是 90 度,然后将角度减去 90 度。
你在哪里
p.angle = 90;
用。。。来代替...
const POINT_NORTH = -90;
p.angle = POINT_NORTH + 90;
您从网上获取的代码(应该带有参考/归属)是非常古老的学校(至少 5 岁)。 最重要的是,代码质量很差。
请注意,2d 上下文translate
、 scale
、 rotate
和transform
是累积的。 如果你调用ctx.rotate(Math.PI/2)
(90 deg) 然后再次调用它ctx.rotate(Math.PI/2)
你实际上已经旋转了Math.PI
(180 deg)。 但是,代码每次都会创建一个新画布,因此这不会导致双重旋转。 为什么会发生这种情况在代码中并不明显。
画布上的旋转是顺时针方向。 0 度是在 3 点钟。
分离关注点并使用现代 JS。 加载图像和显示图像应该是单独的功能
首先是一个旋转图像并适合画布的函数
// Rotates image 90 and sets canvas size to fit rotated image
function drawImageRot90(ctx, image) {
ctx.canvas.style.width = (ctx.canvas.width = image.height) + "px";
ctx.canvas.style.height = (ctx.canvas.height = image.width) + "px";
ctx.setTransform(0, 1, -1, 0, ctx.canvas.width, 0); // overwrite existing transform
ctx.drawImage(image, 0, 0);
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset default transform
}
然后是加载图像的函数。 该函数返回一个承诺,该承诺将在加载时传递图像。
// Return promise to provide loaded image as described in details AKA `p`
function loadImage(details) {
return new Promise(loaded => {
if (!details.oImage) {
const img = new Image;
img.src = details.src
img.addEventListener("load",() => {
img.width = details.width;
img.height = details.height;
loaded(img);
}, {once: true}
);
} else {
loaded(details.oImage);
}
});
}
把它放在一起
loadImage(this.get(0))
.then((img) => {
const canvas = document.createElement("canvas");
drawImageRot90(canvas.getContext("2d"), img);
})
以 90 为步长旋转的功能
function drawImageRot(ang, ctx, image) { // ang must be 0, 90, 180, 270 or will default 180
if (ang === 90 || ang === 270) {
ctx.canvas.style.width = (ctx.canvas.width = image.height) + "px";
ctx.canvas.style.height = (ctx.canvas.height = image.width) + "px";
if (ang === 90) { ctx.setTransform(0, 1, -1, 0, ctx.canvas.width, 0) }
else { ctx.setTransform(0, -1, 1, 0, 0, ctx.canvas.height) }
} else {
ctx.canvas.style.width = (ctx.canvas.width = image.width) + "px";
ctx.canvas.style.height = (ctx.canvas.height = image.height) + "px";
if (ang === 0) { ctx.setTransform(1, 0, 0, 1, 0, 0) }
else { ctx.setTransform(-1, 0, 0, -1, ctx.canvas.width, ctx.canvas.height) }
}
ctx.drawImage(image, 0, 0);
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset default transform
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.