你能用 JavaScript 判断一个元素是否与另一个元素接触吗?
Can you tell if one element is touching another using JavaScript?
我想使用 JavaScript 检查一个 div
元素(可以拖动)是否正在接触另一个 div
元素。
这是一些代码:
<div id="draggable" style="position: absolute; top: 100px; left: 200px; background-color: red; width: 100px; height: 100px;"></div>
<div style="background-color: green; width: 100px; height: 100px;"></div>
这可以做到吗?
如果是,怎么做?
编辑: 我不想使用 jQuery,只是老旧 JavaScript!
更新: 我现在意识到,这只说明了目标元素左上角的交集,因此没有提供完整的解决方案。但我会把它留给后代,以防有人发现它对其他用途有用。
使用element.getBoundingClientRect()
和document.elementFromPoint()
可以使用element.getClientBoundingRect()
(src)获取目标(点击、拖动等)元素的位置
暂时隐藏目标元素,然后使用document.elementFromPoint(x, y)
(src)获取该位置的最顶层元素,然后检查它是class用于比较的名称(如果愿意,您可以比较任何属性或 属性)。
通过此方法实现跨浏览器兼容行为
阅读:document.elementFromPoint – a jQuery solution (你不
必须使用 jQuery 才能达到此结果。该方法可以是
以纯 JS 复制。)
附录:
我只展示了检测重叠的功能,而不是展示了拖放或拖拽移动功能,因为不清楚你正在尝试实现其中的哪一个,如果有的话,还有显示如何完成各种拖动模式的其他答案。
在任何情况下,您都可以将下面的detectCollision()
功能与任何拖动解决方案结合使用。
var box2 = document.getElementById('box2'),
box3 = document.getElementById('box3');
box2.onclick = detectCollision;
box3.onclick = detectCollision;
function detectCollision(e) {
var elem = e.target,
elemOffset = elem.getBoundingClientRect(),
elemDisplay = elem.style.display;
// Temporarily hide element
elem.style.display = 'none';
// Check for top-most element at position
var topElem = document.elementFromPoint(elemOffset.left, elemOffset.top);
// Reset element's initial display value.
elem.style.display = elemDisplay;
// If a top-most element is another box
if (topElem.className.match(/box/)) {
alert(elem.id + " is touching " + topElem.id);
} else {
alert(elem.id + " isn't touching another box.");
};
}
#box1 {
background-color: LightSeaGreen;
}
#box2 {
top: 25px;
left: -25px;
background-color: SandyBrown;
}
#box3 {
background-color: SkyBlue;
}
.box {
position: relative;
display: inline-block;
width: 100px;
height: 100px;
}
.clickable {
cursor: pointer;
}
<div class="box" id="box1"></div>
<div class="box clickable" id="box2"></div>
<div class="box clickable" id="box3"></div>
更完整的解决方案
下面是 "plain old JavaScript" 对 this answer to the question titled "jQuery/Javascript collision detection 中的重叠检测函数的重写。
两者之间唯一真正的区别是替换了使用 jQuery 获取元素位置和宽度以计算边界框。
令人惊讶的是,原生 JavaScript 使用得到良好支持的 (IE4+) Element.getBoundingClientRect()
方法使这项任务变得更容易,returns 创建位置矩阵所需的四个值由getPositions
函数。
我为框添加了一个点击处理程序,作为您如何使用该函数将目标(点击、拖动等)元素与一组选定元素进行比较的简单演示。 不过,我承认 jQuery 使 DOM 选择和事件绑定比原生 JS 更容易。
var boxes = document.querySelectorAll('.box');
boxes.forEach(function (el) {
if (el.addEventListener) {
el.addEventListener('click', clickHandler);
} else {
el.attachEvent('onclick', clickHandler);
}
})
var detectOverlap = (function () {
function getPositions(elem) {
var pos = elem.getBoundingClientRect();
return [[pos.left, pos.right], [pos.top, pos.bottom]];
}
function comparePositions(p1, p2) {
var r1, r2;
if (p1[0] < p2[0]) {
r1 = p1;
r2 = p2;
} else {
r1 = p2;
r2 = p1;
}
return r1[1] > r2[0] || r1[0] === r2[0];
}
return function (a, b) {
var pos1 = getPositions(a),
pos2 = getPositions(b);
return comparePositions(pos1[0], pos2[0]) && comparePositions(pos1[1], pos2[1]);
};
})();
function clickHandler(e) {
var elem = e.target,
elems = document.querySelectorAll('.box'),
elemList = Array.prototype.slice.call(elems),
within = elemList.indexOf(elem),
touching = [];
if (within !== -1) {
elemList.splice(within, 1);
}
for (var i = 0; i < elemList.length; i++) {
if (detectOverlap(elem, elemList[i])) {
touching.push(elemList[i].id);
}
}
if (touching.length) {
console.log(elem.id + ' touches ' + touching.join(' and ') + '.');
alert(elem.id + ' touches ' + touching.join(' and ') + '.');
} else {
console.log(elem.id + ' touches nothing.');
alert(elem.id + ' touches nothing.');
}
}
#box1 {
background-color: LightSeaGreen;
}
#box2 {
top: 25px;
left: -25px;
background-color: SandyBrown;
}
#box3 {
left: -50px;
background-color: SkyBlue;
}
#box4 {
background-color: SlateGray;
}
.box {
position: relative;
display: inline-block;
width: 100px;
height: 100px;
color: White;
font: bold 72px sans-serif;
line-height: 100px;
text-align: center;
cursor: pointer;
}
.box:hover {
color: Black;
}
<p>Click a box to see which other boxes are detected as touching it.<br />
<em>If no alert dialog box appears, open your console to view messages.</em></p>
<div class="box" id="box1">1</div>
<div class="box" id="box2">2</div>
<div class="box" id="box3">3</div>
<div class="box" id="box4">4</div>
我想使用 JavaScript 检查一个 div
元素(可以拖动)是否正在接触另一个 div
元素。
这是一些代码:
<div id="draggable" style="position: absolute; top: 100px; left: 200px; background-color: red; width: 100px; height: 100px;"></div>
<div style="background-color: green; width: 100px; height: 100px;"></div>
这可以做到吗?
如果是,怎么做?
编辑: 我不想使用 jQuery,只是老旧 JavaScript!
更新: 我现在意识到,这只说明了目标元素左上角的交集,因此没有提供完整的解决方案。但我会把它留给后代,以防有人发现它对其他用途有用。
使用element.getBoundingClientRect()
和document.elementFromPoint()
可以使用
element.getClientBoundingRect()
(src)获取目标(点击、拖动等)元素的位置暂时隐藏目标元素,然后使用
document.elementFromPoint(x, y)
(src)获取该位置的最顶层元素,然后检查它是class用于比较的名称(如果愿意,您可以比较任何属性或 属性)。通过此方法实现跨浏览器兼容行为 阅读:document.elementFromPoint – a jQuery solution (你不 必须使用 jQuery 才能达到此结果。该方法可以是 以纯 JS 复制。)
附录:
我只展示了检测重叠的功能,而不是展示了拖放或拖拽移动功能,因为不清楚你正在尝试实现其中的哪一个,如果有的话,还有显示如何完成各种拖动模式的其他答案。
在任何情况下,您都可以将下面的detectCollision()
功能与任何拖动解决方案结合使用。
var box2 = document.getElementById('box2'),
box3 = document.getElementById('box3');
box2.onclick = detectCollision;
box3.onclick = detectCollision;
function detectCollision(e) {
var elem = e.target,
elemOffset = elem.getBoundingClientRect(),
elemDisplay = elem.style.display;
// Temporarily hide element
elem.style.display = 'none';
// Check for top-most element at position
var topElem = document.elementFromPoint(elemOffset.left, elemOffset.top);
// Reset element's initial display value.
elem.style.display = elemDisplay;
// If a top-most element is another box
if (topElem.className.match(/box/)) {
alert(elem.id + " is touching " + topElem.id);
} else {
alert(elem.id + " isn't touching another box.");
};
}
#box1 {
background-color: LightSeaGreen;
}
#box2 {
top: 25px;
left: -25px;
background-color: SandyBrown;
}
#box3 {
background-color: SkyBlue;
}
.box {
position: relative;
display: inline-block;
width: 100px;
height: 100px;
}
.clickable {
cursor: pointer;
}
<div class="box" id="box1"></div>
<div class="box clickable" id="box2"></div>
<div class="box clickable" id="box3"></div>
更完整的解决方案
下面是 "plain old JavaScript" 对 this answer to the question titled "jQuery/Javascript collision detection 中的重叠检测函数的重写。
两者之间唯一真正的区别是替换了使用 jQuery 获取元素位置和宽度以计算边界框。
令人惊讶的是,原生 JavaScript 使用得到良好支持的 (IE4+) Element.getBoundingClientRect()
方法使这项任务变得更容易,returns 创建位置矩阵所需的四个值由getPositions
函数。
我为框添加了一个点击处理程序,作为您如何使用该函数将目标(点击、拖动等)元素与一组选定元素进行比较的简单演示。 不过,我承认 jQuery 使 DOM 选择和事件绑定比原生 JS 更容易。
var boxes = document.querySelectorAll('.box');
boxes.forEach(function (el) {
if (el.addEventListener) {
el.addEventListener('click', clickHandler);
} else {
el.attachEvent('onclick', clickHandler);
}
})
var detectOverlap = (function () {
function getPositions(elem) {
var pos = elem.getBoundingClientRect();
return [[pos.left, pos.right], [pos.top, pos.bottom]];
}
function comparePositions(p1, p2) {
var r1, r2;
if (p1[0] < p2[0]) {
r1 = p1;
r2 = p2;
} else {
r1 = p2;
r2 = p1;
}
return r1[1] > r2[0] || r1[0] === r2[0];
}
return function (a, b) {
var pos1 = getPositions(a),
pos2 = getPositions(b);
return comparePositions(pos1[0], pos2[0]) && comparePositions(pos1[1], pos2[1]);
};
})();
function clickHandler(e) {
var elem = e.target,
elems = document.querySelectorAll('.box'),
elemList = Array.prototype.slice.call(elems),
within = elemList.indexOf(elem),
touching = [];
if (within !== -1) {
elemList.splice(within, 1);
}
for (var i = 0; i < elemList.length; i++) {
if (detectOverlap(elem, elemList[i])) {
touching.push(elemList[i].id);
}
}
if (touching.length) {
console.log(elem.id + ' touches ' + touching.join(' and ') + '.');
alert(elem.id + ' touches ' + touching.join(' and ') + '.');
} else {
console.log(elem.id + ' touches nothing.');
alert(elem.id + ' touches nothing.');
}
}
#box1 {
background-color: LightSeaGreen;
}
#box2 {
top: 25px;
left: -25px;
background-color: SandyBrown;
}
#box3 {
left: -50px;
background-color: SkyBlue;
}
#box4 {
background-color: SlateGray;
}
.box {
position: relative;
display: inline-block;
width: 100px;
height: 100px;
color: White;
font: bold 72px sans-serif;
line-height: 100px;
text-align: center;
cursor: pointer;
}
.box:hover {
color: Black;
}
<p>Click a box to see which other boxes are detected as touching it.<br />
<em>If no alert dialog box appears, open your console to view messages.</em></p>
<div class="box" id="box1">1</div>
<div class="box" id="box2">2</div>
<div class="box" id="box3">3</div>
<div class="box" id="box4">4</div>