vue自定义拖拽

2022-05-12  本文已影响0人  菜蚴菜
<template>
  <div
    ref="floatTab"
    class="float-tab"
    :style="{
      top: top + 'px',
      left: left + 'px',
    }"
    @mousedown="handleMousedown"
  >
    拖拽组件
  </div>
</template>

<script>
// 距离窗口上下边的距离
const fixedDirection = 50;
// 距离右侧的固定距离
const fixedRightDirection = 18;
export default {
  name: 'float-tab',
  props: {},
  data() {
    return {
      /** 距离窗口头部的距离 */
      top: 0,
      /** 距离窗口右侧的距离 */
      left: 0,
      /** 组件的拖拽状态 */
      dragStatus: false,
      /** 组件的高度 */
      height: 0,
      /** 组件的宽度 */
      width: 0,
      /** 鼠标点击的时候距离内容顶部的高度 */
      mouseStartTop: 0,
      /** 鼠标点击的时候距离内容左侧的高度 */
      mouseStartLeft: 0,
      /** 窗口的高度 */
      clientHeight: 0,
      /** 窗口的宽度 */
      clientWidth: 0,
    };
  },
  created() {
    //进入页面获取窗口宽高
    this.clientHeight = document.documentElement.clientHeight;
    this.clientWidth = document.documentElement.clientWidth;
  },
  mounted() {
    // 当窗口的大小发生变化时,主要用于pc端
    window.addEventListener('resize', this.resizeFuc);
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('mousemove', this.handleMousemove);
      window.removeEventListener('mouseup', this.handleMouseup);
      window.removeEventListener('resize', this.resizeFuc);
    });
    this.$nextTick(() => {
      // 获取拖动部分的宽高
      setTimeout(() => {
        let floatTab = this.$refs.floatTab;
        this.height = floatTab?.clientHeight:100;
        this.width = floatTab?.clientWidth:50;
        this.top = this.clientHeight - fixedDirection - this.height;
        // 开始时的距离左侧的距离为窗口宽度-右侧距离-自身宽度
        this.left = this.clientWidth - fixedRightDirection - this.width;
      });
    });
  },
  methods: {
    /** 窗口尺寸发生变化时,防止拖拽的内容被隐藏,能一直显示在页面中 */
    resizeFuc() {
      this.clientHeight = document.documentElement.clientHeight;
      this.clientWidth = document.documentElement.clientWidth;
      // 当竖直方向上窗口的尺寸发生变化,会掩盖住内容的时候、
      if (this.top + this.height + fixedDirection > this.clientHeight) {
        // 重新计算距离顶部的高度
        this.top = this.clientHeight - this.height - this.mouseStartTop;
        console.log('窗口尺寸发生变化', this.top);
      }
      // 当水平方向上窗口的尺寸发生变化,会掩盖住内容的时候、
      if (this.left + this.width + fixedRightDirection !== this.clientWidth) {
        // 重新计算距离顶部的高度
        this.left = this.clientWidth - this.width - fixedRightDirection;
        console.log('窗口尺寸发生变化', this.left);
      }
    },
    /** 释放鼠标,拖动结束*/
    handleMouseup() {
   //解除在window上的监听
    window.removeEventListener('mousemove', this.handleMousemove);
    window.removeEventListener('mouseup', this.handleMouseup);
      console.log('释放鼠标');
      this.dragStatus = false;
      // 松开鼠标内容自动贴在右侧
      this.left = this.clientWidth - this.width - fixedRightDirection;
    },
    /** 鼠标拖动,更改组件内容位置 */
    handleMousemove(e) {
      let clientY = e.clientY;
      let clientX = e.clientX;
      // 计算距离顶部的高度
      if (
        this.dragStatus &&
        clientY + this.height + fixedDirection < this.clientHeight &&
        clientY - this.mouseStartTop > fixedDirection
      ) {
        // 判断当前的位置
        this.top = clientY - this.mouseStartTop;
      }
      // 计算距离左侧的距离
      if (
        this.dragStatus &&
        clientX - this.mouseStartLeft > 0 &&
        this.clientWidth - clientX + this.mouseStartLeft >
          this.width + fixedRightDirection
      ) {
        this.left = clientX - this.mouseStartLeft;
      }
    },
    /** 按下鼠标开始拖动 */
   //注意在使用的时候再往window上绑定鼠标事件,这样减少性能消耗
    handleMousedown(e) {
      // dom中mouseup脱离元素后无法触发,所以要把 mouseup 事件挂载到全局或者 document 上即可
      window.addEventListener('mousemove', this.handleMousemove);
      window.addEventListener('mouseup', this.handleMouseup);
      console.log('按下鼠标', e.clientY, this.top);
      this.dragStatus = true;
      this.mouseStartTop = e.clientY - this.top;
      this.mouseStartLeft = e.clientX - this.left;
    },
  },
};
</script>

<style lang="less" scoped>
.float-tab {
  position: fixed;
  width: 50px;
  height: 100px;
  background: red;
}
</style>

上一篇下一篇

猜你喜欢

热点阅读