Javascript 在画布上旋转现有图像
我尝试旋转已在HTML画布上绘制的图像,如下所示:Javascript 在画布上旋转现有图像,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,我尝试旋转已在HTML画布上绘制的图像,如下所示: var canvas = document.getElementById("editorCanvas"); var ctx = canvas.getContext("2d"); var canvasOffset = $("#editorCanvas").offset(); var offsetX = canvasOffset.left; var offsetY = canvasOffset.top; var startX; var star
var canvas = document.getElementById("editorCanvas");
var ctx = canvas.getContext("2d");
var canvasOffset = $("#editorCanvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var startX;
var startY;
var isDown = false;
var pi2 = Math.PI * 2;
var resizerRadius = 4;
var rr = resizerRadius * resizerRadius;
var draggingResizer = {
x: 0,
y: 0
};
var imageX = 0;
var imageY;
var imageWidth, imageHeight, imageRight, imageBottom;
var draggingImage = false;
var startX;
var startY;
var img = new Image();
img.crossOrigin='anonymous';
img.onload = function () {
var ratio = img.width / img.height;
imageWidth = 71;
imageHeight = imageWidth / ratio;
imageY = (245-imageHeight)/2;
if (imageHeight > 245) {
imageHeight = 245;
imageWidth = imageHeight * ratio;
imageY = 0;
}
imageX = ((canvas.width-imageWidth)/2);
imageY = ((canvas.height-imageHeight)/2);
imageRight = imageX + imageWidth;
imageBottom = imageY + imageHeight;
draw(true, false);
}
function draw(withAnchors, withBorders) {
// clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw the image
ctx.drawImage(img, 0, 0, img.width, img.height, imageX, imageY, imageWidth, imageHeight);
// optionally draw the draggable anchors
if (withAnchors) {
drawDragAnchor(imageX, imageY);
drawDragAnchor(imageRight, imageY);
drawDragAnchor(imageRight, imageBottom);
drawDragAnchor(imageX, imageBottom);
}
// optionally draw the connecting anchor lines
if (withBorders) {
ctx.beginPath();
ctx.moveTo(imageX, imageY);
ctx.lineTo(imageRight, imageY);
ctx.lineTo(imageRight, imageBottom);
ctx.lineTo(imageX, imageBottom);
ctx.closePath();
ctx.stroke();
}
}
function drawDragAnchor(x, y) {
ctx.beginPath();
ctx.arc(x, y, resizerRadius, 0, pi2, false);
ctx.closePath();
ctx.fill();
}
function anchorHitTest(x, y) {
var dx, dy;
// top-left
dx = x - imageX;
dy = y - imageY;
if (dx * dx + dy * dy <= rr) {
return (0);
}
// top-right
dx = x - imageRight;
dy = y - imageY;
if (dx * dx + dy * dy <= rr) {
return (1);
}
// bottom-right
dx = x - imageRight;
dy = y - imageBottom;
if (dx * dx + dy * dy <= rr) {
return (2);
}
// bottom-left
dx = x - imageX;
dy = y - imageBottom;
if (dx * dx + dy * dy <= rr) {
return (3);
}
return (-1);
}
function hitImage(x, y) {
return (x > imageX && x < imageX + imageWidth && y > imageY && y < imageY + imageHeight);
}
function handleMouseDown(e) {
startX = parseInt(e.clientX - offsetX);
startY = parseInt(e.clientY - offsetY);
draggingResizer = anchorHitTest(startX, startY);
draggingImage = draggingResizer < 0 && hitImage(startX, startY);
}
function handleMouseUp(e) {
draggingResizer = -1;
draggingImage = false;
draw(true, false);
}
function handleMouseOut(e) {
handleMouseUp(e);
}
function handleMouseMove(e) {
if (draggingResizer > -1) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// resize the image
switch (draggingResizer) {
case 0:
//top-left
imageX = mouseX;
imageWidth = imageRight - mouseX;
imageY = mouseY;
imageHeight = imageBottom - mouseY;
break;
case 1:
//top-right
imageY = mouseY;
imageWidth = mouseX - imageX;
imageHeight = imageBottom - mouseY;
break;
case 2:
//bottom-right
imageWidth = mouseX - imageX;
imageHeight = mouseY - imageY;
break;
case 3:
//bottom-left
imageX = mouseX;
imageWidth = imageRight - mouseX;
imageHeight = mouseY - imageY;
break;
}
if(imageWidth<25){imageWidth=25;}
if(imageHeight<25){imageHeight=25;}
// set the image right and bottom
imageRight = imageX + imageWidth;
imageBottom = imageY + imageHeight;
// redraw the image with resizing anchors
draw(true, true);
} else if (draggingImage) {
imageClick = false;
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// move the image by the amount of the latest drag
var dx = mouseX - startX;
var dy = mouseY - startY;
imageX += dx;
imageY += dy;
imageRight += dx;
imageBottom += dy;
// reset the startXY for next time
startX = mouseX;
startY = mouseY;
// redraw the image with border
draw(false, true);
}
}
$("#editorCanvas").mousedown(function (e) {
handleMouseDown(e);
});
$("#editorCanvas").mousemove(function (e) {
handleMouseMove(e);
});
$("#editorCanvas").mouseup(function (e) {
handleMouseUp(e);
});
$("#editorCanvas").mouseout(function (e) {
handleMouseOut(e);
});
但我认为唯一的办法是通过重画图像
有没有办法在画布上旋转图像而不重新绘制它,如果没有,我该如何在画布上旋转图像?正是斯宾塞所说的,画布更像是你在上面绘制的一张纸。如果你画一个圆,你不能只是旋转它,你必须擦除它,然后在它的新位置画它 您必须跟踪对象状态(旋转、位置、颜色等),然后使用这些状态重新绘制画布
如果您想为移动对象提供一个更完善的解决方案,请尝试使用。它提供了一个处理对象而不是绘制像素的框架。这是从标准画布向上的一个步骤,而不会变得复杂。如果不想存储重新创建画布所需的所有命令,可以使用第二个内存画布来旋转现有画布内容
- 创建第二个内存画布
- 将主画布复制到第二个画布上
- 清理主画布
- 将旋转点设置为主画布的中心
- (但可以设置所需的任何旋转点)
- 旋转90度(=π/2)
- 将第二个画布重新绘制回(现在已旋转)主画布
- 清理--取消旋转并取消转换主画布
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var cw=画布宽度;
var ch=画布高度;
var img=新图像();
img.onload=启动;
img.src=”https://dl.dropboxusercontent.com/u/139992952/multple/leftarrow.png";
函数start(){
ctx.drawImage(图像,cw/2-img.width/2,ch/2-img.width/2);
$(“#旋转”)。单击(函数(){
旋转(cw/2,ch/2,90);
});
}
函数旋转(rotationPointX、rotationPointY、degreeRotation){
//创建第二个内存画布:
var mCanvas=document.createElement('canvas');
mCanvas.width=canvas.width;
mCanvas.height=canvas.height;
var mctx=mCanvas.getContext('2d');
//将画布绘制到第二个画布上
mctx.drawImage(画布,0,0);
//清除主画布
clearRect(0,0,canvas.width,canvas.height);
//旋转主画布
//将旋转点设置为画布的中心
//(但可以设置所需的任何旋转点)
平移(旋转点x,旋转点y);
//旋转90度(=π/2)
var弧度=脱脂/180*Math.PI;
ctx.旋转(弧度);
//将第二个画布绘制回(现在已旋转)主画布:
ctx.drawImage(mCanvas,-canvas.width/2,-canvas.height/2);
//清理-不旋转和不转换
ctx.旋转(-弧度);
ctx.translate(-canvas.width/2,-canvas.height/2);
}
body{背景色:象牙;}
#画布{边框:1px纯红;}
旋转现有图像。
最简单的方法是使用“复制”复合模式绘制画布。“复制”将在绘制新内容时清除背景:
例子
var ctx=document.querySelector(“canvas”).getContext(“2d”);
ctx.moveTo(75,10);//一些图形。。。
ctx.lineTo(30140);
ctx.lineTo(120140);
ctx.fill();
//为下一步操作准备画布
ctx.translate(75,75);//转换到画布中心
ctx.旋转(数学PI*0.5);//添加旋转变换
ctx.globalCompositeOperation=“复制”//设置补偿。“复制”模式
//每次单击时旋转
document.querySelector(“按钮”).onclick=function(){
//画布将自身用作源、源区域和目标偏移量
//补偿上面的平移,使其围绕中心旋转:
drawImage(ctx.canvas,0,0,150,150,-75,75,150,150);
};代码>
body{background:#eee}
旋转
图像只是在画布上绘制,而不是“附加”到画布上。因此,如果你想改变它,移动或旋转,你需要擦除画布并重新绘制。您可以不重新绘制,但您将看到未擦除的旧图像的位置,旋转后的图像位于顶部。感谢您的回答,同时我可以看到它在示例中工作,以及当我复制代码行时。但是,当我试图将其集成到上面的代码中时,它要么不起作用,要么只是导致画布上的图像被隐藏。有什么提示吗?@AlexSaidani刚刚重置了转换和合成模式。简单的方法是在应用任何恢复之前使用ctx.save(),完成后使用restore()。或者,使用setTransform(1,0,0,1,0,0)手动重置,并将补偿模式设置回“源代码结束”。上面显示的设置步骤可以移动到按钮处理程序内部。@Alexaidani添加了第二个示例,如下所示:感谢您的回答,同时我可以看到它在示例中起作用,并且当我将代码行复制到下一行时。但是,当我试图将其集成到上面的代码中时,它要么不起作用,要么只是导致画布上的图像被隐藏。有什么提示吗?你没有设置任何img.src,所以你的代码不会显示任何图像!在我添加了一个图像源之后,我的答案中的旋转函数确实会旋转您的图像(请参见添加到答案)。但是,请注意,draw()函数会重新绘制原始图像并在不旋转的情况下定位。这将撤消旋转效果,因此您必须调整这些处理程序以绘制图像&锚定为零旋转,而不是新的旋转。我建议保存当前的旋转角度,并将您的drawImage和drawAnchors包装在适当的平移/旋转中,以便它们以新的角度绘制。回到这里,感谢您提供详细的答案。不过我还是没能让它正常工作。它现在会旋转,但正如您所提到的,draw函数会将图像重置回其原始角度。你知道如何在不重置它的情况下让它工作吗?
function rotateImage() {
var rotateCanvas = document.getElementById('editorCanvas');
var rotateContext = canvas.getContext('2d');
rotateContext.rotate(90 * Math.PI / 180);
}