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;
; };
相关文章
相关标签/搜索