In my code I am loading an image in to a canvas. Then I need to resize, rotate and drag it. I managed to implement both dragging and resizing.
How can I implement ro
Here’s how to use a drag-handle to rotate an image
The mousedown event handler hit-tests if the user is starting to drag the rotation-handle.
This hit-testing is made easier with context.isPointInPath(x,y) which tests whether a specified [x,y] coordinate is inside the most recently drawn path (Conveniently, the rotation-handle is actually a path).
So mousedown activates the drag-handle like this:
The mousedown code looks like this:
function handleMouseDown(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
drawRotationHandle(false);
isDown=ctx.isPointInPath(mouseX,mouseY);
}
Yes...we could have simply hit-tested a circle on the end of the rotation-handle, but using isPointInPath will allow you to draw whatever fancy rotation handle you desire.
And isPointInPath has another nice benefit. When the context containing the path is rotated, isPointInPath will hit-test the rotated path for you. This means you don't have to code the math to unrotate the mouse coordinates to do the hit testing--it's done for you!
The mousemove handler redraws the rotatable image at the angle specified by the rotation-handle:
The mousemove code looks like this:
function handleMouseMove(e){
if(!isDown){return;}
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
var dx=mouseX-cx;
var dy=mouseY-cy;
r=Math.atan2(dy,dx);
draw();
}
The image is drawn at the specified rotation using context's transform methods
function drawRect(){
ctx.save();
ctx.translate(cx,cy);
ctx.rotate(r);
ctx.drawImage(img,0,0);
ctx.restore();
}
Finally, the mouseup and mouseout handlers stop the drag operation by clearing the isDown flag.
function handleMouseUp(e){
isDown=false;
}
function handleMouseOut(e){
isDown=false;
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/QqwKR/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var isDown=false;
var cx=canvas.width/2;
var cy=canvas.height/2;
var w;
var h;
var r=0;
var img=new Image();
img.onload=function(){
w=img.width/2;
h=img.height/2;
draw();
}
img.src="facesSmall.png";
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
drawRotationHandle(true);
drawRect();
}
function drawRect(){
ctx.save();
ctx.translate(cx,cy);
ctx.rotate(r);
ctx.drawImage(img,0,0,img.width,img.height,-w/2,-h/2,w,h);
ctx.restore();
}
function drawRotationHandle(withFill){
ctx.save();
ctx.translate(cx,cy);
ctx.rotate(r);
ctx.beginPath();
ctx.moveTo(0,-1);
ctx.lineTo(w/2+20,-1);
ctx.lineTo(w/2+20,-7);
ctx.lineTo(w/2+30,-7);
ctx.lineTo(w/2+30,7);
ctx.lineTo(w/2+20,7);
ctx.lineTo(w/2+20,1);
ctx.lineTo(0,1);
ctx.closePath();
if(withFill){
ctx.fillStyle="blue";
ctx.fill();
}
ctx.restore();
}
function handleMouseDown(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
drawRotationHandle(false);
isDown=ctx.isPointInPath(mouseX,mouseY);
console.log(isDown);
}
function handleMouseUp(e){
isDown=false;
}
function handleMouseOut(e){
isDown=false;
}
function handleMouseMove(e){
if(!isDown){return;}
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
var dx=mouseX-cx;
var dy=mouseY-cy;
r=Math.atan2(dy,dx);
draw();
}
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUp(e);});
$("#canvas").mouseout(function(e){handleMouseOut(e);});
}); // end $(function(){});
</script>
</head>
<body>
<p>Rotate by dragging blue rotation handle</p>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>