本文介绍了使用鼠标在画布中旋转图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的代码中,我将图像加载到画布中。然后我需要调整大小,旋转和拖动它。我设法实现了拖动和调整大小。

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 rotation(along the center of the image) using mouse on this code.

我的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>


推荐答案

以下是如何使用拖动手柄旋转图像

如果用户开始拖动旋转句柄,则mousedown事件处理程序将进行测试。

使用context.isPointInPath可以更轻松地进行命中测试(x,y)测试指定的[x,y]坐标是否在最近绘制的路径内(方便地,旋转句柄实际上是路径)。

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).

所以mousedown激活了这样的拖动句柄:

So mousedown activates the drag-handle like this:


  • 计算当前的mouseX和mouseY。

  • 重绘旋转句柄(因为isPointInPath命中测试只需要最近的路径,因此必需)

  • 如果用户在旋转手柄中单击,则设置isDown标志。

mousedown代码如下所示:

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

是的...我们可以简单地在最后测试一个圆圈旋转句柄,但使用isPointInPath将允许你绘制你想要的任何花哨的旋转句柄。

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.

并且isPointInPath有另一个好处。当旋转包含路径的上下文时,isPointInPath将为您测试旋转路径。这意味着您不必编写数学代码来取消旋转鼠标坐标以进行命中测试 - 它已经为您完成了!

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!

mousemove处理程序重绘旋转手柄指定角度的可旋转图像:


  • 如果未设置isDown标志,则返回(用户没有拖动旋转手柄。)

  • 计算当前的mouseX和mouseY。

  • 计算旋转手柄的当前角度。

  • 以当前角度重绘可旋转图像。

  • If the isDown flag is not set, just return (the user is not dragging the rotation-handle).
  • Calculate the current mouseX and mouseY.
  • Calculate the current angle of the rotation-handle.
  • Redraw the rotatable image at the current angle.

mousemove代码如下所示:

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

使用上下文的变换方法在指定的旋转处绘制图像

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

最后,mouseup和mouseout处理程序通过清除来停止拖动操作isDown标志。

function handleMouseUp(e){
  isDown=false;
}

function handleMouseOut(e){
  isDown=false;
}

这是代码和小提琴:

<!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>

这篇关于使用鼠标在画布中旋转图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 14:58