vue对话框拖拽移动

565 阅读1分钟

函数封装

/** dialog移动处理函数
 * @param {HTMLObjectElement} dragTarget 拖拽的目标区域
 * @param {HTMLObjectElement} dragMain 拖拽移动的主体
 */
function handleDialogDrag (dragTarget, dragMain) {
  dragTarget.style.cursor = 'move';
  // 鼠标按下
  dragTarget.onmousedown = e => {
    // 鼠标放在按钮上则不触发移动
    if (e.target.classList.contains('icon')) return;
    // 鼠标开始位置
    const startX = e.clientX;
    const startY = e.clientY;
    // 当前屏幕宽高
    const screenWidth = document.body.clientWidth;
    const screenHeight = document.body.clientHeight;
    // 移动主体宽高
    const dragMainWidth = dragMain.offsetWidth;
    const dragMainHeight = dragMain.offsetHeight;
    // 移动主体向左和向右移动的最远距离
    const leftMaxDistance = dragMain.offsetLeft;
    const rightMaxDistance = screenWidth - dragMain.offsetLeft - dragMainWidth;
    // 移动主体向上和向下移动的最远距离
    const topMaxDistance = dragMain.offsetTop;
    const bottomMaxDistance = screenHeight - dragMain.offsetTop - dragMainHeight;
    // 移动主体当前的left top值
    let { left, top } = getComputedStyle(dragMain, null);
    if (left.includes('%')) {
      left = document.body.clientWidth * (parseInt(left) / 100);
      top = document.body.clientHeight * (parseInt(top) / 100);
    } else {
      left = parseInt(left);
      top = parseInt(top);
    }

    // 鼠标移动
    document.onmousemove = function(e) {
      let moveLeft = e.clientX - startX;
      let moveTop = e.clientY - startY;
      // 边界处理
      if (-moveLeft > leftMaxDistance) {
        moveLeft = -leftMaxDistance;
      } else if (moveLeft > rightMaxDistance) {
        moveLeft = rightMaxDistance;
      }

      if (-moveTop > topMaxDistance) {
        moveTop = -topMaxDistance;
      } else if (moveTop > bottomMaxDistance) {
        moveTop = bottomMaxDistance;
      }

      dragMain.style.left = moveLeft + left + 'px';
      dragMain.style.top = moveTop + top + 'px';
    };
    // 鼠标松开
    document.onmouseup = function(e) {
      document.onmousemove = null;
      document.onmouseup = null;
    };
  }
}

使用,以el-dialog为例

dom结构

<el-dialog
  v-dialog-drag
  append-to-body
  title="提示"
  :visible.sync="dialogVisible"
  width="30%"
  :before-close="handleClose">
  <span>这是一段信息</span>
  <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  </span>
</el-dialog>

定义指令

directives: {
  dialogDrag: {
    bind(el) {
      handleDialogDrag(el.querySelector('.el-dialog__header'), el.querySelector('.el-dialog'));
    }
  }
},