Vue自定义指令实现元素拖拽(ts版本)

588 阅读1分钟

Vue自定义指令实现元素拖拽(ts版本)

Vue自定义实现元素拖拽,代码如下

import Vue, { DirectiveOptions } from 'vue';
const elDrag: DirectiveOptions = {
  bind(el, binding) {
    const dragEl = [].find.call(el.childNodes, (node: any) => node.id === 'drag-el') || el;
    (dragEl as any).onmousedown = (e: any) => {
      e = e || window.event; // 事件源对象兼容
      el.style.cursor = 'move';
      const { offsetTop, offsetLeft, offsetWidth, offsetHeight } = el; // 获取拖拽元素的位置和大小
      let maxX = 0;
      let maxY = 0;
      // 是否允许拖拽元素超出页面
      if (!binding.value.overRange) {
        maxX = window.innerWidth - offsetWidth;
        maxY = window.innerHeight - offsetHeight;
      }
      // 拖拽时阻止浏览器默认事件
      if ((dragEl as any).setCapture) {
        (dragEl as any).setCapture();
      } else {
        e.preventDefault ? e.preventDefault() : e.returnValue = false;
      }
      // 获取鼠标位置和拖拽元素位置的偏差
      const deltaX = e.clientX - offsetLeft;
      const deltaY = e.clientY - offsetTop;
      document.onmousemove = (event: any) => {
        event = event || window.event; // 事件源对象兼容
        const { clientX, clientY } = event;
        let left = clientX - deltaX;
        let top = clientY - deltaY;
        // 是否允许拖拽元素超出页面
        if (!binding.value.overRange) {
          left = left > 0 ? left > maxX ? maxX : left : 0;
          top = top > 0 ? top > maxY ? maxY : top : 0;
        }
        // 鼠标
        if (clientX > 0 && clientX < window.innerWidth) {
          el.style.left = `${left}px`;
        }
        if (clientY > 0 && clientY < window.innerHeight) {
          el.style.top = `${top}px`;
        }
      };
    };
    document.onmouseup = () => {
      el.style.cursor = '';
      document.onmousemove = null;
      document.onmouseup = null;
    };
  }
};
Vue.directive('el-drag', elDrag);

使用方式:在需要拖拽的元素绑定v-el-drag指令。 overRange设置是否允许元素离开页面可视区;如需设置元素某子元素为拖拽目标,给目标子元素添加id="drag-el"即可

<div v-el-drag="{ overRange: false }">
    <div id="drag-el">拖拽目标</div>
</div>

目前只是基础实现拖拽,更多配置功能还在思考中……