【问题标题】:How to determine when rectangle and rotated rectangle intersect using JavaScript?如何使用 JavaScript 确定矩形和旋转矩形何时相交?
【发布时间】:2018-03-23 00:45:27
【问题描述】:

对于我的应用程序,我有一个 SVG 绘制的矩形,我将其用作命中框,并且我正在寻找一个 JavaScript 函数,该函数在命中框接触到另一个围绕其中心旋转的矩形时返回一个布尔值 true从某个角度使用 CSS 转换。我从http://www.inkfood.com/collision-detection-with-svg/ 发现了这段代码:

function intersectRect(r1, r2) {
var r1 = r1.getBoundingClientRect();    //BOUNDING BOX OF THE FIRST OBJECT
var r2 = r2.getBoundingClientRect();    //BOUNDING BOX OF THE SECOND OBJECT

//CHECK IF THE TWO BOUNDING BOXES OVERLAP
 return !(r2.left > r1.right || 
       r2.right < r1.left || 
       r2.top > r1.bottom ||
       r2.bottom < r1.top);
}

这对常规矩形非常有效,但我不确定如何在此基础上构建旋转矩形。当我在 Web 浏览器中使用开发人员工具检查旋转的矩形时,我可以看到它正确突出显示了矩形。话虽如此,当我尝试使用 JavaScript 提取边界客户端矩形时,它会以未旋转的形式返回矩形的尺寸。我的问题是如何接收旋转矩形的正确尺寸,以便检测它何时与我的命中框矩形发生碰撞?是否有另一种方法可以检测我的命中框何时触及我的旋转矩形?任何帮助将非常感激。

【问题讨论】:

  • 如果您愿意改用canvas,您可能会更轻松。 isPointInPath 尤其可以为您省去很多麻烦:w3schools.com/tags/canvas_ispointinpath.asp
  • @jmcgriz 感谢您的回复!我正在玩 W3Schools 上的画布,我可以看到 isPointInPath 似乎在我绘制的没有旋转的矩形中完美地工作。但是,在旋转之后,当给定它内部的一个点时,它似乎不会触发 true。我也尝试过使用 lineTo(),但它只适用于实际的细线本身,当我增加 lineWidth 时,它仍然只适用于原始线条,而不适用于新的笔划区域。有没有办法克服这两种情况?
  • 我会稍微弄乱它,但我认为您的答案将来自实际跟踪矩形并使用转换矩阵进行旋转,而不是仅使用内置的 rectrotate 方法

标签: javascript html svg collision


【解决方案1】:

SVG 规范中有很多 ick,但这是您所要求的工作示例。请注意,这是中心问题!

https://codepen.io/josephscottstevens/pen/XEgbrP

window.onmousemove = function(e) {
  var c = document.getElementById("circle");
  var l = document.getElementById("line");
  var displayDiv = document.getElementById("isColiding");
  var circle = { radius : c.r, center : { x:c.cx, y:c.cy } };
  var line =   { p1 : { x:l.x1, y:l.y1 }, p2 : { x:l.x2, y:l.y2 } };
  displayDiv.textContent = circle.radius; //(distance == 0) ? "coliding" : "not coliding";
  moveSection("circle", e.clientX - 20, e.clientY - 20);
  var distance = circleDistFromLineSeg(circle, line);


}

【讨论】:

  • 很聪明,但你有点作弊哈哈。虽然如果您使用两条线段作为矩形的边界,并且可以为移动元素使用圆形碰撞框,这可能会节省大量处理能力。
  • 这正是我所需要的。谢谢!
【解决方案2】:

好的,所以这需要大量优化才能适用于您的用例,但它确实可以证明isPointInPath 可以使用旋转,只要您按点绘制矩形(您也可以使用fillRectrotate 来绘制它,只需使用lineTo 跟踪轮廓,但不要使用stroke 来创建要检查的边界框)。

要测试isPointInPath,请编辑checkXcheckY 的值

var ctx = document.querySelector('canvas').getContext('2d')

function rotate(x, y, a, b, degrees){
	let angle = degrees * (Math.PI / 180),
  	sinA = Math.sin(angle),
  	cosA = Math.cos(angle)
    
  return [
  	cosA * (a - x) - sinA * (b - y) + x,
    sinA * (a - x) + cosA * (b - y) + y
  ]
}

function drawRect(x, y, w, h, rotation){
	var manipFn = rotation ? rotate : function(a,b){ return [a,b]; }
  
  var coords = {
  	bottomLeft: manipFn(x,y,x,y,rotation),
    bottomRight: manipFn(x,y,x+w,y,rotation),
    topRight: manipFn(x,y,x+w,y+h,rotation),
    topLeft: manipFn(x,y,x,y+h,rotation)
  }
  
  var checkX = 106,
    checkY = 18
  
  ctx.moveTo(...coords.bottomLeft)
  ctx.strokeStyle = "#3a1"
  ctx.lineWidth = 1
  ctx.lineTo(...coords.bottomRight)
  ctx.lineTo(...coords.topRight)
  ctx.lineTo(...coords.topLeft)
  ctx.lineTo(...coords.bottomLeft)
  console.log(ctx.isPointInPath(checkX,checkY))
  ctx.stroke()
  ctx.closePath()
  
  ctx.fillStyle = "#000"
  ctx.fillRect(checkX, checkY, 2, 2)
}


//drawRect(10, 10, 20, 30)


drawRect(100, 10, 20, 30, 45)
canvas {
  width: 500px;
  height: 500px;
  border: 1px solid black;
}
&lt;canvas&gt;&lt;/canvas&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 2018-09-27
    • 1970-01-01
    相关资源
    最近更新 更多