Vue3鼠标拖拽生成区域块并选中元素

Vue3鼠标拖拽生成区域块并选中元素,选中的元素则背景高亮(或者其它逻辑)。

javascript 复制代码
<script setup>
import { ref } from 'vue'

// 区域ref
const regionRef = ref(null)

// 内容ref
const itemRefs = ref(null)

// 是否开启绘画区域
const enable = ref(false)

// 鼠标开始位置
const start = ref({
  x: 0,
  y: 0
})

// 区域块元素配置
const regionConfig = ref({
  top: '0px',
  left: '0px',
  width: '0px',
  height: '0px'
})


// 鼠标点击
const onMousedown = (e) => {
  const { pageX, pageY } = e
  start.value.x = pageX
  start.value.y = pageY
  regionConfig.value.top = pageY + 'px'
  regionConfig.value.left = pageX + 'px'
  enable.value = true
}

// 鼠标弹起
const onMouseup = () => {
  enable.value = false
}

// 鼠标移动
const onMousemove = (e) => {
  if (!enable.value) return false
  const { pageX, pageY } = e

  // 当前鼠标移动的位置减开始位置得到区域块宽高
  const x = pageX - start.value.x
  const y = pageY - start.value.y

  regionConfig.value.width = Math.abs(x) + 'px'
  regionConfig.value.height = Math.abs(y) + 'px'

  // 鼠标移动的位置小于开始位置,当前鼠标的位置是区域块的位置
  if (x < 0) {
    regionConfig.value.left = pageX + 'px'
  }

  if (y < 0) {
    regionConfig.value.top = pageY + 'px'
  }

  // 获取区域块和内容的位置
  const boxRect = regionRef.value.getBoundingClientRect()

  itemRefs.value.forEach((item) => {
    const rect = item.getBoundingClientRect()

    // 判断区域块包裹内容元素则改变背景颜色
    if (boxRect.top <= rect.top && boxRect.bottom >= rect.bottom && boxRect.left <= rect.left && boxRect.right >= rect.right) {
      item.style.backgroundColor = 'rgb(10, 228, 10)'
    } else {
      item.style.backgroundColor = '#cbccce'
    }
  })
}
</script>

<template>
  <main
    class="w_h_100 home"
    @mousedown="onMousedown"
    @mouseup="onMouseup"
    @mousemove="onMousemove"
  >
    <div class="box">
      <div
        ref="itemRefs"
        class="item"
        v-for="item in 10"
        :key="item"
      >{{ item }}</div>
    </div>

    <div
      ref="regionRef"
      class="region"
      :style="regionConfig"
    ></div>
  </main>
</template>

<style lang="less">
.home {
  display: flex;
  align-items: center;
  justify-content: center;

  .box {
    width: 200px;
    display: flex;
    flex-wrap: wrap;
  }

  .item {
    margin-right: 10px;
    margin-bottom: 10px;
    width: 30px;
    height: 30px;
    color: #fff;
    text-align: center;
    line-height: 30px;
    background-color: #cbccce;
    user-select: none;
  }

  .region {
    position: fixed;
    z-index: 10;
    border: 1px solid #0094ff;
    background-color: rgba(0, 148, 255, 0.1);
  }
}
</style>
相关推荐
wyzqhhhh17 分钟前
前端常见的设计模式
前端·设计模式
IT_陈寒21 分钟前
React 19重磅前瞻:10个性能优化技巧让你少写30%的useEffect代码
前端·人工智能·后端
m0_748233641 小时前
C++开发中的常用设计模式:深入解析与应用场景
javascript·c++·设计模式
fruge1 小时前
TypeScript 基础类型与接口详解
javascript·ubuntu·typescript
今天没有盐1 小时前
💕CSS 基础入门指南💕:选择器与文本样式
前端·html·响应式设计
AAA阿giao2 小时前
JavaScript 中的变量声明:var、let 与 const 深度解析
javascript·笔记
云枫晖2 小时前
Webpack系列-Entry入口
前端·webpack
mustfeng2 小时前
VCS & Verdi 2023安装
java·服务器·前端
Mintopia2 小时前
🌐 数据合规框架下的 WebAIGC 训练数据处理技术规范
前端·javascript·aigc
骥龙2 小时前
2.6、Web漏洞挖掘实战(下):XSS、文件上传与逻辑漏洞深度解析
前端·xss