我正在尝试在网页上实现这样的功能:1.通过拖动鼠标选择正方形区域1.拾取选定区域中的所有元素1.处理它们=>所以我基本上想创建一个类似于“photoshop square selection tool”的东西,它可以获取所选区域中的所有HTML元素...这甚至可能以某种方式吗?你们中有谁做过这个或者知道一个js(jQuery)库吗?
smtd7mpg1#
不需要使用jQuery来创建矩形套索工具。逻辑并不难。
fixed
x = min(pointerStartX, pointerCurrentX)和w = abs(pointerStartX - pointerCurrentX);并对y和h执行等效操作套索工具示例:
x = min(pointerStartX, pointerCurrentX)
w = abs(pointerStartX - pointerCurrentX)
y
h
const el = (sel, par) => (par || document).querySelector(sel); const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop); const toolLasso = { onDown({clientX, clientY}) { this.startX = clientX; this.startY = clientY; this.el = elNew("div", {className: "lasso"}); this.onMove = this.onMove.bind(this); this.onUp = this.onUp.bind(this); addEventListener("pointermove", this.onMove); addEventListener("pointerup", this.onUp); // Insert into DOM Object.assign(this.el.style, { position: `fixed`, outline: `2px dashed blue`, zIndex: `99999`, pointerEvents: `none`, userSelect: `none`, }); el("body").append(this.el); }, onMove({clientX, clientY}) { this.currX = clientX; this.currY = clientY; const x = Math.min(this.startX, this.currX); const y = Math.min(this.startY, this.currY); const w = Math.abs(this.startX - this.currX); const h = Math.abs(this.startY - this.currY); Object.assign(this.el.style, { left: `${x}px`, top: `${y}px`, width: `${w}px`, height: `${h}px`, }); // Check elements selection: // checkElementsCollision(x, y, w, h); }, onUp() { removeEventListener("pointermove", this.onMove); removeEventListener("pointerup", this.onUp); this.el.remove(); } }; addEventListener("pointerdown", (evt) => toolLasso.onDown(evt));
* { margin: 0; box-sizing: border-box; } body { min-height: 200vh; } /* just to force some demo scrollbars */
对于元素的选择-任务非常基本:
onMove
checkElementsCollision(x, y, w, h)
Element.getBoundingClientRect()
x, y, w, h,
const el = (sel, par) => (par || document).querySelector(sel); const els = (sel, par) => (par || document).querySelectorAll(sel); const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop); const collides = (a, b) => a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y; const checkElementsCollision = (x, y, width, height) => { els(".box").forEach(elBox => { const isColliding = collides({x, y, width, height}, elBox.getBoundingClientRect()); elBox.classList.toggle("is-selected", isColliding); }); }; const toolLasso = { onDown({clientX, clientY}) { this.startX = clientX; this.startY = clientY; this.el = elNew("div", {className: "lasso"}); this.onMove = this.onMove.bind(this); this.onUp = this.onUp.bind(this); addEventListener("pointermove", this.onMove); addEventListener("pointerup", this.onUp); // Insert into DOM Object.assign(this.el.style, { position: `fixed`, outline: `2px dashed blue`, zIndex: `99999`, pointerEvents: `none`, userSelect: `none`, }); el("body").append(this.el); }, onMove({clientX, clientY}) { this.currX = clientX; this.currY = clientY; const x = Math.min(this.startX, this.currX); const y = Math.min(this.startY, this.currY); const w = Math.abs(this.startX - this.currX); const h = Math.abs(this.startY - this.currY); Object.assign(this.el.style, { left: `${x}px`, top: `${y}px`, width: `${w}px`, height: `${h}px`, }); // Check elements selection: checkElementsCollision(x, y, w, h); }, onUp() { removeEventListener("pointermove", this.onMove); removeEventListener("pointerup", this.onUp); this.el.remove(); } }; addEventListener("pointerdown", (evt) => toolLasso.onDown(evt));
* { margin: 0; box-sizing: border-box; } body { min-height: 200vh; } /* just to force some demo scrollbars */ .box { position: absolute; background: gray; width: 40px; aspect-ratio: 1; left: calc(var(--x) * 1px ); top: calc(var(--y) * 1px); } .box.is-selected { background: gold; }
<div class="box" style="--x:100; --y:100;"></div> <div class="box" style="--x:150; --y:170;"></div> <div class="box" style="--x:50; --y:200;"></div> <div class="box" style="--x:180; --y:10;"></div>
在MDN上阅读更多关于:2D collision detection
uwopmtnx2#
好吧,有几种方法可以做到这一点。事实上,我刚才已落实了这一点。我使用一个div,id="tool-lasso" style="position: absolute;"在鼠标按下时,我将一个变量mouseMode设置为lasso,并将元素(tool-lasso) css设置为左:
id="tool-lasso" style="position: absolute;"
mouseMode
lasso
(tool-lasso)
e.pageX; top: e.pageY; width: 0; height: 0;
在鼠标移动时,如果mouseMode == 'lasso',我会更新宽度和高度:
mouseMode == 'lasso'
e.pageX - parseInt($('#tool-lasso').css('left')), e.pageY - parseInt($('#tool-lasso').css('top'))
然后在鼠标向上时,将mouseMode设置为normal。对于鼠标移动部分,您可能希望将其设置为function(e) {...},并在鼠标向下和向上事件以及鼠标移动中调用它。
normal
function(e) {...}
2条答案
按热度按时间smtd7mpg1#
使用碰撞选择套索工具
不需要使用jQuery来创建矩形套索工具。
逻辑并不难。
fixed
位置元素”,因此您还需要一个位置固定的样式化套索元素。x = min(pointerStartX, pointerCurrentX)
和w = abs(pointerStartX - pointerCurrentX)
;并对y
和h
执行等效操作套索工具示例:
对于元素的选择-任务非常基本:
onMove
调用一个checkElementsCollision(x, y, w, h)
,在这里你基本上可以检查一个元素或一组元素Element.getBoundingClientRect()
x,y,width 和 height 是否与你的lasso工具传递的x, y, w, h,
参数值冲突。在MDN上阅读更多关于:2D collision detection
uwopmtnx2#
好吧,有几种方法可以做到这一点。
事实上,我刚才已落实了这一点。
我使用一个div,
id="tool-lasso" style="position: absolute;"
在鼠标按下时,我将一个变量mouseMode
设置为lasso
,并将元素(tool-lasso)
css设置为左:在鼠标移动时,如果
mouseMode == 'lasso'
,我会更新宽度和高度:然后在鼠标向上时,将
mouseMode
设置为normal
。对于鼠标移动部分,您可能希望将其设置为
function(e) {...}
,并在鼠标向下和向上事件以及鼠标移动中调用它。