2013-10-07 8 views
5

私のコードでは、イメージをキャンバスにロードしています。次に、サイズを変更し、回転させてドラッグする必要があります。私は、ドラッグとサイズ変更の両方を実装することができました。マウスを使用してキャンバス内のイメージを回転するには

このコードでマウスを使用して回転(画像の中央に沿って)を実装するにはどうすればよいですか?

マイHTMLページ:

<!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; padding:10px;} 
    #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 startX; 
    var startY; 
    var isDown=false; 


    var pi2=Math.PI*2; 
    var resizerRadius=8; 
    var rr=resizerRadius*resizerRadius; 
    var draggingResizer={x:0,y:0}; 
    var imageX=50; 
    var imageY=50; 
    var imageWidth,imageHeight,imageRight,imageBottom; 
    var draggingImage=false; 
    var startX; 
    var startY; 



    var img=new Image(); 
    img.onload=function(){ 
     imageWidth=img.width; 
     imageHeight=img.height; 
     imageRight=imageX+imageWidth; 
     imageBottom=imageY+imageHeight 
     draw(true,false); 
    } 
    img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/facesSmall.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; 
      } 

      // enforce minimum dimensions of 25x25 
      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); 

     } 


    } 


    $("#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>Resize the image using the 4 draggable corner anchors</p> 
    <p>You can also drag the image</p> 
    <canvas id="canvas" width=350 height=350></canvas> 
</body> 
</html> 

答えて

15

はここでマウスダウンイベントハンドラがあれば、テストを打つ方法を画像を回転させるために、ドラッグハンドルを使用する

enter image description hereenter image description here

ですユーザーは回転ハンドルをドラッグし始めます。

このヒットテストは、指定された[x、y]座標が最後に描画されたパス内にあるかどうかをテストするcontext.isPointInPath(x、y)を使用すると簡単になります(回転ハンドルは、 )。

のでマウスダウンは、次のようにドラッグして、ハンドルを活性化:

  • 現在するmouseXとmouseYのを計算します。
  • 回転ハンドルを再描画します(isPointInPathが最新のパスだけをヒットテストするため必要です)
  • ユーザーが回転ハンドルをクリックした場合は、isDownフラグを設定します。

マウスダウンのコードは次のようになります。

function handleMouseDown(e){ 
    mouseX=parseInt(e.clientX-offsetX); 
    mouseY=parseInt(e.clientY-offsetY); 
    drawRotationHandle(false); 
    isDown=ctx.isPointInPath(mouseX,mouseY); 
} 

はい...私たちは単に回転ハンドルの端にある円をテストし、ヒットしている可能性がありますが、isPointInPathを使用すると、あなたが描くことができますどんな回転があなたの望むものであっても。

また、isPointInPathには別の利点があります。パスを含むコンテキストが回転すると、isPointInPathはの回転パスをヒットテストします。つまり、ヒットテストを行うためにマウス座標を回転させないように数学をコードする必要はありません。

のMouseMoveハンドラは回転ハンドルで指定された角度で回転可能な画像を再描画:

  • isDownフラグが設定されていない場合、単に(ユーザが回転ハンドルをドラッグしていない)を返します。
  • 現在のmouseXとmouseYを計算します。
  • 回転ハンドルの現在の角度を計算します。
  • 回転可能なイメージを現在の角度で再描画します。

のMouseMoveコードは次のようになります。

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(); 
} 

画像は、コンテキストのを使用して、指定された回転で描かれているが、方法最後に

function drawRect(){ 
    ctx.save(); 
    ctx.translate(cx,cy); 
    ctx.rotate(r); 
    ctx.drawImage(img,0,0); 
    ctx.restore(); 
} 

を変換、のmouseupとマウスアウトハンドラが停止isDownフラグをクリアしてドラッグ操作を行います。ここで

function handleMouseUp(e){ 
    isDown=false; 
} 

function handleMouseOut(e){ 
    isDown=false; 
} 

コードとフィドルです: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> 
+0

は素晴らしい答え、@markEのためにありがとう!しかし、私は小さな問題があります。私のキャンバスにはdraw()、ctx.clearRect()、キャンバスを白い空白にしてfacesSmall.pngを追加するとバックグラウンドがあります。前に描いたイメージを保つ方法は? – Davuz

+2

ようこそ。背景画像がある場合は、各clearRectの直後にイメージを描くだけです。乾杯! – markE

+0

ああ、私はそれを今得ます!それは簡単な解決策です! – Davuz

関連する問題