首先看效果图
PC端
移动端
首先实现拖拽需要知道三个事件,按下,移动和抬起
PC端

鼠标按下事件:onmousedown鼠标移动事件:onmousemove鼠标抬起事件:onmouseup

移动端

1、当在屏幕上按下手指时触发:touchstart2、当在屏幕上移动手指时触发:touchmove3、当在屏幕上抬起手指时触发:touchend4、touchcancel 当一些更高级别的事件发生的时候(如电话接入或者弹出信息)会取消当前的touch操作,即触发
touchcancel。一般会在touchcancel时暂停游戏、存档等操作。

其次知道几个概念
window.outerWidthwindow.outerHeight:获得的是加上工具条与滚动条窗口的宽度与高度。
window.innerWidthwindow.innerHeight:获得的是可视区域的宽高,但是宽度包含了纵向滚动条的宽度。
document.documentElement.clientWidthdocument.documentElement.clientHeight:获得的是屏幕可视区域的宽高,不包括滚动条与工具条,

  • clientY 指的是距离可视页面左上角的距离
  • pageY 指的是距离可视页面左上角的距离(不受页面滚动影响)
  • screenY 指的是距离屏幕左上角的距离
  • layerY 指的是找到它或它父级元素中最近具有定位的左上角距离
  • offsetY 指的是距离它自己左上角的距离

接下来上代码,先绑定PC端的托拽事件

