vue 指定区域可拖拽的限定拖拽区域的div(如仅弹窗标题可拖拽的弹窗)

简介: vue 指定区域可拖拽的限定拖拽区域的div(如仅弹窗标题可拖拽的弹窗)

<template>
  <div class="container" ref="container">
    <div class="drag-box" v-drag>
      <div class="win_head">弹窗标题</div>
      <div class="win_content">弹窗内容</div>
    </div>
  </div>
</template>

<script>
export default {
  //自定义指令
  directives: {
    drag: {
      // 指令的定义
      bind: function (el, binding, vnode) {
        // 获取到vue实例
        let that = vnode.context;
        let drag_dom = el;
        // 获取到拖拽区
        let drag_handle = el.querySelector(".win_head");
        // 鼠标在拖拽区按下时触发拖拽
        drag_handle.onmousedown = (e) => {
          // 按下鼠标时,鼠标相对于被拖拽元素的坐标
          let disX = e.clientX - drag_dom.offsetLeft;
          let disY = e.clientY - drag_dom.offsetTop;

          // 获取容器dom
          let container_dom = that.$refs.container;

          document.onmousemove = (e) => {
            // 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
            let left = e.clientX - disX;
            let top = e.clientY - disY;

            // 在容器范围内移动时,被拖拽元素的最大left值
            let leftMax =
              container_dom.offsetLeft +
              (container_dom.clientWidth - drag_dom.clientWidth);

            // 在容器范围内移动时,被拖拽元素的最小left值
            let leftMin = container_dom.offsetLeft + 1; //此处+1为容器的边框1px

            if (left > leftMax) {
              drag_dom.style.left = leftMax + "px";
            } else if (left < leftMin) {
              drag_dom.style.left = leftMin + "px";
            } else {
              drag_dom.style.left = left + "px";
            }

            // 在容器范围内移动时,被拖拽元素的最大left值
            let topMax =
              container_dom.offsetTop +
              (container_dom.clientHeight - drag_dom.clientHeight);

            // 在容器范围内移动时,被拖拽元素的最小left值
            let topMin = container_dom.offsetTop + 1; //此处+1为容器的边框1px

            if (top > topMax) {
              drag_dom.style.top = topMax + "px";
            } else if (top < topMin) {
              drag_dom.style.top = leftMin + "px";
            } else {
              drag_dom.style.top = top + "px";
            }
          };

          document.onmouseup = () => {
            document.onmousemove = null;
            document.onmouseup = null;
          };
        };
      },
    },
  },
};
</script>

<style lang="scss" scoped>
.drag-box {
  position: absolute;
  top: 100px;
  left: 100px;
  width: 300px;
  height: 100px;
  background: #fff;
  border-radius: 5px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);

  // 禁止文字被选中
  user-select: none;
}

.container {
  border: 1px solid red;
  width: 600px;
  height: 300px;
  margin: 30px;
}

.win_head {
  background-color: rgb(45, 141, 250);
  color: white;
  height: 30px;
  line-height: 30px;
  font-weight: bold;
  padding-left: 10px;
  cursor: move;
}
.win_content {
  padding: 10px;
}
</style>
目录
相关文章
|
2天前
|
JavaScript
|
1天前
|
存储 缓存 JavaScript
vue代码优化方案
【7月更文挑战第13天】 **Vue.js 优化要点:** 分解大组件以提高复用性和加载速度;利用计算属性与侦听器优化数据处理;使用Object.freeze()减少响应式数据;借助Vuex或Composition API管理状态;实现虚拟滚动和无限加载提升长列表性能;路由懒加载减少初始加载时间;用Vue DevTools检测性能瓶颈;定期代码审查与重构;应用缓存策略;遵循最佳实践与团队规范,提升应用整体质量。
10 2
|
4天前
|
JavaScript 前端开发
【vue】 el-table解决分页不能筛选全部数据的问题
【vue】 el-table解决分页不能筛选全部数据的问题
15 4
|
4天前
|
JavaScript
【vue】 vue2 监听滚动条滚动事件
【vue】 vue2 监听滚动条滚动事件
10 1
|
4天前
|
JavaScript
【vue】el-dialog 内的tinymce弹窗被遮挡的解决办法 及 tinymce打开弹出菜单后直接关闭对话组件,导致该弹出菜单残留
【vue】el-dialog 内的tinymce弹窗被遮挡的解决办法 及 tinymce打开弹出菜单后直接关闭对话组件,导致该弹出菜单残留
16 6
|
4天前
|
JavaScript 定位技术
【天地图】vue 天地图 T is not defined
【天地图】vue 天地图 T is not defined
15 1
|
9天前
|
数据采集 JavaScript 前端开发
Vue框架的优缺点是什么
【7月更文挑战第5天】 Vue框架:组件化开发利于重用与扩展,响应式数据绑定简化状态管理;学习曲线平缓,生态系统丰富,集成便捷,且具性能优化手段。缺点包括社区规模相对小,类型支持不足(Vue 3.x改善),路由和状态管理需额外配置,SEO支持有限。随着发展,部分缺点正被克服。
19 1
|
9天前
|
JavaScript
Vue卸载eslint的写法,单独安装eslint,单独卸载eslint
Vue卸载eslint的写法,单独安装eslint,单独卸载eslint
|
9天前
|
JavaScript
青戈大佬安装Vue,无Eslint安装版,vue2安装,vue2无eslint,最简单配置Vue安装资料
青戈大佬安装Vue,无Eslint安装版,vue2安装,vue2无eslint,最简单配置Vue安装资料
|
4天前
|
JavaScript 前端开发
【vue】 Tinymce 数据 回显问题 | 第一次正常回显后面,显示空白bug不能编辑
【vue】 Tinymce 数据 回显问题 | 第一次正常回显后面,显示空白bug不能编辑
11 0