div容器拖拽实现方式

拖拽演示.png

实现方式1:方法直接挂在mounted中

<template>
  <div>
    <div class="add_card" ref="dialog_card">
      <div class="content_1" ref="dialog_header">可拖拽区域</div>
      <div>不可拖拽区域</div>
    </div>
  </div>
</template>
<script>
export default {
  name: "custom-clone",
  mounted() {
    this.dialogMove();
  },
  methods: {
    dialogMove() {
      const iframeBox = this.$refs.dialog_card;
      const iframeHeader = this.$refs.dialog_header;
      console.log(iframeBox, "dialog_card============");
      console.log(iframeHeader, "iframeHeader============");

      iframeHeader.onmousedown = function (ev) {
        // 用元素距离视窗的X、Y坐标,减去el元素最近的相对定位父元素的left、top值
        var sX = ev.clientX - iframeBox.offsetLeft;
        var sY = ev.clientY - iframeBox.offsetTop;
        // 不断地更新元素的left、top值
        document.onmousemove = function (ev) {
          iframeBox.style.left = ev.clientX - sX + "px";
          iframeBox.style.top = ev.clientY - sY + "px";
        };
        document.onmouseup = function () {
          document.onmousemove = null;
          document.onmouseup = null;
        };
      };
    },
  },
};
</script>
<style lang="less" scoped>
.add_card {
  width: 400px;
  height: 500px;
  border: 1px solid #eff7ff;
  background-color: #eff7ff;
  position: absolute;
  right: 0;
  top: 0;
  cursor: move;
  z-index: 3000;
  .content_1 {
    height: 100px;
    line-height: 100px;
    background-color: #0780ed;
  }
}
</style>

实现方式2:自定义指令v-drag

drag-min-top设置拖拽上边界,防止拖出可视区域

<template>
  <div>
    <div class="add_card" ref="dialog_card">
      <div class="content_1" v-drag drag-min-top="50" ref="dialog_header">
        可拖拽区域drag
      </div>
      <div>不可拖拽区域</div>
    </div>
  </div>
</template>
<script>
export default {
  name: "custom-clone",
  mounted() {
    // this.dialogMove();
  },
  directives: {
    drag: {
      inserted: function (el) {
        const oDiv = el; // 当前元素
        const minTop = oDiv.getAttribute("drag-min-top");
        const ifMoveSizeArea = 20;
        oDiv.onmousedown = (e) => {
          let target = oDiv;
          while (
            window.getComputedStyle(target).position !== "absolute" &&
            target !== document.body
          ) {
            target = target.parentElement;
          }

          document.onselectstart = () => {
            return false;
          };
          if (!target.getAttribute("init_x")) {
            target.setAttribute("init_x", target.offsetLeft);
            target.setAttribute("init_y", target.offsetTop);
          }
          const initX = parseInt(target.getAttribute("init_x"));
          const initY = parseInt(target.getAttribute("init_y"));
          // 鼠标按下,计算当前元素距离可视区的距离
          const disX = e.clientX - target.offsetLeft;
          const disY = e.clientY - target.offsetTop;
          document.onmousemove = (e) => {
            // 通过事件委托,计算移动的距离
            // 因为浏览器里并不能直接取到并且使用clientX、clientY,所以使用事件委托在内部做完赋值
            const l = e.clientX - disX;
            const t = e.clientY - disY;
            // 计算移动当前元素的位置,并且给该元素样式中的left和top值赋值
            target.style.left = l + "px";
            target.style.top = (t < minTop ? minTop : t) + "px";
            if (
              Math.abs(l - initX) > ifMoveSizeArea ||
              Math.abs(t - initY) > ifMoveSizeArea
            ) {
              target.setAttribute("dragged", "");
            } else {
              target.removeAttribute("dragged");
            }
          };
          document.onmouseup = (e) => {
            document.onmousemove = null;
            document.onmouseup = null;
            document.onselectstart = null;
          };
          // return false不加的话可能导致黏连,拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效
          return false;
        };
      },
    },
  },
};
</script>
<style lang="less" scoped>
.add_card {
  width: 400px;
  height: 500px;
  border: 1px solid #eff7ff;
  background-color: #eff7ff;
  position: absolute;
  right: 0;
  top: 0;
  cursor: move;
  z-index: 3000;
  .content_1 {
    height: 100px;
    line-height: 100px;
    background-color: #0780ed;
  }
}
</style>

全局注册方法

1.新建drag.js

import Vue from "vue"

const drag = Vue.directive('drag', (el) => {
    const oDiv = el // 当前元素
    const minTop = oDiv.getAttribute('drag-min-top')
    const ifMoveSizeArea = 20
    oDiv.onmousedown = e => {
      let target = oDiv
      while (window.getComputedStyle(target).position !== 'absolute' && target !== document.body) {
        target = target.parentElement
      }
  
      document.onselectstart = () => {
        return false
      }
      if (!target.getAttribute('init_x')) {
        target.setAttribute('init_x', target.offsetLeft)
        target.setAttribute('init_y', target.offsetTop)
      }
  
      const initX = parseInt(target.getAttribute('init_x'))
      const initY = parseInt(target.getAttribute('init_y'))
  
      // 鼠标按下,计算当前元素距离可视区的距离
      const disX = e.clientX - target.offsetLeft
      const disY = e.clientY - target.offsetTop
      document.onmousemove = e => {
        // 通过事件委托,计算移动的距离
        // 因为浏览器里并不能直接取到并且使用clientX、clientY,所以使用事件委托在内部做完赋值
        const l = e.clientX - disX
        const t = e.clientY - disY
        // 计算移动当前元素的位置,并且给该元素样式中的left和top值赋值
        target.style.left = l + 'px'
        target.style.top = (t < minTop ? minTop : t) + 'px'
        if (Math.abs(l - initX) > ifMoveSizeArea || Math.abs(t - initY) > ifMoveSizeArea) {
          target.setAttribute('dragged', '')
        } else {
          target.removeAttribute('dragged')
        }
      }
      document.onmouseup = e => {
        document.onmousemove = null
        document.onmouseup = null
        document.onselectstart = null
      }
      // return false不加的话可能导致黏连,拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效
      return false
    }
  })
  export { drag }

2.在入口index.js引入注册

import {drag} from "@/components/module/OPSScheduleManagement/src/components/common/drag"
Vue.prototype.$drag = drag

3.使用

<template>
  <div>
    <div class="add_card" ref="dialog_card">
      <div class="content_1" v-drag drag-min-top="50" ref="dialog_header">
        可拖拽区域drag
      </div>
      <div>不可拖拽区域</div>
    </div>
  </div>
</template>

仓库代码地址:容器拖拽

发表评论 / Comment

用心评论~