<template><divid="app"@mousedown="move"></div>
</template>
<script>export default {name: "Drag",data() {return {};},methods: {move(e) {e.preventDefault();let odiv = e.target; //获取目标元素//算出鼠标相对元素的位置let disX = e.clientX - odiv.offsetLeft;let disY = e.clientY - odiv.offsetTop;console.log("x======" + disX, "y======" + disY);console.log("offsetLeft======" + odiv.offsetLeft,"offsetTop======" + odiv.offsetTop);console.log(window.innerWidth,window.innerHeight);//可视区域的宽高,但是宽度包含了纵向滚动条的宽度console.log(document.documentElement.clientWidth);//可视区域的宽高,但是宽度不包含了纵向滚动条的宽度console.log(odiv.offsetWidth, odiv.offsetHeight); //元素宽高document.onmousemove = (e) => {//鼠标事件//鼠标按下并移动的事件//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置let left = e.clientX - disX;let top = e.clientY - disY;if (left < 0) {left = 0;}if (left >document.documentElement.clientWidth - odiv.offsetWidth) { //如果元素移动宽度超过屏幕可视高度则为屏幕高度left = document.documentElement.clientWidth - odiv.offsetWidth;}//判断与左边的距离不能超出屏幕可见区域外if (top <0) {top = 0;}if (top >document.documentElement.clientHeight - odiv.offsetHeight) { //如果元素移动高度超过屏幕可视高度则为屏幕高度top =document.documentElement.clientHeight - odiv.offsetHeight;}console.log("left======" + left, "top======" + top);//移动当前元素odiv.style.left = left + "px";odiv.style.top = top + "px";};document.onmouseup = (e) => {document.onmousemove = null;document.onmouseup = null;};},},
};
</script>
<style lang="scss" scoped>
#app {position: absolute; /*定位*/top: 30px;left: 30px;width: 100px;height: 100px;background: red; /*设置一下背景*/z-index: 999;cursor: pointer;
}
</style>

移动端的拖拽事件有点特殊,点击元素获取可视左边的位置的方法不是e.clientX而是e.changedTouches[0].pageX
按下、拖动、松开事件也改变了,接下来上代码

<template><divid="app"@touchstart="touchStart"@touchmove="touchMove"@touchend="touchEnd"></div>
</template><script>export default {name: "Drag",data() {return {touchX: 0,//移动端点击时距左边的距离touchY: 0,odiv: "",};},methods: {//手指按下touchStart(e) {e.preventDefault();this.odiv = e.target; //获取目标元素//算出鼠标相对元素的位置this.touchX = e.changedTouches[0].pageX - this.odiv.offsetLeft;this.touchY = e.changedTouches[0].pageY - this.odiv.offsetTop;console.log("x======" + this.touchX, "y======" + this.touchY);console.log(e);console.log("offsetLeft======" + this.odiv.offsetLeft,"offsetTop======" + this.odiv.offsetTop);console.log("innerWidth====="+window.innerWidth,"innerHeight====="+window.innerHeight);console.log(this.odiv.offsetWidth, this.odiv.offsetHeight); //元素宽高},//手指拖动事件touchMove(e) {//用手指的位置减去手指相对元素的位置,得到元素的位置let left = e.changedTouches[0].pageX - this.touchX;let top = e.changedTouches[0].pageY - this.touchY;console.log("left======" + left, "top======" + top);if (left < 0) {left = 0;}if (left > window.innerWidth - this.odiv.offsetWidth) {left = window.innerWidth - this.odiv.offsetWidth;}//可视区域宽度if (top < 0) {top = 0;}if (top >window.innerHeight - this.odiv.offsetHeight) {top = window.innerHeight - this.odiv.offsetHeight;}//可视区域高度//移动当前元素this.odiv.style.left = left + "px";this.odiv.style.top = top + "px";},//手指抬起touchEnd() {console.log(123)},},
};
</script>
<style lang="scss" scoped>
#app {position: absolute; /*定位*/top: 30px;left: 30px;width: 100px;height: 100px;background: red; /*设置一下背景*/z-index: 999;
}
</style>

TouchEvent事件

综合起来的代码

<template><divid="app"@mousedown="move"@touchstart="touchStart"@touchmove="touchMove"@touchend="touchEnd"></div>
</template><script>export default {name: "Drag",data() {return {touchX: 0,//移动端点击时距左边的距离touchY: 0,odiv: "",};},methods: {move(e) {e.preventDefault();let odiv = e.target; //获取目标元素//算出鼠标相对元素的位置let disX = e.clientX - odiv.offsetLeft;let disY = e.clientY - odiv.offsetTop;console.log("x======" + disX, "y======" + disY);console.log("offsetLeft======" + odiv.offsetLeft,"offsetTop======" + odiv.offsetTop);console.log(window.innerWidth,window.innerHeight);//可视区域的宽高,但是宽度包含了纵向滚动条的宽度console.log(document.documentElement.clientWidth);//可视区域的宽高,但是宽度不包含了纵向滚动条的宽度console.log(odiv.offsetWidth, odiv.offsetHeight); //元素宽高document.onmousemove = (e) => {//鼠标事件//鼠标按下并移动的事件//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置let left = e.clientX - disX;let top = e.clientY - disY;if (left < 0) {left = 0;}if (left >document.documentElement.clientWidth - odiv.offsetWidth) { //如果元素移动宽度超过屏幕可视高度则为屏幕高度left = document.documentElement.clientWidth - odiv.offsetWidth;}//判断与左边的距离不能超出屏幕可见区域外if (top <0) {top = 0;}if (top >document.documentElement.clientHeight - odiv.offsetHeight) { //如果元素移动高度超过屏幕可视高度则为屏幕高度top =document.documentElement.clientHeight - odiv.offsetHeight;}console.log("left======" + left, "top======" + top);//移动当前元素odiv.style.left = left + "px";odiv.style.top = top + "px";};document.onmouseup = (e) => {document.onmousemove = null;document.onmouseup = null;};},//手指按下touchStart(e) {e.preventDefault();this.odiv = e.target; //获取目标元素//算出鼠标相对元素的位置this.touchX = e.changedTouches[0].pageX - this.odiv.offsetLeft;this.touchY = e.changedTouches[0].pageY - this.odiv.offsetTop;console.log("x======" + this.touchX, "y======" + this.touchY);console.log(e);console.log("offsetLeft======" + this.odiv.offsetLeft,"offsetTop======" + this.odiv.offsetTop);console.log("innerWidth====="+window.innerWidth,"innerHeight====="+window.innerHeight);console.log(this.odiv.offsetWidth, this.odiv.offsetHeight); //元素宽高},//手指拖动事件touchMove(e) {//用手指的位置减去手指相对元素的位置,得到元素的位置let left = e.changedTouches[0].pageX - this.touchX;let top = e.changedTouches[0].pageY - this.touchY;console.log("left======" + left, "top======" + top);if (left < 0) {left = 0;}if (left > window.innerWidth - this.odiv.offsetWidth) {left = window.innerWidth - this.odiv.offsetWidth;}if (top < 0) {top = 0;}if (top >window.innerHeight - this.odiv.offsetHeight) {top = window.innerHeight - this.odiv.offsetHeight;}//移动当前元素this.odiv.style.left = left + "px";this.odiv.style.top = top + "px";},//手指抬起touchEnd() {console.log(123)},},
};
</script>
<style lang="scss" scoped>
#app {position: absolute; /*定位*/top: 30px;left: 30px;width: 100px;height: 100px;background: red; /*设置一下背景*/z-index: 999;cursor: pointer;
}
</style>

==========5.20号跟新
上面的版本虽然能实现拖动,但是假如给元素加个比如子元素比如像这样

<template><divid="app"@mousedown="move"@touchstart="touchStart"@touchmove="touchMove"@touchend="touchEnd"><div><h1>我爱我的祖国</h1><p>请不要点到我了</p></div></div>
</template>

用之前的办法取到的e.target是你点到哪个元素就是哪个元素的dom节点,显然这样是不对的,甚至你点击到子元素会使父元素失效。
那么就要用jq来获取元素节点
修改后的代码

<!--此组件需要传入id则可以使用,传入的拖拽功能需在不同页面上-->
<template><divid="app-div"@mousedown="move"@touchstart="touchStart"@touchmove.prevent="touchMove"@touchend="touchEnd"><slot></slot>//插槽,这里可以放子元素</div>
</template><script>
export default {name: "Drag",data() {return {touchX: 0, //移动端点击时距左边的距离touchY: 0,odiv: "",timer: 0,};},methods: {//点击事件click() {//判断是点击事件还是拖动事件},move(e) {e.stopPropagation(); //阻止事件传播// e.preventDefault(); //禁用默认事件,如点击let app = document.getElementById(this.id);let odiv = app; //获取目标元素//算出鼠标相对元素的位置let disX = e.clientX - odiv.offsetLeft;let disY = e.clientY - odiv.offsetTop;this.timer = setTimeout(() => {this.timer = 0;//执行长按事件}, 1000);document.onmousemove = (e) => {//鼠标事件//鼠标按下并移动的事件//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置let left = e.clientX - disX;let top = e.clientY - disY;if (left < 0) {left = 0;}if (left >document.documentElement.clientWidth - odiv.offsetWidth) {//如果元素移动宽度超过屏幕可视高度则为屏幕高度left =document.documentElement.clientWidth - odiv.offsetWidth;} //判断与左边的距离不能超出屏幕可见区域外if (top < 0) {top = 0;}if (top >document.documentElement.clientHeight - odiv.offsetHeight) {//如果元素移动高度超过屏幕可视高度则为屏幕高度top =document.documentElement.clientHeight -odiv.offsetHeight;}// console.log("left======" + left, "top======" + top);//移动当前元素odiv.style.left = left + "px";odiv.style.top = top + "px";};document.onmouseup = (e) => {document.onmousemove = null;document.onmouseup = null;clearTimeout(this.timer);if (this.timer != 0) {//执行单次点击事件this.click();}return false;};return false;},//手指按下touchStart(e) {// e.preventDefault();   //禁用默认事件比如点击e.stopPropagation(); //阻止事件传播let app = document.getElementById(this.id);this.odiv = app; //获取目标元素//算出鼠标相对元素的位置this.touchX = e.changedTouches[0].pageX - this.odiv.offsetLeft;this.touchY = e.changedTouches[0].pageY - this.odiv.offsetTop;this.timer = setTimeout(() => {this.timer = 0;//执行长按事件}, 1000);return false;},//手指拖动事件touchMove(e) {//用手指的位置减去手指相对元素的位置,得到元素的位置let left = e.changedTouches[0].pageX - this.touchX;let top = e.changedTouches[0].pageY - this.touchY;// console.log( "window.innerWidth==375")// console.log(this.odiv.offsetWidth)// console.log("left======" + left, "top======" + top);if (left < 0) {left = 0;}if (left > window.innerWidth - this.odiv.offsetWidth) {left = window.innerWidth - this.odiv.offsetWidth;}if (top < 0) {top = 0;}if (top > window.innerHeight - this.odiv.offsetHeight) {top = window.innerHeight - this.odiv.offsetHeight;}//移动当前元素this.odiv.style.left = left + "px";this.odiv.style.top = top + "px";},//手指抬起touchEnd() {clearTimeout(this.timer);if (this.timer != 0) {//执行单次点击事件this.click();}return false;},},
};
</script>
<style lang="scss" scoped>
#app-div {position: absolute; /*绝对定位*///其余样式自己定义
}
</style>

用vue实现H5页面托拽的div(兼容pc与移动端)相关推荐

  1. js面向对象思想封装拖拽功能,兼容pc和移动端

    我们在开发项目过程中,很可能会碰到页面上某块需要可以拖拽移动的功能需求,网上已经有不少前辈分享了相关功能的案例,插件或者代码,但是考虑到项目功能需求,我们可能仅需要实现拖拽移动功能就可以,不需要其他功 ...

  2. vue支付宝html,Vue的H5页面唤起支付宝支付功能

    目前项目中比较常用的第三方支付无非就是支付宝支付和微信支付.下面介绍一下Vue中H5页面如何使用支付宝支付.其实很简单的,只不过是调自己后台的一个接口而已(后台根据支付宝文档,写好支付接口). 触发支 ...

  3. Vue的H5页面唤起支付宝支付

    目前项目中比较常用的第三方支付无非就是支付宝支付和微信支付.下面介绍一下Vue中H5页面如何使用支付宝支付.其实很简单的,只不过是调自己后台的一个接口而已(后台根据支付宝文档,写好支付接口). 触发支 ...

  4. vue项目H5页面在苹果手机点击输入框输入内容时 页面自动放大

    遇到的问题 用vue写H5页面时,iPhone手机点击input搜索框,输入内容时,页面会自动放大. 解决方法 在public文件夹下找到html文件,打开后加上user-scalable=no 就行 ...

  5. H5页面使用html2canvas实现div生成为图片,保存到手机

    在做微信公众号H5页面时,需求要求html页面生成base64图片,并保存到手机相册中.之前没做过,在网上搜了相关的资料.了解到了html2canvas.js. html2canvas首先将页面生成c ...

  6. 静态html页面如何兼容pc和移动端

    静态html页面如何兼容pc和移动端 在"test.html"文件中的head之间,录入如下代码: <meta name="viewport" conte ...

  7. vue中h5页面的搭建

    在工作中可能会遇到h5页面的搭建,本篇文章主要讲解如何从零开始搭建一个vue项目,实现h5页面的适配,浏览器默认样式的清除,路由的配置,项目的打包等,那就让我们开始学习吧. 如果大家只是需要一个完整的 ...

  8. h5页面转PDF下载(包括pc端和移动端)

    前情:需要在app内嵌的weixin项目将页面转成PDF并下载. 使用技术:html2canvas插件 + jspdf插件 实现思路:1)将h5页面用canvas画成图片 2)利用jspdf将图片插入 ...

  9. vue 编写H5页面在公众号外部获取手机本地坐标经纬度

    1.必须先注册个公众号,且认证后去下面这个地方配置好您的域名这仨地方都得设置,目前我试了下用域名还是用具体项目所在的文件夹目录没什么明显差异 譬如你是用shuzhiqiang.com或者shuzhiq ...

最新文章

  1. rm: cannot remove directory `misc': Device or resource busy
  2. 在ump系统的那半个多月-jqGrid
  3. 基于百度地图API的微信周边搜索
  4. 羡慕,浙江大学的双 11 快递,全部由物流机器人配送
  5. java编写正则表达式引擎_从0到1打造正则表达式执行引擎(一)
  6. 5.录制与回放终端会话.
  7. 解密后的暴风一号病毒(1KB文件夹快捷方式病毒)
  8. 软件项目开发流程以及人员职责,软件工程中五种常用的软件开发模型整理
  9. 字节跳动的面试算法题,实在太变态了
  10. 使用TSMaster从零打造车辆控制器HIL实时仿真系列3-脱离RT的车辆模型的实时仿真
  11. 入行数据分析要知道什么是概括性度量
  12. Could not find resource xxx/xxxx/xxx.xml报错解决
  13. 【钉钉-场景化能力包】CRM销售系统集成
  14. Module 的语法
  15. 数据结构-图-知识点总结
  16. HTML5期末大作业——HTML+CSS+JavaScript平遥古城旅游景点介绍(6页)
  17. 面试题(部分有答案)
  18. 【不专一的开发】UML(二)---行为图(状态图、活动图、序列图、协同图)
  19. R语言获取dataframe数据中某一数据列以某一特定字符串开头的数据行
  20. 【Unity3D】血条(HP)

热门文章

  1. 第四次个人作业——关于微软必应词典android客户端的案例分析
  2. java递归输出杨辉三角,杨辉三角算法 | zhangman523
  3. 必备CAD技能:原来3D的钣金设计这么好用!
  4. JProfiler远程监控
  5. 如何自动备份文件到移动硬盘?
  6. 经济学通识 (第二版) 薛兆丰
  7. 关于List 的一个方法 removeif()
  8. 用maven create创建一个项目,只看到不停在downloading,不知道下载到哪里了,%MAVEN_HOME%里什么都没有。。
  9. K_A08_005 基于 STM32等单片机驱动XY-160D模块按键控制直流电机正反转加减速启停
  10. 002_【SAP精英之路】-SAP GUI的快捷复制粘贴和栅格操作