vue实现div可拖动位置也可改变盒子大小的原理


Posted in Javascript onSeptember 16, 2020

以下是效果图:实现了div盒子在固定区域的拖动,也可改变盒子的高度和宽度,当超出边距后无法继续改变大小

vue实现div可拖动位置也可改变盒子大小的原理

这里说一下大致原理:拖动和改变大小是分开来操作的,接下来分别说一下

盒子拖动

这里用到了js的三个鼠标事件,分别是onmousedown(鼠标按下)、onmousemove(鼠标移动)以及onmouseup(鼠标松开),大致流程就是鼠标按下拖动图标进行拖动时,动态获取当前div的left和top再重新赋值给当前div的top、left值,当鼠标松开再清除事件,至于固定在某个区域内拖动,在赋值的时候判断当前top及left值是否超过限制区域的值,如果超过给最大值最小值

盒子改变大小

这里用到的也是盒子拖动的三个事件,当鼠标移入盒子左边框触发mousemove事件,动态计算盒子宽度重新赋值,鼠标松开注销mousrmove事件,我将宽度和高度改变分别封装了组件,用的时候直接调用就好

博主用的vue写的,这里展示的也是铜鼓vue书写的,其他都是大同小异,知道原理就好

// index.vue
<template>
 <!-- demo -->
 <div class="demo" id="maxBoxId">
  <div
   :id="moveInfo.dragId"
   :style="
    'width:' +
    moveInfo.width +
    'px; left:' +
    moveInfo.coordinate.x +
    'px; top:' +
    moveInfo.coordinate.y +
    'px; height:' +
    moveInfo.height +
    'px'
   "
   class="drag-class"
  >
   <div class="drag-content">
    <div class="content-text">
     <!-- 拖拽图标 -->
     <div class="drag-icon">
      <i
       class="iconfont icon-tuodong1 down-dragger"
       @mousedown.stop="dragDiv($event)"
       @mouseup.stop="dragUp($event)"
      ></i>
     </div>
     {{ moveInfo.text }}
    </div>
    <!-- 宽度改变组件 -->
    <ChangeWidth :moveId="moveInfo.moveId" index="0" @widthChange="changeWidth" @clearEvent="clearEvent" />
    <!-- 高度改变组件 -->
    <ChangeHeight :moveId="moveInfo.moveId" index="1" @heightChange="heightChange" @clearEvent="clearEvent" />
   </div>
  </div>
 </div>
</template>
 
