vue封装弹窗元素拖动指令

项目开发过程中我们通常会遇到需要到一些弹窗鼠标可以随意拖动位置去放置,vue里面直接通过封装对应的指令即可,于是封装了一个出来,希望可以用到。

Vue.directive('draggable-dom', draggableDom);

组件节点添加对应指令就可以

v-draggable-dom="{zIndex: 999, top: 10, left: 50}"

<div class="search-bar" ref="seachBar" :style="{ width }" v-draggable-dom="{zIndex: 999, top: 10, left: 50}">

指令代码:

/**
 * 拖拽元素指令
 * @param { Number } top  // 初始位置top 坐标 默认为元素本身的top
 * @param { Number } left  // 初始位置left 坐标 默认为元素本身的left
 * @param { Number } zIndex  // 层级,默认为9999
 */
export const draggableDom = {
  bind(el, binding, vnode) {
    // 初始化变量
    let startX = 0; // 鼠标按下时的初始 X 坐标
    let startY = 0; // 鼠标按下时的初始 Y 坐标
    let initialLeft = 0; // 元素的初始 left 值
    let initialTop = 0; // 元素的初始 top 值
    let isDragging = false; // 拖拽状态

    if (binding.value?.position) {
      e.style.position = binding.value?.position;
    }

    // 如果属性定位没有的时候则设置绝对定位
    const position = window.getComputedStyle(el);
    if (!position || position == 'static') {
      e.style.position = "absolute";
    }

    // el.style.cursor = "move"; // 设置鼠标样式为移动图标
    // 默认层级,默认为9999
    el.style.zIndex = binding?.value?.zIndex || 9999;
    // 传入top值
    if (binding.value?.top) {
      // let top = el.getBoundingClientRect().top;
      let top = binding.value?.top;
      el.style.top = `${top}px`;
    }
    // 传入left值
    if (binding.value?.left) {
      // let left = el.getBoundingClientRect().left;
      let left = binding.value?.left;
      el.style.left = `${left}px`;
    }

    // 鼠标按下事件处理函数
    const onMouseDown = (event) => {
      // 防止文本选择
      // event.preventDefault();

      // 记录初始鼠标位置和元素位置
      startX = event.clientX;
      startY = event.clientY;
      initialLeft = el.offsetLeft;
      initialTop = el.offsetTop;
      isDragging = true; // 开启拖拽状态

      // 监听 mousemove 和 mouseup 事件
      document.addEventListener("mousemove", onMouseMove);
      document.addEventListener("mouseup", onMouseUp);
    };

    // 鼠标移动事件处理函数
    const onMouseMove = (event) => {
      if (!isDragging) return; // 如果未处于拖拽状态,直接返回

      // 计算鼠标的位移
      const moveX = event.clientX - startX;
      const moveY = event.clientY - startY;

      // 更新元素的位置
      el.style.left = initialLeft + moveX + "px";
      el.style.top = initialTop + moveY + "px";
    };

    // 鼠标松开事件处理函数
    const onMouseUp = () => {
      isDragging = false; // 关闭拖拽状态

      // 移除事件监听器
      document.removeEventListener("mousemove", onMouseMove);
      document.removeEventListener("mouseup", onMouseUp);
    };

    // 绑定 mousedown 事件
    el.style.position = "absolute"; // 确保元素是绝对定位
    el.addEventListener("mousedown", onMouseDown);
  },

  // 解绑指令
  unbind(el) {
    // 移除 mousedown 事件监听器
    el.removeEventListener("mousedown", onMouseDown);
  },
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值