我试图旋转已经在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 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);
});
我希望这很简单:
function rotateImage() {
var rotateCanvas = document.getElementById('editorCanvas');
var rotateContext = canvas.getContext('2d');
rotateContext.rotate(90 * Math.PI / 180);
}
但我认为唯一的方法是重绘图像?
是否有任何方法可以在画布上旋转图像而不重绘它,如果不是,我将如何在画布上旋转图像?
答案 0 :(得分:2)
最简单的方法是使用“复制”复合模式将画布绘制到自身。 “复制”将在绘制新内容时清除背景:
var ctx = document.querySelector("canvas").getContext("2d");
ctx.moveTo(75, 10); // some graphics...
ctx.lineTo(30, 140);
ctx.lineTo(120, 140);
ctx.fill();
// prep canvas for next actions
ctx.translate(75, 75); // translate to canvas center
ctx.rotate(Math.PI*0.5); // add rotation transform
ctx.globalCompositeOperation = "copy"; // set comp. mode to "copy"
// rotate on each click
document.querySelector("button").onclick = function() {
// canvas uses itself as source, source region, target offset to
// compensate for translation above so it rotates around center:
ctx.drawImage(ctx.canvas, 0, 0, 150, 150, -75, -75, 150, 150);
};
body {background:#eee}
<canvas width=150></canvas>
<button>Rotate</button>
var ctx = document.querySelector("canvas").getContext("2d");
ctx.moveTo(75, 10); // some graphics...
ctx.lineTo(30, 140);
ctx.lineTo(120, 140);
ctx.fill();
// rotate on each click
document.querySelector("button").onclick = function() {
ctx.save();
// prep canvas for rotation
ctx.translate(75, 75); // translate to canvas center
ctx.rotate(Math.PI*0.5); // add rotation transform
ctx.globalCompositeOperation = "copy"; // set comp. mode to "copy"
ctx.drawImage(ctx.canvas, 0, 0, 150, 150, -75, -75, 150, 150);
ctx.restore();
};
// or use, instead of save/restore, at the end:
// ctx.setTransform(1,0,0,1,0,0);
// ctx.globalCompositeOperation = "source-over";
body {background:#eee}
<canvas width=150></canvas>
<button>Rotate</button>
答案 1 :(得分:0)
正是斯宾塞所说的,画布更像是你画的一张纸。如果你绘制一个圆圈,你不能只是旋转它,你必须擦除它然后将它绘制在新的位置。
您必须跟踪对象状态(旋转,位置,颜色等),然后使用这些状态重绘到画布。
如果您想为移动对象提供更多设置和完成的解决方案,请尝试使用ocanvas。它提供了一个处理对象而不是绘制像素的框架。它是标准画布的一步而不是复杂的。
答案 2 :(得分:0)
如果您不想存储重新创建画布所需的所有命令,则可以使用第二个内存中画布来旋转现有画布内容。
示例代码和演示:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/leftarrow.png";
function start(){
ctx.drawImage(img,cw/2-img.width/2,ch/2-img.width/2);
$('#rotate').click(function(){
rotate(cw/2,ch/2,90);
});
}
function rotate(rotationPointX,rotationPointY,degreeRotation){
// Create an second in-memory canvas:
var mCanvas=document.createElement('canvas');
mCanvas.width=canvas.width;
mCanvas.height=canvas.height;
var mctx=mCanvas.getContext('2d');
// Draw your canvas onto the second canvas
mctx.drawImage(canvas,0,0);
// Clear your main canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// Rotate the main canvas
// set the rotation point as center of the canvas
// (but you can set any rotation point you desire)
ctx.translate(rotationPointX,rotationPointY);
// rotate by 90 degrees (==PI/2)
var radians=degreeRotation/180*Math.PI;
ctx.rotate(radians);
// Draw the second canvas back to the (now rotated) main canvas:
ctx.drawImage(mCanvas,-canvas.width/2,-canvas.height/2);
// clean up -- unrotate and untranslate
ctx.rotate(-radians);
ctx.translate(-canvas.width/2,-canvas.height/2);
}
&#13;
body{ background-color: ivory; }
#canvas{border:1px solid red;}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=rotate>Rotate the existing image.</button>
<br>
<canvas id="canvas" width=300 height=300></canvas>
&#13;
[在提问者代码中添加rotate()]
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);
}
img.src='https://dl.dropboxusercontent.com/u/139992952/multple/leftarrow.png';
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);
});
function rotate(rotationPointX,rotationPointY,degreeRotation){
// Create an second in-memory canvas:
var mCanvas=document.createElement('canvas');
mCanvas.width=canvas.width;
mCanvas.height=canvas.height;
var mctx=mCanvas.getContext('2d');
// Draw your canvas onto the second canvas
mctx.drawImage(canvas,0,0);
// Clear your main canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// Rotate the main canvas
// set the rotation point as center of the canvas
// (but you can set any rotation point you desire)
ctx.translate(rotationPointX,rotationPointY);
// rotate by 90 degrees (==PI/2)
var radians=degreeRotation/180*Math.PI;
ctx.rotate(radians);
// Draw the second canvas back to the (now rotated) main canvas:
ctx.drawImage(mCanvas,-canvas.width/2,-canvas.height/2);
// clean up -- unrotate and untranslate
ctx.rotate(-radians);
ctx.translate(-canvas.width/2,-canvas.height/2);
}
$('#rotate').click(function(){
rotate(canvas.width/2,canvas.height/2,90);
});
&#13;
body{ background-color: ivory; }
canvas{border:1px solid red;}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=rotate>Rotate</button>
<br>
<canvas id="editorCanvas" width=300 height=300></canvas>
&#13;