Vue-Drag

vue拖拽功能

必备知识点:

先给不懂的童鞋补充下流程,文章要细读方能拖动元素到你心里~

按下的时候,我们需要获取

元素当前的 具有相对定位元素的左侧距离

元素当前的具有相对定位元素的顶部距离

鼠标按下点的x轴距离(鼠标左侧的距离)

鼠标按下点的y轴距离 (鼠标顶部的距离)

获取到这些点,先存储起来,后面的计算需要用到这些值

start(e){
    // 如果touches存在就说明是移动端
    // 否则为pc端直接获取事件源对象
    let touch = e.touches? e.touches[0] : e;
    this.position.x = touch.clientX;
    this.position.y = touch.clientY;
    this.dx = moveDiv.offsetLeft;
    this.dy = moveDiv.offsetTop;
}

Step1.

​ 让元素跟着鼠标的移动不断移动。既然鼠标的x轴和y轴可以获取到,那我们就可以通过计算来让元素实现移动。

​ 移动的时候,我们需要获取并设置

鼠标此时的当前的x轴和y轴的距离

鼠标点击的x轴和y轴的距离(按下的时候定义过)

此时用移动的距离 - 点击的起始位置就是移动的距离。

赋值给点击元素的left和top即可。

补充:计算的方式很多种,这只是其中一种

move(e){
  let touch = e.touches ? e.touches[0] : e;
  this.nx = touch.clientX - this.position.x;
  this.ny = touch.clientY - this.position.y;
  this.xPum = this.dx + this.nx;
  this.yPum = this.dy + this.ny;
  moveDiv.style.left = this.xPum + "px";
  moveDiv.style.top = this.yPum + "px";
}

Step2.

​ 离开的时候,我们需要抬起和移动事件从栈中清除掉,并且在结束时对边界做一个处理。不让元素拖动到屏幕外面,否则的话,不小心拖出去了,拉都拉不回来。这就很尴尬了。

元素的宽度

父元素的宽度和高度

元素的左侧距离 + 元素的宽度

元素的顶部距离 + 元素的高度

end(e){
    let oWidth = moveDiv.offsetWidth; // Element Width
    let oWrapWidth = moveDiv.parentNode.offsetWidth; // Parent Element Width
    let oWrprapHeight = moveDiv.parentNode.offsetHeight; // Parent Element Height
    let sumWidth = moveDiv.offsetLeft + oWidth; // Element Left + Element Width
    let sumHeight = moveDiv.offsetTop + moveDiv.offsetHeight; // Element Top + Element Height
    // The Limit Deal
    if(moveDiv.offsetLeft < 0) {
        moveDiv.style.left = 0;
    } else if(sumWidth > oWrapWidth){
        moveDiv.style.left = oWrapWidth - oWidth + 'px';
    } else if(moveDiv.offsetTop < 0) {
        moveDiv.style.top = 0;
    } else if(sumHeight > oWrprapHeight) {
        moveDiv.style.top = oWrprapHeight - moveDiv.offsetHeight + 'px';
    }
    document.onmousemove = null;
    document.onmouseup = null;
}

组件源码

​ 考虑到复用性,pc和移动端。

<template>
<!--S 拖动组件 -->
  <div class="drag" id="moveDiv"
    @mousedown="start($event)" @touchstart="start($event)"
    @mousemove="move($event)" @touchmove="move($event)"
    @mouseup="end($event)" @touchend="end($event)">
    <slot name="drag-cont"></slot>
  </div><!--E 拖动组件 -->
</template>
<script>
export default {
  data() {
    return {
      position: {x: 0,y: 0}, // 鼠标点击的x轴和y轴的距离
      nx: '',    // 鼠标当前距离元素的左侧距离
      ny: '',    // 鼠标当前距离元素的顶部距离
      dx: '',    // 元素距离左侧的距离
      dy: '',    // 元素距离顶部的距离
      xPum: '',  // 元素移动的x轴距离
      yPum: '',  // 元素移动的y轴距离
    }
  },
  methods: {
    start(e){
      // 如果touches存在就说明是移动端
      // 否则为pc端直接获取事件源对象
      let touch = e.touches ? e.touches[0] : e;
      this.position.x = touch.clientX;
      this.position.y = touch.clientY;
      this.dx = moveDiv.offsetLeft;
      this.dy = moveDiv.offsetTop;
    },
    move(e){
      let touch = e.touches ? e.touches[0] : e;
      this.nx = touch.clientX - this.position.x;
      this.ny = touch.clientY - this.position.y;
      this.xPum = this.dx+this.nx;
      this.yPum = this.dy+this.ny;
      moveDiv.style.left = this.xPum + "px";
      moveDiv.style.top = this.yPum + "px";
      document.addEventListener("touchmove",function(){
        event.preventDefault();
      },false);
      if(e.preventDefault) {
        e.preventDefault();
      } else {
        window.event.returnValue == false;
      }
    },
    end(e){
      let oWidth = moveDiv.offsetWidth; // Element Width
      let oWrapWidth = moveDiv.parentNode.offsetWidth; // Parent Element Width
      let oWrprapHeight = moveDiv.parentNode.offsetHeight; // Parent Element Height
      let sumWidth = moveDiv.offsetLeft + oWidth; // Element Left + Element Width
      let sumHeight = moveDiv.offsetTop + moveDiv.offsetHeight; // Element Top + Element Height
      // The Limit Deal
      if(moveDiv.offsetLeft < 0) {
        moveDiv.style.left = 0;
      } else if(sumWidth > oWrapWidth){
        moveDiv.style.left = oWrapWidth - oWidth + 'px';
      } else if(moveDiv.offsetTop < 0) {
        moveDiv.style.top = 0;
      } else if(sumHeight > oWrprapHeight) {
        moveDiv.style.top = oWrprapHeight - moveDiv.offsetHeight + 'px';
      }
      document.onmousemove = null;
      document.onmouseup = null;
    }
  }
}
</script>

<style lang="less" scoped>
.drag {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 999;
}
</style>

引入Demo

<Drag class="drag">
  <div slot="drag-cont">订单记录</div>
</Drag>
<style>
  .drag {
    width: .6rem;
    height: .6rem;
    background-color: rgba(0, 0, 0,.55);
    text-align: center;
    line-height: .6rem;
    font-size: .14rem;
    color: #ffffff;
  }
</style>

使用的时候,给组件添加类名,添加样式即可。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!