feat: 鼠标框选获取dom

master
lichaojun 1 week ago
parent b96d5d79db
commit 0a725cc1f0

@ -0,0 +1,361 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>DOM元素框选工具</title>
<style>
body {
margin: 0;
padding: 20px;
font-family: Arial, sans-serif;
background-color: #f5f5f5;
}
#container {
position: relative;
width: 100%;
height: 80vh;
border: 2px solid #333;
background-color: white;
overflow: hidden;
}
.selectable-element {
position: absolute;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #ccc;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
}
.selectable-element:hover {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
transform: scale(1.02);
}
.selectable-element.selected {
border: 2px solid #007bff;
box-shadow: 0 0 10px rgba(0, 123, 255, 0.5);
z-index: 10;
}
#selection-box {
position: absolute;
border: 2px dashed #007bff;
background-color: rgba(0, 123, 255, 0.1);
pointer-events: none;
display: none;
}
#result {
margin-top: 20px;
padding: 15px;
background-color: #e9ecef;
border-radius: 5px;
min-height: 100px;
}
button {
margin: 5px;
padding: 10px 15px;
background-color: #007bff;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
h1 {
color: #333;
}
</style>
</head>
<body>
<h1>DOM元素框选工具</h1>
<div id="container">
<!-- 可选择的元素 -->
<div
class="selectable-element"
style="width: 100px; height: 60px; top: 50px; left: 50px; background-color: #ff6b6b"
>
图片1
</div>
<div
class="selectable-element"
style="width: 120px; height: 80px; top: 150px; left: 200px; background-color: #4ecdc4"
>
按钮1
</div>
<div
class="selectable-element"
style="width: 150px; height: 70px; top: 300px; left: 100px; background-color: #45b7d1"
>
文本框
</div>
<div
class="selectable-element"
style="width: 80px; height: 80px; top: 200px; left: 400px; background-color: #96ceb4"
>
图片2
</div>
<div
class="selectable-element"
style="width: 100px; height: 50px; top: 100px; left: 500px; background-color: #feca57"
>
按钮2
</div>
<div
class="selectable-element"
style="width: 130px; height: 90px; top: 350px; left: 400px; background-color: #ff9ff3"
>
文本区域
</div>
<div
class="selectable-element"
style="width: 90px; height: 90px; top: 50px; left: 600px; background-color: #54a0ff"
>
图标
</div>
<div
class="selectable-element"
style="width: 110px; height: 60px; top: 250px; left: 650px; background-color: #5f27cd"
>
标签
</div>
<div
class="selectable-element"
style="width: 140px; height: 80px; top: 150px; left: 750px; background-color: #00d2d3"
>
输入框
</div>
<div
class="selectable-element"
style="width: 100px; height: 100px; top: 300px; left: 700px; background-color: #ff6348"
>
按钮3
</div>
<!-- 框选框 -->
<div id="selection-box"></div>
</div>
<div>
<button onclick="clearSelection()">清除选择</button>
<button onclick="getSelectedElements()">获取选中元素</button>
</div>
<div id="result">
<h3>选中元素列表:</h3>
<p id="selected-list">暂无选中元素</p>
</div>
<script>
let isSelecting = false;
let startX, startY;
let selectionBox = document.getElementById('selection-box');
let container = document.getElementById('container');
let elements = document.querySelectorAll('.selectable-element');
// 鼠标按下事件
container.addEventListener('mousedown', function (e) {
// 如果点击的是元素本身,则不进行框选
if (e.target.classList.contains('selectable-element')) {
return;
}
isSelecting = true;
// 获取相对于容器的坐标
const rect = container.getBoundingClientRect();
startX = e.clientX - rect.left;
startY = e.clientY - rect.top;
// 设置框选框的位置和大小
selectionBox.style.left = startX + 'px';
selectionBox.style.top = startY + 'px';
selectionBox.style.width = '0px';
selectionBox.style.height = '0px';
selectionBox.style.display = 'block'; // 防止拖拽时选择文字
e.preventDefault();
});
// 鼠标移动事件
container.addEventListener('mousemove', function (e) {
if (!isSelecting) return;
const rect = container.getBoundingClientRect();
const currentX = e.clientX - rect.left;
const currentY = e.clientY - rect.top;
// 计算框选框的宽度和高度
const width = Math.abs(currentX - startX);
const height = Math.abs(currentY - startY);
// 确定框选框的左上角位置
const left = Math.min(startX, currentX);
const top = Math.min(startY, currentY);
// 更新框选框的样式
selectionBox.style.left = left + 'px';
selectionBox.style.top = top + 'px';
selectionBox.style.width = width + 'px';
selectionBox.style.height = height + 'px';
});
// 鼠标释放事件
container.addEventListener('mouseup', function (e) {
if (!isSelecting) return;
isSelecting = false;
// 获取框选范围(在隐藏之前)
const containerRect = container.getBoundingClientRect();
const selectionLeft = parseFloat(selectionBox.style.left);
const selectionTop = parseFloat(selectionBox.style.top);
const selectionWidth = parseFloat(selectionBox.style.width);
const selectionHeight = parseFloat(selectionBox.style.height);
// 修复确保最小尺寸为1像素避免0值问题
const finalWidth = Math.max(selectionWidth, 1);
const finalHeight = Math.max(selectionHeight, 1);
const finalLeft = selectionLeft;
const finalTop = selectionTop;
console.log('Selection box info:', {
left: finalLeft,
top: finalTop,
width: finalWidth,
height: finalHeight,
containerRect: containerRect,
});
// 隐藏框选框
selectionBox.style.display = 'none';
// 检查哪些元素在框选范围内
checkSelection(finalLeft, finalTop, finalWidth, finalHeight);
});
// 检查元素是否在框选范围内
function checkSelection(left, top, width, height) {
console.log('Checking selection:', { left, top, width, height });
const selectedElements = [];
elements.forEach((element) => {
const elementRect = element.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
// 转换为相对于容器的坐标
const elementLeft = elementRect.left - containerRect.left;
const elementTop = elementRect.top - containerRect.top;
const elementWidth = elementRect.width;
const elementHeight = elementRect.height;
console.log('Element info:', {
text: element.textContent,
left: elementLeft,
top: elementTop,
width: elementWidth,
height: elementHeight,
});
// 矩形相交检测算法
// 两个矩形相交的条件是在x轴和y轴上都有重叠
const xOverlap = elementLeft < left + width && elementLeft + elementWidth > left;
const yOverlap = elementTop < top + height && elementTop + elementHeight > top;
console.log('Overlap check:', {
xOverlap,
yOverlap,
condition: xOverlap && yOverlap,
});
if (xOverlap && yOverlap) {
selectedElements.push(element);
}
});
console.log('Selected elements count:', selectedElements.length);
// 标记选中的元素
markSelectedElements(selectedElements);
// 显示结果
displayResults(selectedElements);
}
// 标记选中的元素
function markSelectedElements(elements) {
// 先清除所有已选中的标记
document.querySelectorAll('.selectable-element.selected').forEach((el) => {
el.classList.remove('selected');
});
// 给新选中的元素添加标记
elements.forEach((element) => {
element.classList.add('selected');
});
}
// 显示结果
function displayResults(elements) {
const resultElement = document.getElementById('selected-list');
if (elements.length === 0) {
resultElement.innerHTML = '没有选中任何元素';
return;
}
let html = '<ul>';
elements.forEach((element, index) => {
html += `<li>${index + 1}. ${element.textContent || '未知元素'}</li>`;
});
html += '</ul>';
resultElement.innerHTML = html;
}
// 清除选择
function clearSelection() {
document.querySelectorAll('.selectable-element.selected').forEach((el) => {
el.classList.remove('selected');
});
document.getElementById('selected-list').innerHTML = '暂无选中元素';
}
// 获取选中元素
function getSelectedElements() {
const selectedElements = document.querySelectorAll('.selectable-element.selected');
const elementsArray = Array.from(selectedElements);
displayResults(elementsArray);
}
// 添加鼠标离开容器时的处理,防止拖拽时鼠标移出容器导致的问题
document.addEventListener('mouseleave', function (e) {
if (isSelecting && e.target === container) {
isSelecting = false;
selectionBox.style.display = 'none';
}
});
// 添加document mouseup事件防止鼠标在容器外释放时的问题
document.addEventListener('mouseup', function (e) {
if (isSelecting) {
isSelecting = false;
selectionBox.style.display = 'none';
}
});
</script>
</body>
</html>
Loading…
Cancel
Save