// x1, y1 would be mouse coordinates onmousedown
// x2, y2 would be mouse coordinates onmouseup
// all coordinates are considered relative to the document
function rectangleSelect(selector, x1, y1, x2, y2) {
var elements = [];
jQuery(selector).each(function() {
var $this = jQuery(this);
var offset = $this.offset();
var x = offset.left;
var y = offset.top;
var w = $this.width();
var h = $this.height();
if (x >= x1
&& y >= y1
&& x + w <= x2
&& y + h <= y2) {
// this element fits inside the selection rectangle
elements.push($this.get(0));
}
});
return elements;
}
// Simple test
// Mark all li elements red if they are children of ul#list
// and if they fall inside the rectangle with coordinates:
// x1=0, y1=0, x2=200, y2=200
var elements = rectangleSelect("ul#list li", 0, 0, 200, 200);
var itm = elements.length;
while(itm--) {
elements[itm].style.color = 'red';
console.log(elements[itm]);
}
const div = document.getElementById('myDiv');
const rect = div.getBoundingClientRect();
const elements = [];
for (let x = rect.left; x <= rect.right; x++) {
for (let y = rect.top; y <= rect.bottom; y++) {
const el = document.elementFromPoint(x, y);
if (el && !elements.includes(el)) {
elements.push(el);
}
}
}
2条答案
按热度按时间hgc7kmma1#
试试这样的方法:
对于vanilla JS解决方案,请查看此笔:https://codepen.io/ArtBIT/pen/KOdvjM
6uxekuva2#
嘿@powerboy几年前我有一个类似的用例,让我列出你的选择:
使用库
这将是一样简单:
举例来说:
该库附带拖放功能,但如果你只是想选择,没有拖放,你可以关闭它设置
draggability: false,
(文档|example)。在文档中,你还可以找到一个关于如何将它与你的自定义选择库一起使用的部分。即:
上下文:十多年前,当我面临这个挑战时,我写了这个方便的选择库。它现在非常成熟,可以解决您的用例。我强烈推荐使用它,而不是自己写,因为这是一个非常非常困难的挑战,仍然有很多可能出错。
在编写DragSelect时,我尝试了各种方法:
点下元素
理论上,我们有
document.elementFromPoint(x, y);
(),所以我们可以做以下事情(简化的伪代码):这段代码遍历myDiv元素边界内的每个点,并使用
document.elementFromPoint()
获取该点的元素。然后将元素添加到数组中(如果尚未添加)。这将给予一个数组,其中包含方形div边界内的所有元素。这似乎是最简单的方法,但它也有缺点:
elementsFromPoint
返回所有然而,如果你只需要一个点下面的元素,这是很棒的。
知道了这一点,我们可以通过检查可选元素的中点是否有ref矩形来改进算法:
使用碰撞算法
轴对齐最小包围盒
一个增强这一个是什么DragSelect是使用引擎盖下。我在这里详细解释了它,还有一篇关于2D碰撞的MDN文章。
让我解释一下:
轴对齐边界框碰撞检测。想象一下下面的例子:
为了检查这两个盒子是否碰撞,我们进行AABB计算:
因为你必须对每个可能发生冲突的元素进行检查,所以理论上这具有O(n)的复杂度(假设你只有1个引用元素),这是很大的,因为并且随着输入的数量线性扩展。
这在DragSelect中被证明是有效的,最多可以处理30.000个元素,然后它开始变慢,因为在JavaScript中获取边界框是昂贵的,我正在寻找一个更好的算法,因为我们幸运地说,对于99.99%的用例,30 k元素就足够了:)
但会让你更新未来的发现(即。其他算法或广泛和狭窄的阶段可能是有趣的)
希望能帮上忙,干杯!