2013-10-07 4 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

Обработчик MouseDown событие хитовых тесты, если пользователь начинает перетаскивать ручку вращения.

Это тестовое тестирование облегчается с помощью context.isPointInPath (x, y), который проверяет, установлена ​​ли указанная координата [x, y] в самом последнем рисованном пути (удобно, что handle-handle фактически является путем).

Так MouseDown активирует перетащить обрабатывать как это:

  • Вычислить текущий mouseX и мышиный.
  • Перерисовать ручку вращения (требуется, потому что isPointInPath hit-tests только последний путь)
  • Установите флаг isDown, если пользователь нажал на ручку вращения.

Код MouseDown выглядит следующим образом:

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 и MouseOut обработчики остановки операцию перетаскивания, очистив флаг isDown.

function handleMouseUp(e){ 
    isDown=false; 
} 

function handleMouseOut(e){ 
    isDown=false; 
} 

Вот код и 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> 
+0

Спасибо за удивительный ответ, @markE! Но у меня небольшая проблема. У моего холста есть фон (нарисовано изображение на нем), когда я добавляю «facesSmall.png» с помощью 'draw()', 'ctx.clearRect()' сделать canvas белым пустым. Как сохранить изображение, которое я нарисовал раньше? – Davuz

+2

Добро пожаловать. Если у вас есть фоновое изображение, просто drawImage это изображение сразу после каждого clearRect. Ура! – markE

+0

О, я понял! Это простое решение! – Davuz

Смежные вопросы