实现全局可拖拽的小标签vue3+ts

实现效果图:

在app.vue中

HTML部分:

<template>
  <ConfigProvider :locale="getAntdLocale">
    <AppProvider>
      <RouterView />
      <!-- 智能助手 -->
      <div
        class="drag-div"
        :style="{ left: pos.x + 'px', top: pos.y + 'px' }"
        @mousedown="startDrag($event)"
      >
        <img :src="robotImg" alt="" />
        <p class="robot">智能助手</p>
      </div>
    </AppProvider>
  </ConfigProvider>
</template>

js部分:

<script lang="ts">
   import { defineComponent, ref, onMounted, onUnmounted } from 'vue';
  import robotImg from '/@/assets/assets/images/robot.png';

  export default defineComponent({
    name: 'App',
    components: { ConfigProvider, AppProvider },
    setup() {
      // 智能助手drag
      const pos = ref({ x: 1463, y: 179 });
      let isDragging = false;
      let mouseOffset = { x: 0, y: 0 };
      const startDrag = (event: MouseEvent) => {
        isDragging = true;
        mouseOffset.x = event.pageX - pos.value.x;
        mouseOffset.y = event.pageY - pos.value.y;
        document.addEventListener('mousemove', moveHandler);
        document.addEventListener('mouseup', upHandler);
      };
      const moveHandler = (event: MouseEvent) => {
        event.preventDefault();
        if (isDragging) {
          const newX = event.pageX - mouseOffset.x;
          const newY = event.pageY - mouseOffset.y;
          const maxX = window.innerWidth - 20; // 页面宽度 - div宽度
          const maxY = window.innerHeight - 20; // 页面高度 - div高度
          pos.value.x = Math.max(0, Math.min(newX, maxX));
          pos.value.y = Math.max(0, Math.min(newY, maxY));
        }
      };
      const upHandler = () => {
        isDragging = false;
        document.removeEventListener('mousemove', moveHandler);
        document.removeEventListener('mouseup', upHandler);
      };
      onMounted(() => {
        window.addEventListener('resize', () => {
          // console.log(window.innerWidth, window.innerHeight);
          const maxX = window.innerWidth - 20;
          const maxY = window.innerHeight - 20;
          console.log(maxX, maxY);
          const left = parseInt(pos.value.x || '0', 10);
          const top = parseInt(pos.value.y || '0', 10);
          const newLeft = Math.max(0, Math.min(left, maxX));
          const newTop = Math.max(0, Math.min(top, maxY));
          pos.value.x = newLeft;
          pos.value.y = newTop;
        });
      });
      // 清除窗口大小改变的监听器
      onUnmounted(() => {
        window.removeEventListener('resize', () => {});
      });

      return {
        robotImg,
        pos,
        startDrag,
      };
    },
  });
</script>

style:

<style lang="less">
  .drag-div {
    width: 20px;
    position: fixed;
    right: 0px;
    top: 200px;
    z-index: 10;
    user-select: none;
    cursor: move;
    img {
      width: 24px;
      height: auto;
    }
    p {
      width: 20px;
      margin: 0 auto;
      line-height: 20px;
      font-size: 14px;
      text-align: center;
      background: rgb(255, 139, 29);
      color: #fff;
      border-radius: 3px;
      padding: 3px;
    }
  }
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值