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>
相关推荐
子兮曰19 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰19 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万19 小时前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝19 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋20 小时前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁21 小时前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄21 小时前
JavaScript 隐式全局变量解析
javascript
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端