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


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

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

html:

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

小demo,不做其他修飾,直接寫邏輯吧。

js:

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

如果想讓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 = [];

    // 重新繪制畫布.

    drawCircles();
    }


  window.onload = function() {
      canvas = document.getElementById("canvas");
      context = canvas.getContext("2d");
      canvas.onmousedown = canvasClick;
      canvas.onmouseup = stopDragging;
      canvas.onmouseout = stopDragging;
      canvas.onmousemove =dragRect;
; };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM