canvas實現鼠標拖拽矩形移動改變大小

項目的一個新需求,動態生成矩形框,鼠標點擊拖動改變矩形框的位置,並能夠調整大小。html

以前作過一個小demo,需求相似,可是在canvas內只有一個矩形框,拖動移動,當時記得是用isPointInPath()直接判斷鼠標是否點在了矩形框之內。新需求的矩形框個數爲n,通過測試,isPointinPath實現過程當中有bug,並不能精準定位到具體點擊到canvas的某一個矩形框。通過一系列的頭腦風暴,纔想出了解決辦法,才發現原來是最簡單的方法,可是在思考的當初就被pass了,見代碼:canvas

html:

<body>
  <canvas id="canvas" width="400" height="300">
  </canvas>
</body>

小demo,不作其餘修飾,直接寫邏輯吧。數組

js:

第一步,建立一個容器,以保存Canvas內繪製的元素點。Canvas是一種非保留性的繪圖界面,即不會記錄過去執行的繪圖操做,而是保持最終結果(構成圖像的彩色像素)。dom

若是想讓Canvas變得具備交互性,好比用戶能夠選擇、拖動畫布上的圖形。那麼咱們必須記錄繪製的每個對象,才能在未來靈活的修改並重繪它們,實現交互。

 

 1     // canvas 矩形框集合
 2     var rects=[];
 3      function rectar(x,y,width,height){
 4             this.x = x;
 5             this.y = y;
 6             this.width = width;
 7             this.height = height;
 8             this.isSelected = false;
 9         };

繪製矩形框:

 1 function drawRect() {
 2       // 清除畫布,準備繪製
 3       context.clearRect(0, 0, canvas.width, canvas.height);
 4 
 5       // 遍歷全部矩形框
 6       for(var i=0; i<rects.length; i++) {
 7         var rect = rects[i];
 8 
 9         // 繪製矩形
10         context.strokeStyle="#FF0000";
11         context.strokeRect(rect.x,rect.y,rect.width,rect.height,rect.color);
12 
13         if (rect.isSelected) {
14           context.lineWidth = 50;
15         }
16         else {
17           context.lineWidth = 10;
18         }
19       }
20     }

這是一個繪製函數,由於在Canvas的全部操做,所有都是從新繪製的(先清除,在繪製),每次程序刷新畫布時,會先使用 clearRect() 方法清除畫布上的全部內容。但不用小心這樣會形成畫布閃爍,即畫布上的圓圈一會兒所有消失,而後一會兒又從新出現。由於Canvas針對這個問題進行了優化,會在全部繪圖邏輯執行完畢後才清除或繪製全部內容,保證最終結果的流暢。而後遍歷矩形數組 其中的x,y,width,height來畫矩形。函數

*這裏個人項目是根據病變位置動態生成的矩形框,每一次生成矩形框,都要把它的位置信息添加到數組中,這裏就直接建立矩形框了,能夠根據本身需求改造測試

 1 function addRandomRect() {
 2      var x=10;
 3      var y=10;
 4      var width=100;
 5      var height=100;
 6       // 建立一個新的矩形對象
 7       var rect=new rectar(x,y,width,height);
 8 
 9       // 把它保存在數組中
10       rects.push(rect);
11       // 從新繪製畫布
12      drawRect();
13  };

 *Canvas點擊事件

 

 1     var SelectedRect;
 2     var x1;
 3     var y1;
 4     var right=false;
 5     var widthstart,widthend;
 6     var heightstart,heightend;
 7 
 8 function canvasClick(e) {
 9       // 取得畫布上被單擊的點
10       var clickX = e.pageX - canvas.offsetLeft;
11       var clickY = e.pageY - canvas.offsetTop;
12 
13       // 查找被單擊的矩形框
14       for(var i=rects.length-1; i>=0; i--) {
15         var rect = rects[i];
16 
17             widthstart=rect.x;
18             widthend=rect.x+rect.width;
19 
20             heightstart=rect.y;
21             heightend=rect.y+rect.height;
22 
23         // 判斷這個點是否在矩形框中
24         if ((clickX>=widthstart&&clickX<(widthend-20))&&(clickY>=heightstart)&&(clickY<(heightend-20))) {
25           console.log(clickX);
26           // 清除以前選擇的矩形框
27           if (SelectedRect != null) SelectedRect.isSelected = false;
28           SelectedRect = rect;
29           x1=clickX-SelectedRect.x;
30           y1=clickY-SelectedRect.y;
31           //選擇新圓圈
32           rect.isSelected = true;
33 
34           // 使圓圈容許拖拽
35           isDragging = true;
36 
37           //更新顯示
38           drawRect();
39           //中止搜索
40           return;
41         };
42         /*
43           設置拉伸的界限。
44           */
45        // if ((clickX>=(widthend-20))&&(clickY>=(heightend-20)))
46        // {
47        //   SelectedRect = rect;
48        //  right=true;
49        //  }
//18-02-01改
            if ((clickX>=(widthend-20)&&((clickX<=(widthend+20)))&&(clickY>=(heightend-20))&&(clickY>=(heightend+20))) 
{
SelectedRect = rect;
right=true;
}
50   } 

51 }

 代碼中23行爲判斷具體點擊哪一個元素的語句,其實很簡單,當初繞了好久,很簡單直接判斷鼠標點擊點是否在矩形框以內便可,不管是哪一個矩形框,只要在矩形框以內,就把當前矩形框設置爲點擊的矩形框。29行判斷鼠標點擊點相對於矩形框的位置。42-49行,是鼠標拉伸改變大小的判斷,能夠設置矩形四個角拉伸,但我認爲太複雜了,只保留了右下角拉伸的點擊判斷,操做更簡單一些。優化

響應事件:

  function dragRect(e) {
      // 判斷矩形是否開始拖拽
      if (isDragging == true) {
        // 判斷拖拽對象是否存在
        if (SelectedRect != null) {
          // 取得鼠標位置
          var x = e.pageX - canvas.offsetLeft;
          var y = e.pageY - canvas.offsetTop;
          // 將圓圈移動到鼠標位置
          SelectedRect.x= x-x1;
          SelectedRect.y= y-y1;

         // 更新畫布
         drawRect();
        }
      }
//判斷是否開始拉伸
if (right) {
//設置拉伸最小的邊界
if ((e.pageX - canvas.offsetLeft-SelectedRect.x)>50) { SelectedRect.width=e.pageX - canvas.offsetLeft-SelectedRect.x; } else { SelectedRect.width=50; } console.log(SelectedRect.width); if((e.pageY - canvas.offsetTop-SelectedRect.y)>50){ SelectedRect.height=e.pageY - canvas.offsetTop-SelectedRect.y; } else { SelectedRect.height=50; } drawRect(); } };

以上就完成了對矩形框的基本操做,而後添加onmouseup的函數和調用函數:動畫

    var isDragging = false;
    function stopDragging() {
      isDragging = false;
      right=false;
    };

   function clearCanvas() {
     // 去除全部矩形
      rects = [];this

    // 從新繪製畫布.spa

    drawCircles();
    }


  window.onload = function() {
      canvas = document.getElementById("canvas");
      context = canvas.getContext("2d");
      canvas.onmousedown = canvasClick;
      canvas.onmouseup = stopDragging;
      canvas.onmouseout = stopDragging;
      canvas.onmousemove =dragRect;
; };
相關文章
相關標籤/搜索