在画布上绘制多个矩形框而不重叠

时间:2015-08-03 15:27:06

标签: javascript angularjs html5 canvas

我试图在画布图像上绘制多个(最多6个)矩形而不实际让它们与另一个重叠。怎么能在javascript中完成? 我想不出可用于此的逻辑..

修改:

如何检测任何一个绘制的矩形内是否发生鼠标点击,以便我可以再次在画布周围移动矩形而不重叠?

3 个答案:

答案 0 :(得分:1)

要确定新的矩形是否会与现有的任何重叠相叠,您必须进行3次测试:

  1. 新的rect是否与任何现有的rect相交?
  2. 新的rect是否完全包含任何现有的rect?
  3. 现有的rect是否完全包含新的rect?
  4. 以下是......

    如果您使用javascript对象定义了现有的矩形,请执行以下操作:

    var rects=[];
    rects.push({left:100,right:200,top:100,bottom:200});
    

    然后你可以测试一个新的矩形是否会重叠任何现有的矩形,如下所示:

    var newRectangle={left:50,right:25,top:50,bottom:25};
    
    function willOverlap(newRect){
    
        // shortcut to the new potential rect
        var r2=newRect;
    
        // test if one rect is completely inside another rect
        var isInside=function(rect1,rect2){
            return(rect2.left>=rect1.left && 
            rect2.right<=rect1.right && 
            rect2.top>=rect1.top &&
            rect2.bottom<=rect1.bottom);
        }
    
        // test if the new rect is overlapping any existing rect
        var isOverlapping=false;
        for(var i=0;i<rects.length;i++){
            var r1=rects[i];
            //
            var isIntersecting = !(r2.left>r1.right ||
            r2.right<r1.left ||
            r2.top>r1.bottom ||
            r2.bottom<r1.top);
            //
            var isContained= isInside(r1,r2) || isInside(r2,r1);
            //
            if(isIntersecting || isContained){
                isOverlapping=true;
            }
        }
        return(isOverlapping);
    }
    

    以下是示例代码和演示:

    &#13;
    &#13;
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    function reOffset(){
      var BB=canvas.getBoundingClientRect();
      offsetX=BB.left;
      offsetY=BB.top;        
    }
    var offsetX,offsetY;
    reOffset();
    window.onscroll=function(e){ reOffset(); }
    window.onresize=function(e){ reOffset(); }
    
    var isDown=false;
    var startX,startY;
    
    var rects=[];
    var newRect;
    
    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});
    $("#canvas").mouseout(function(e){handleMouseOut(e);});
    
    
    function handleMouseDown(e){
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
    
      startX=parseInt(e.clientX-offsetX);
      startY=parseInt(e.clientY-offsetY);
    
      // Put your mousedown stuff here
      isDown=true;
    }
    
    function handleMouseUp(e){
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
    
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
    
      // Put your mouseup stuff here
      isDown=false;
    
      if(!willOverlap(newRect)){
        rects.push(newRect);
      }
      drawAll();
    }
    
    function drawAll(){
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.lineWidth=1;
      ctx.strokeStyle='green';
      for(var i=0;i<rects.length;i++){
        var r=rects[i];
        ctx.strokeRect(r.left,r.top,r.right-r.left,r.bottom-r.top);
      }
    }
    
    function handleMouseOut(e){
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
    
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
    
      // Put your mouseOut stuff here
      isDown=false;
    }
    
    function handleMouseMove(e){
      if(!isDown){return;}
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
    
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
    
      newRect={
        left:Math.min(startX,mouseX),
        right:Math.max(startX,mouseX),
        top:Math.min(startY,mouseY),
        bottom:Math.max(startY,mouseY),
      }
    
      drawAll();
      ctx.strokeStyle = "lightgray";
      ctx.lineWidth = 3;
      ctx.strokeRect(startX,startY,mouseX-startX,mouseY-startY);
    
    }
    
    
    function willOverlap(newRect){
    
      // shortcut to the new potential rect
      var r2=newRect;
    
      // test if one rect is completely inside another rect
      var isInside=function(rect1,rect2){
        return(rect2.left>=rect1.left && 
               rect2.right<=rect1.right && 
               rect2.top>=rect1.top &&
               rect2.bottom<=rect1.bottom);
      }
    
      // test if the new rect is overlapping any existing rect
      var isOverlapping=false;
      for(var i=0;i<rects.length;i++){
        var r1=rects[i];
        //
        var isIntersecting = !(r2.left>r1.right ||
                               r2.right<r1.left ||
                               r2.top>r1.bottom ||
                               r2.bottom<r1.top);
        //
        var isContained= isInside(r1,r2) || isInside(r2,r1);
        //
        if(isIntersecting || isContained){
          isOverlapping=true;
        }
      }
      return(isOverlapping);
    }
    &#13;
    body{ background-color: ivory; }
    #canvas{border:1px solid red; margin:0 auto; }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <h4>Drag to create a new rect.<br>New rect will be added if not overlapping.</h4>
    <canvas id="canvas" width=300 height=300></canvas>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:0)

查看此演示:JSFiddle

只需在JavaScript中指定矩形的不同起点,然后绘制它们:

function draw() {
    var canvas = document.getElementById("canvas");
    if (canvas.getContext) {
        var ctx = canvas.getContext("2d");

        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect(10, 10, 20, 20);

        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect(30, 30, 20, 20);

        ......
    }
}

答案 2 :(得分:0)

将每个方块视为一个框,然后插入逻辑。

要检查您是否将方框1视为点云,请检查方框2的四个点中是否有任何一个位于该点云中。

作为一个说明,我是一个java开发人员,但原理是一样的。 Math.abs是x的绝对值。

if((Math.abs(b1X - b2X) < b1Width && Math.abs(b1Y - b2Y) < b1Height) ||
   (Math.abs(b1X - (b2X + b2Width)) < b1Width && Math.abs(b1Y - b2Y) < b1Height) ||
   (Math.abs(b1X - b2X) < b1Width && Math.abs(b1Y - (b2Y + b2Height)) < b1Height) ||
  (Math.abs(b1X - (b2X + b2Width)) < b1Width && Math.abs(b1Y - (b2Y + b2Height)) < b1Height))
            return false;

第一行检查b2上的点1是否在点云中,如果点2在点云上则为第2行,如果点3在云上则为第3行,如果点4在云上则为第4行

点定义为

1 ----- 2

|。 。 。 。 |

3 ----- 4

在创建方块时,您必须检查新创建的方块。如果它向任何方块返回false,则它重叠。