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的朋友一点学习经验小结
Nov 23 Javascript
jquery索引在使用中的一些困惑
Oct 24 Javascript
使用JQUERY进行后台页面布局控制DIV实现左右式
Jan 07 Javascript
JS中捕获console.log()输出的方法
Apr 16 Javascript
jQuery横向擦除焦点图特效代码分享
Sep 06 Javascript
jQuery判断浏览器并动态调整select宽度的方法
Mar 02 Javascript
jquery的ajax提交form表单的两种方法小结(推荐)
May 25 Javascript
正则表达式(语法篇推荐)
Jun 24 Javascript
如何抽象一个Vue公共组件
Oct 17 Javascript
AngularJS 教程及实例代码
Oct 23 Javascript
微信小程序实现列表下拉刷新上拉加载
Jul 29 Javascript
微信小程序支付前端源码
Aug 29 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
2020最新CPU的性能排名
2020/04/02 数码科技
PHP实现采集程序原理和简单示例代码
2007/03/18 PHP
用php或asp创建网页桌面快捷方式的代码
2010/03/23 PHP
php用户注册时常用的检验函数实例总结
2014/12/22 PHP
PHP实现采集抓取淘宝网单个商品信息
2015/01/08 PHP
php生成固定长度纯数字编码的方法
2015/07/09 PHP
深入分析PHP优化及注意事项
2016/07/04 PHP
一些有关检查数据的JS代码
2006/09/07 Javascript
javascript appendChild,innerHTML,join性能比较代码
2009/08/29 Javascript
关于JavaScript的面向对象和继承有利新手学习
2013/01/11 Javascript
JavaScript中使用typeof运算符需要注意的几个坑
2014/11/08 Javascript
原生JS实现首页进度加载动画
2016/09/14 Javascript
Vue自定义指令介绍(2)
2016/12/08 Javascript
JavaScript表单验证完美代码
2017/03/02 Javascript
bootstrap IE8 兼容性处理
2017/03/22 Javascript
Ajax异步文件上传与NodeJS express服务端处理
2017/04/01 NodeJs
使用ionic播放轮询广告的实现方法(必看)
2017/04/24 Javascript
详解Vue2.x-directive的学习笔记
2017/07/17 Javascript
JS中使用new Option()实现时间联动效果
2018/12/10 Javascript
NestJs 静态目录配置详解
2019/03/12 Javascript
在vue中阻止浏览器后退的实例
2019/11/06 Javascript
浅谈Vue SSR中的Bundle的具有使用
2019/11/21 Javascript
antd vue 刷新保留当前页面路由,保留选中菜单,保留menu选中操作
2020/08/06 Javascript
Openlayers实现点闪烁扩散效果
2020/09/24 Javascript
微信小程序canvas实现签名功能
2021/01/19 Javascript
python中(str,list,tuple)基础知识汇总
2018/02/20 Python
python matlibplot绘制3D图形
2018/07/02 Python
python实现祝福弹窗效果
2019/04/07 Python
简单了解Python matplotlib线的属性
2019/06/29 Python
Python-numpy实现灰度图像的分块和合并方式
2020/01/09 Python
Python获取对象属性的几种方式小结
2020/03/12 Python
台湾屈臣氏网路商店:Watsons台湾
2020/12/29 全球购物
机械绘图员岗位职责
2013/11/19 职场文书
忆童年!用Python实现愤怒的小鸟游戏
2021/06/07 Python
Python制作春联的示例代码
2022/01/22 Python
动画《平凡职业成就世界最强》宣布制作OVA
2022/04/01 日漫