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 相关文章推荐
Javascript的匿名函数小结
Dec 31 Javascript
一个XML格式数据转换为图表的例子
Feb 09 Javascript
不同浏览器的怪癖小结
Jul 11 Javascript
通过一段代码简单说js中的this的使用
Jul 23 Javascript
js jq 单击和双击区分示例介绍
Nov 05 Javascript
Select2.js下拉框使用小结
Oct 24 Javascript
ionic进入多级目录后隐藏底部导航栏(tabs)的完美解决方案
Nov 23 Javascript
20行JS代码实现网页刮刮乐效果
Jun 23 Javascript
vue使用drag与drop实现拖拽的示例代码
Sep 07 Javascript
Vue的事件响应式进度条组件实例详解
Feb 04 Javascript
浅谈vue加载优化策略
Mar 19 Javascript
vue接通后端api以及部署到服务器操作
Aug 13 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
ip签名探针
2006/10/09 PHP
php的日期处理函数及uchome的function_coomon中日期处理函数的研究
2011/01/12 PHP
destoon找回管理员密码的方法
2014/06/21 PHP
Zend Framework处理Json数据方法详解
2016/12/09 PHP
PHP实现创建一个RPC服务操作示例
2020/02/23 PHP
在js(jquery)中获得文本框焦点和失去焦点的方法
2012/12/04 Javascript
jQuery.prop() 使用详解
2015/07/19 Javascript
jQuery语法小结(超实用)
2015/12/31 Javascript
vue子组件使用自定义事件向父组件传递数据
2017/05/27 Javascript
JavaScript实现无限级递归树的示例代码
2019/03/29 Javascript
亲自动手实现vue日历控件
2019/06/26 Javascript
Echarts地图添加引导线效果(labelLine)
2019/09/30 Javascript
node.js使用http模块创建服务器和客户端完整示例
2020/02/10 Javascript
[01:00:44]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#1COL VS Alliance第三局
2016/03/04 DOTA
python实现批量下载新浪博客的方法
2015/06/15 Python
Python编程修改MP3文件名称的方法
2017/04/19 Python
python操作xlsx文件的包openpyxl实例
2018/05/03 Python
用python3 返回鼠标位置的实现方法(带界面)
2019/07/05 Python
python中读入二维csv格式的表格方法详解(以元组/列表形式表示)
2020/04/24 Python
python右对齐的实例方法
2020/07/05 Python
Matplotlib中rcParams使用方法
2021/01/05 Python
超30万乐谱下载:Musicnotes.com
2016/09/24 全球购物
AMAVII眼镜官网:时尚和设计师太阳镜
2019/05/05 全球购物
Etam德国:内衣精品店
2019/08/25 全球购物
乌克兰珠宝大卖场:Zlato.ua
2020/09/27 全球购物
护理自荐信
2013/10/22 职场文书
工业设计专业推荐信
2013/10/29 职场文书
优秀员工自荐书
2013/12/19 职场文书
后备干部培训方案
2014/05/22 职场文书
医院领导班子查摆问题对照检查材料思想汇报
2014/10/08 职场文书
学校三八妇女节活动总结
2015/02/06 职场文书
教师网络培训心得体会
2016/01/09 职场文书
PHP命令行与定时任务
2021/04/01 PHP
Python+uiautomator2实现自动刷抖音视频功能
2021/04/29 Python
Nginx 反向代理解决跨域问题多种情况分析
2022/01/18 Servers
Vue中使用import进行路由懒加载的原理分析
2022/04/01 Vue.js