<script>
import ChangeWidth from '../component/ChangeWidth'
import ChangeHeight from '../component/ChangeHeight'
export default {
 components: { ChangeWidth, ChangeHeight },
 name: 'demo',
 data() {
  return {
   moveInfo: {
    dragId: 'smallDragBoxId',
    moveId: 'smallMoveBoxId',
    text: '我是拖动的小盒子',
    width: 400,
    height: 100,
    // 上边距和左边距
    coordinate: {
     x: 180,
     y: 10
    }
   }
  }
 },
 methods: {
  // 区块拖动
  dragDiv(el, index) {
   // dragId: 可拖动区域唯一标识
   // moveId: 改变宽度组件唯一标识
   const { dragId, coordinate } = this.moveInfo
   let obig = document.getElementById('maxBoxId')
   let osmall = document.getElementById(dragId)
   // 用于保存小的div拖拽前的坐标
   osmall.startX = el.clientX - osmall.offsetLeft
   osmall.startY = el.clientY - osmall.offsetTop
   document.onmousemove = e => {
    let left, top
    left = e.clientX - osmall.startX
    top = e.clientY - osmall.startY
    osmall.style.left = left + 'px'
    osmall.style.top = top + 'px'
    coordinate.x = left
    coordinate.y = top
    if (left <= 0) {
     osmall.style.left = 0 + 'px'
     coordinate.x = 0
    }
    if (top <= 0) {
     osmall.style.top = 0 + 'px'
     coordinate.y = 0
    }
    if (left >= obig.offsetWidth - osmall.offsetWidth) {
     osmall.style.left = obig.offsetWidth - osmall.offsetWidth + 'px'
     coordinate.x = obig.offsetWidth - osmall.offsetWidth
    }
    if (top >= obig.offsetHeight - osmall.offsetHeight) {
     osmall.style.top = obig.offsetHeight - osmall.offsetHeight + 'px'
     coordinate.y = obig.offsetHeight - osmall.offsetHeight
    }
   }
  },
  dragUp(el) {
   document.onmousemove = null
   document.onmouseup = null
   // 调用接口保存数据
  },
  // 改变drag宽度尺寸
  changeWidth(params) {
   const { index, width } = params
   let left
   const { dragId } = this.moveInfo
   // let obig = document.getElementById('maxBoxId')
 
   let osmall = document.getElementById(dragId)
   let boxWidth = document.getElementById('maxBoxId').offsetWidth
   left = osmall.style.left
   const newWidth = this.moveInfo.width + width
   // outWidth拖动宽度时超出box的宽度
   const outWidth = Number(left.slice(0, left.length - 2)) + Number(newWidth) - Number(boxWidth)
   // 如果超出box将截取留下的
   if (outWidth >= 0) {
    this.moveInfo.width = Number(boxWidth) - Number(left.slice(0, left.length - 2))
   } else {
    this.moveInfo.width = newWidth
   }
   // 设置div的最小宽度和最大宽度
   if (this.moveInfo.width < 200) {
    this.moveInfo.width = 200
   }
   if (this.moveInfo.width > 900) {
    this.moveInfo.width = 900
   }
  },
  // 改变drag高度
  heightChange(params) {
   const { index, height } = params
   let top
   let osmall = document.getElementById(this.moveInfo.dragId)
   let boxHeight = document.getElementById('maxBoxId').offsetHeight
   top = osmall.style.top
   const newHeight = this.moveInfo.height + height
   // outHeight拖动宽度时超出box的高度
   const outHeight = Number(top.slice(0, top.length - 2)) + Number(newHeight) - Number(boxHeight)
   // 如果超出box将截取留下的
   if (outHeight >= 0) {
    this.moveInfo.height = Number(boxHeight) - Number(top.slice(0, top.length - 2))
   } else {
    this.moveInfo.height = newHeight
   }
   // 设置div的最小宽度和最大宽度
   if (this.moveInfo.height < 100) {
    this.moveInfo.height = 100
   }
   if (this.moveInfo.height > 200) {
    this.moveInfo.height = 200
   }
  },
  // 清除鼠标事件
  clearEvent() {
   document.onmousemove = null
   document.onmouseup = null
  }
 }
}
</script>
<style lang="scss" scoped>
.demo {
 position: relative;
 width: 100%;
 z-index: 10;
 width: 1200px;
 background: red;
 height: 300px;
 margin-bottom: 1000px;
 margin-left: 100px;
 .drag-class {
  background: rgba(255, 255, 255, 0);
  position: absolute;
  .drag-content {
   position: relative;
   height: 100%;
   .content-text {
    border: 1px dashed #ffffff;
    font-size: 34px;
    color: #ffffff;
    margin-top: 5px;
    position: relative;
    height: 100%;
    .drag-icon {
     position: absolute;
     right: 10px;
     top: 5px;
     float: left;
     // margin-right: 10px;
     .down-dragger {
      cursor: move;
      font-size: 30px;
      color: #dbdce0;
      color: #ffffff;
     }
    }
   }
  }
 }
}
</style>

以下是改变大小的组件

<template>
 <!-- 拖动右边距改变div宽度 -->
 <div :id="`width${moveId}`" class="x-handle" @mousedown="mouseDown"></div>
</template>
 
<script>
export default {
 name: 'ChangeWidth',
 props: ['index', 'moveId'],
 data() {
  return {
   lastX: ''
  }
 },
 
 created() {
  document.addEventListener('mouseup', this.mouseUp)
 },
 
 destroyed() {
  document.removeEventListener('mouseup', this.mouseUp)
 },
 
 methods: {
  mouseDown(event) {
   document.addEventListener('mousemove', this.mouseMove)
   this.lastX = event.screenX
  },
  mouseMove(e) {
   this.$emit('widthChange', { width: e.screenX - this.lastX, index: this.index })
   this.lastX = e.screenX
  },
  mouseUp() {
   this.lastX = ''
   document.removeEventListener('mousemove', this.mouseMove)
   this.$emit('clearEvent')
  }
 }
}
</script>
<style lang="less" scoped>
.x-handle {
 width: 5px;
 cursor: e-resize;
 background: #2866f0;
 height: 30px;
 position: absolute;
 right: 0;
 top: 40%;
}
</style>

改变高度的组件原理和宽度一样,避免代码重复就不上传了

