返回

网页控群框选的那些事

前端

网页框选是种便捷的操作方式,允许用户在网页上选择多个元素,以便执行后续操作。框选功能的实现方式有很多,但最常见的是基于绝对定位或Fixed定位。本文将重点介绍基于Fixed定位的框选功能,并提供实现步骤和示例代码。

基于Fixed定位的框选功能

基于Fixed定位的框选功能是一种使用Fixed定位元素来实现框选功能的技术。其基本原理是:

  1. 创建一个Fixed定位的元素,并将其覆盖在目标区域之上。
  2. 为该元素添加事件监听器,以便在用户拖动鼠标时捕获鼠标移动事件。
  3. 在鼠标移动事件中,计算出框选区域的坐标和大小。
  4. 将框选区域内的元素添加到选定元素列表中。

基于Fixed定位的框选功能的优点在于:

  • 实现简单,易于理解。
  • 定位准确,不会受到页面滚动或其他因素的影响。
  • 可以轻松实现拖动框选功能。

基于Fixed定位的框选功能的缺点在于:

  • 只能在支持Fixed定位的浏览器中使用。
  • 在某些情况下,可能会出现闪烁或重绘问题。

实现步骤

以下是如何使用Fixed定位实现框选功能的步骤:

  1. 创建一个Fixed定位的元素,并将其覆盖在目标区域之上。
  2. 为该元素添加事件监听器,以便在用户拖动鼠标时捕获鼠标移动事件。
  3. 在鼠标移动事件中,计算出框选区域的坐标和大小。
  4. 将框选区域内的元素添加到选定元素列表中。

以下是如何使用Fixed定位实现拖动框选功能的步骤:

  1. 创建一个Fixed定位的元素,并将其覆盖在目标区域之上。
  2. 为该元素添加鼠标按下事件监听器和鼠标移动事件监听器。
  3. 在鼠标按下事件中,记录鼠标按下的坐标。
  4. 在鼠标移动事件中,计算出框选区域的坐标和大小。
  5. 将框选区域内的元素添加到选定元素列表中。

示例代码

以下是如何使用Fixed定位实现框选功能的示例代码:

<div id="box-select">
  <div id="box-select-inner"></div>
</div>
#box-select {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

#box-select-inner {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  border: 1px dashed red;
}
const boxSelect = document.getElementById('box-select');
const boxSelectInner = document.getElementById('box-select-inner');

boxSelect.addEventListener('mousedown', e => {
  boxSelect.style.pointerEvents = 'auto';
  boxSelectInner.style.display = 'block';

  const startX = e.clientX;
  const startY = e.clientY;

  const moveHandler = e => {
    const endX = e.clientX;
    const endY = e.clientY;

    const width = Math.abs(endX - startX);
    const height = Math.abs(endY - startY);
    const left = Math.min(startX, endX);
    const top = Math.min(startY, endY);

    boxSelectInner.style.width = width + 'px';
    boxSelectInner.style.height = height + 'px';
    boxSelectInner.style.left = left + 'px';
    boxSelectInner.style.top = top + 'px';
  };

  const upHandler = e => {
    boxSelect.style.pointerEvents = 'none';
    boxSelectInner.style.display = 'none';

    const selectedElements = document.querySelectorAll('.element');
    selectedElements.forEach(element => {
      const elementRect = element.getBoundingClientRect();

      if (elementRect.top >= top &&
          elementRect.left >= left &&
          elementRect.bottom <= top + height &&
          elementRect.right <= left + width) {
        element.classList.add('selected');
      }
    });

    document.removeEventListener('mousemove', moveHandler);
    document.removeEventListener('mouseup', upHandler);
  };

  document.addEventListener('mousemove', moveHandler);
  document.addEventListener('mouseup', upHandler);
});

参考文献