我试图在 Canvas 图像上绘制多个(最多 6 个)矩形,但实际上并不让它们彼此重叠。这如何在 JavaScript 中完成? 我想不出可以用于此目的的逻辑..
编辑:
如何检测鼠标单击是否发生在任何一个绘制的矩形内,以便我可以再次在 Canvas 上移动矩形而不重叠?
最佳答案
要查明新的矩形是否会与任何现有的矩形重叠,您必须执行 3 项测试:
- 新矩形是否与任何现有矩形相交?
- 新矩形是否完全包含任何现有矩形?
- 现有的矩形是否完全包含新的矩形?
方法如下...
如果您有使用 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);
}
这里是示例代码和演示:
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);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<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>
关于javascript - 在 Canvas 上绘制多个矩形框,不要重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31791152/