上面就是大致流程和源码。

总结

到此这篇关于vue实现div可拖动位置也可改变盒子大小的文章就介绍到这了,更多相关vue 实现div拖动位置内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jQuery Ajax之load()方法
Oct 12 Javascript
网页中返回顶部代码(多种方法)另附注释说明
Apr 24 Javascript
解析jquery中的ajax缓存问题
Dec 19 Javascript
JavaScript实现自动消除按钮功能的方法
Aug 05 Javascript
实例解析JS布尔对象的toString()方法和valueOf()方法
Oct 25 Javascript
详解JavaScript数组和字符串中去除重复值的方法
Mar 07 Javascript
详解XMLHttpRequest(一)同步请求和异步请求
Sep 14 Javascript
详解vuex之store源码简单解析
Jun 13 Javascript
通过JQuery,JQueryUI和Jsplumb实现拖拽模块
Jun 18 jQuery
微信小程序 WXML节点信息查询详解
Jul 29 Javascript
JS实现基本的网页计算器功能示例
Jan 16 Javascript
详解Vue之事件处理
Jul 10 Javascript
Vue项目打包编译优化方案
Sep 16 #Javascript
Vue封装Axios请求和拦截器的步骤
Sep 16 #Javascript
如何在JS文件中获取Vue组件
Sep 16 #Javascript
javascript自定义加载loading效果
Sep 15 #Javascript
图解JS原型和原型链实现原理
Sep 15 #Javascript
vue实现简单全选和反选功能
Sep 15 #Javascript
vscode 调试 node.js的方法步骤
Sep 15 #Javascript
You might like
phpMyAdmin2.11.6安装配置方法
2008/08/24 PHP
PHP中把对象转换为关联数组代码分享
2015/04/09 PHP
ThinkPHP模板循环输出Volist标签用法实例详解
2016/03/23 PHP
Laravel使用RabbitMQ的方法示例
2019/06/18 PHP
Laravel自定义 封装便捷返回Json数据格式的引用方法
2019/09/29 PHP
各种页面定时跳转(倒计时跳转)代码总结
2013/10/24 Javascript
JavaScript框架(iframe)操作总结
2014/04/16 Javascript
jquery插件之定时查询待处理任务数量
2014/05/01 Javascript
在Html中使用Requirejs进行模块化开发实例详解
2016/04/15 Javascript
浅析JS异步加载进度条
2016/05/05 Javascript
微信小程序图片自适应支持多图实例详解
2017/06/21 Javascript
微信小程序block的使用教程
2018/04/01 Javascript
LayUi中接口传数据成功,表格不显示数据的解决方法
2018/08/19 Javascript
如何换个角度使用VUE过滤器详解
2019/09/11 Javascript
React-redux实现小案例(todolist)的过程
2019/09/29 Javascript
vue+element树组件 实现树懒加载的过程详解
2019/10/21 Javascript
vue中后端做Excel导出功能返回数据流前端的处理操作
2020/09/08 Javascript
三剑客:offset、client和scroll还傻傻分不清?
2020/12/04 Javascript
[46:47]完美世界DOTA2联赛PWL S2 FTD vs Magma 第二场 11.20
2020/11/23 DOTA
python中getattr函数使用方法 getattr实现工厂模式
2014/01/20 Python
python实现在windows服务中新建进程的方法
2015/06/30 Python
python制作一个桌面便签软件
2015/08/09 Python
Python中防止sql注入的方法详解
2017/02/25 Python
详解Python if-elif-else知识点
2018/06/11 Python
使用Python做垃圾分类的原理及实例代码附源码
2019/07/02 Python
使用Python制作新型冠状病毒实时疫情图
2020/01/28 Python
python实现最速下降法
2020/03/24 Python
pandas 强制类型转换 df.astype实例
2020/04/09 Python
Django models文件模型变更错误解决
2020/05/11 Python
波兰购物网站:MALL.PL
2019/05/01 全球购物
将n个数按输入顺序的逆序排列,用函数实现
2012/11/14 面试题
采购助理岗位职责
2014/02/16 职场文书
企业愿景口号
2015/12/25 职场文书
Python爬虫之爬取某文库文档数据
2021/04/21 Python
Python捕获、播放和保存摄像头视频并提高视频清晰度和对比度
2022/04/14 Python
项目中Nginx多级代理是如何获取客户端的真实IP地址
2022/05/30 Servers