这是现在的效果,可能改了一些,原来的效果是,里面的这张图是可以上下左右拖动的,然后房子上面的显示的楼栋号,也跟着图片一起移动,当时js能力还不行,未能实现项目经理的要求,不过后来项目经理又把这个效果推掉了,换了另外的一个效果

尽管项目经理不想要这个效果了,但是当时就在我心里留下了一个节,到今天都忘不了这个梗。

好了,这就是我今天想写这篇博客的初衷,希望能给想实现这类拖拽效果,但是不知道该怎么去实现的同学,提供一种思路,不给青春留遗憾,当然实现拖拽的方法有很多,这里就只介绍JavaScript中的一种方法,慢慢体会一下其中的原理!

好了,梗也说完了,开始正题,我们先要明白,拖拽到底是一个什么东西,你也知道,我也知道,但是我还是想来描述一下:

拖拽就是一个容器,你用鼠标可以在页面上拖着到处跑,废话,精确的描述应该是,鼠标移到容器上,然后鼠标按下去,注意要按着不放,然后拖动鼠标,容器能跟着鼠标跑,松开鼠标,容器就停在那里不动了,现实中的例子就是桌子上有一个盒子,我用手放在盒子上,然后移动盒子,手停盒子停,手拿开,盒子不动了,嘻嘻,都懂了哈!

别以为上面说了一堆的废话,我们可以从中得到很多的信息,总结如下就是:

拖拽 = 鼠标按下 + 鼠标移动 + 鼠标弹上

这样就完成了一个拖拽任务,好了,原来这就是拖拽的原理,想实现拖拽,自然实现上面的3个动作,便可以模拟拖拽效果,好,对应JavaScript中的语法就是需要实现这3个动作:

onmousedown , onmousemove , onmouseup

实现的代码就应该是:

obj.onmousedown = function(ev){obj.onmousemove = function(ev){} ;obj.onmouseup = function(ev){};}

  

为什么后面2个动作要写的里面,好好回味一下,好了,第一步的大概思路就有了,下一步就需要考虑怎么让物体跟着鼠标一起移动,思路大概是这样的:

首先物体是需要决定定位的,因为我们需要操作它的left和top值,才能让它移动,然后就是要考虑鼠标了,鼠标位移,本身就会有一个距离,如果我们知道鼠标移动了多远,然后把这个距离给物体,那物体是不是也和鼠标一样,移动了相同的距离,这不就实现拖拽了吗?哈哈,思路一点点有,感觉萌萌哒~ 现在的问题就是怎么获取鼠标的距离,如果需要深入了解,请复习一下盒子模型,这里我就不说了,很多大神也有相关的博客,我用一张图表示一下:

说明:蓝色框为屏幕宽高,黑色粗框为浏览器可视区宽高(浏览器缩小效果),黑色细框为鼠标要拖拽的对象,如图可知,获取鼠标的坐标,可以用event.clientX,event.clientY来获取,哦了;

计算的大致原理可以参照下图:

说明:左边为初始位置,右边为目标位置,原点为鼠标位置,大黑框为浏览器可视宽度,小黑框为拖拽对象,看拖拽对象到目标位置的状态,获取鼠标的最终位置,再减去鼠标距离对象的差值,再赋值给对象的top,left值,也可以获取鼠标的位置差值,再用初始的top,left值加上差值,我们采用第一种,第二种也可以,自己去试一下:

obj.onmousedown = function(ev){var ev = ev || event;var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;document.onmousemove = function(ev){var ev = ev || event;obj.style.left = ev.clientX - disX + 'px';obj.style.top = ev.clientY - disY + 'px';};document.onmouseup = function(ev){var ev = ev || event;document.onmousemove = document.onmouseup = null;};
}

  

这里说明一下:onmousemove和onmouseup之所以用document对象而不用obj对象,是因为如果用obj对象,鼠标在obj内部还好,如果在obj外面的话,拖拽会很怪异,你也可以改成obj体会一下,最后我们在鼠标弹起的时候将事件都清空;

上面的基本拖拽就算完成了,但是细心的同学一定会问,如果页面上有文字的话,拖拽物体会将文字选中,这效果岂不是怪怪的,没错,这是因为拖拽的时候触发了浏览器的默认选择事件,所以,在拖拽的时候,我们要清除这个默认事件,那怎么清除呢?

下面给一个兼容性写法:

if(ev.stopPropagation){ev.stopPropagation();
}else{ev.cancelBubble = true; //兼容IE
}
//简写成
ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;

  

将上面的代码放在onmousedown下,鼠标按下就清除浏览器默认事件,文字就不会被选中了,好了,一个简单的拖拽效果就完成了,当然你现在是看不到效果,之所以不给demo链接是为了让你自己试着写一写,这样印象更深刻,

好了,那问题又来了,到这里就这样完了吗?。。。。。。按本人的风格,当然没有,干货还在后面!

如果我想实现这样一个效果,就是这一个大的容器里面(可以是box,也可以是document),怎么样能让我们的拖拽对象不跑出去呢,换句话说,拖到边缘就拖不动了,耶,是不是很多人想要实现的效果,哈哈,我们看看实现的原理是什么:

现实生活中,一个物体在一个盒子里跑不出去,是因为有堵墙,那我们只要能模拟出这堵墙,就可以把物体框起来,那这堵墙要怎么做呢?我们可以换个思路,当拖拽对象拖到边缘的时候,比如说拖到右边,我们将它的left固定住,是不是就不能再往右了,因为left值不能再加了,那么拖到底部,同理我们将top值固定住,就不能再往下拖了,理解吗?

最终的结果就是如下:

//左侧
if(obj.offsetLeft <=0){obj.style.left = 0;
};
//右侧
if(obj.offsetLeft >= pWidth - oWidth){obj.style.left =  pWidth - oWidth + 'px';
};
//上面
if(obj.offsetTop <= 0){obj.style.top = 0;
};
//下面
if(obj.offsetTop >= pHeight - oHeight){obj.style.top =  pHeight - oHeight + 'px';
};

  

说明:pWidth,pHeight 表示父级元素的宽高(这里是表示相对于父级的宽高限制),oWidth,oHeigt表示拖拽元素的宽高

最后,我将整个拖拽代码整理了一下:

/*参数说明:元素绝对定位,父级相对定位,如果父级为window,则可以不用传一个参数,表示父级为window,物体相对于window范围拖动传2个参数,则父级为第二个参数,物体相对于父级范围拖动参数为id值*/function drag(obj,parentNode){var obj = document.getElementById(obj);if(arguments.length == 1){var parentNode = window.self;  var pWidth = parentNode.innerWidth,pHeight = parentNode.innerHeight;   }else{var parentNode = document.getElementById(parentNode);var pWidth = parentNode.offsetWidth,pHeight = parentNode.offsetHeight;}obj.onmousedown = function(ev){var ev = ev || event;var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;var oWidth = obj.offsetWidth,oHeight = obj.offsetHeight;//阻止冒泡时间ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;document.onmousemove = function(ev){var ev = ev || event;obj.style.left = ev.clientX - disX + 'px';obj.style.top = ev.clientY - disY + 'px';//左侧if(obj.offsetLeft <=0){obj.style.left = 0;};//右侧if(obj.offsetLeft >= pWidth - oWidth){obj.style.left =  pWidth - oWidth + 'px';  };//上面if(obj.offsetTop <= 0){obj.style.top = 0; };//下面if(obj.offsetTop >= pHeight - oHeight){obj.style.top =  pHeight - oHeight + 'px'; };};document.onmouseup = function(ev){var ev = ev || event;document.onmousemove = document.onmouseup = null;};}}

  说明:我这里处理的效果是,如果传一个参数,表示相对的对象是window对象,如果传2个参数,第一个是拖拽对象,第二个为相对父级

css:

<style>
.box{width:600px;height:400px;margin:50px auto;position:relative;overflow:hidden;
}
#box{width:1000px;height:800px;position:absolute;left:50%;top:50%;margin:-400px 0 0 -500px;
}
#pic{ width:800px; height:600px; background:url(images/pic1.jpg) no-repeat; position:absolute; left:100px; top:100px; }
#pic:hover{cursor:move;
}
</style>

  html:

<div class="box"><div id="box"><div id="pic"></div></div></div>

  js:

window.onload = function(){drag("pic","box");function drag(obj,parentNode){var obj = document.getElementById(obj);if(arguments.length == 1){var parentNode = window.self;  var pWidth = parentNode.innerWidth,pHeight = parentNode.innerHeight;   }else{var parentNode = document.getElementById(parentNode);var pWidth = parentNode.offsetWidth,pHeight = parentNode.offsetHeight;}obj.onmousedown = function(ev){var ev = ev || event;var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;var oWidth = obj.offsetWidth,oHeight = obj.offsetHeight;//阻止冒泡时间ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;document.onmousemove = function(ev){var ev = ev || event;obj.style.left = ev.clientX - disX + 'px';obj.style.top = ev.clientY - disY + 'px';//左侧if(obj.offsetLeft <=0){obj.style.left = 0;};//右侧if(obj.offsetLeft >= pWidth - oWidth){obj.style.left =  pWidth - oWidth + 'px';  };//上面if(obj.offsetTop <= 0){obj.style.top = 0; };//下面if(obj.offsetTop >= pHeight - oHeight){obj.style.top =  pHeight - oHeight + 'px'; };};document.onmouseup = function(ev){var ev = ev || event;document.onmousemove = document.onmouseup = null;};}}}

  效果完全是用的那个封装代码块,引用起来也挺方便,有人会问了,你这用的id获取DOM元素,一个页面只能用一次啊,如果页面多次使用呢,有道理,解决方案之一,那就命名不同的id呗,又不犯法,方案二,获取id的地方改成获取class,但是要注意的是,getElementsByClassName是获取的class集合,需要改写一下,这里我就不写了,有兴趣的同学自行改写一下,好了,到这里真的结束了!

转载于:https://www.cnblogs.com/xupeiyu/p/5275983.html

javascript小实例,PC网页里的拖拽(转)相关推荐

  1. 简单计算器——JavaScript小实例

    简单计算器--JavaScript小实例 先来看一下下我们要做的计算器(以iQOO neo5手机计算器为例): 这就是我们今天要做的计算器的模板,成品的样子会略有不同,但功能完善. 好,当我们看到这个 ...

  2. jquery回弹_创意网页DOM元素拖拽弹性反弹和变形动画特效

    这是一款非常有创意的HTML网页DOM元素拖拽弹性反弹和变形动画特效.这个特效中有两种效果:第一种是弹性模态窗口效果,第二种是弹性幻灯片效果.这两种效果均可以拖拽DOM元素,然后释放它们时生成非常震撼 ...

  3. 微信小程序图片上传九宫格拖拽组件

    微信小程序图片上传&九宫格拖拽组件 前言 图片上传加九宫格拖拽是一个比较常用的组件,常用于发帖或者评论等内容上传模块,我这篇九宫格拖拽的思路是借鉴了一款优雅的小程序拖拽排序组件实现这篇文章 实 ...

  4. 如何提取小程序/APP/网页里图片视频,小程序APP素材抓取软件批量下载图片音频?

    通常我们在看到某一个好的小程序素材想下载来参考时?会思考以下问题: "怎么下载别人小程序里的图标呀?" "怎么抓取小程序的图片.图标之类的?" "怎么 ...

  5. JavaScript实现网页元素的拖拽效果

    以下的页面中放了两个div,能够通过鼠标拖拽这两个元素到任何位置. 实现该效果的HTML页面代码例如以下所看到的: <!DOCTYPE html> <html> <hea ...

  6. 99乘法表带颜色HTML隔行变色,javascript小实例,实现99乘法表及隔行变色

    人生短暂,废话不多说,直奔主题! 这个小实例的要求: 实现在页面中输出99乘法表.(要求:以每三行为一组,实现隔行变色(颜色为白,红,黄(也可自己定义)),鼠标滑过每一行,行背景颜色变为蓝色,鼠标离开 ...

  7. uni map地图相关使用小计(多点标识,拖拽起点,地图画圆)

    这次的项目用到了地图,特别记录下 小程序不执行地图相关事件时候,看下小程序的调试基础库 进行多点标注时候,经纬度要正确,图标设置50就好了,ID是一定得绑定的. 动态传参时候如果需要保留之前的标注点就 ...

  8. 微信小程序~触摸相关事件(拖拽操作、手势识别、多点触控)

    touchstart 手指触摸动作开始 touchmove 手指触摸后移动 touchcancel 手指触摸动作被打断,如来电提醒,弹窗 touchend 手指触摸动作结束 拖拽操作案例1:(注意按钮 ...

  9. javascript小实例,多种方法实现数组去重问题

    废话不多说,直接拿干货! 先说说这个实例的要求:写一个方法实现数组的去重.(要求:执行方法,传递一个数组,返回去重后的新数组,原数组不变,实现过程中只能用一层循环,双层嵌套循环也可写,只做参考): 先 ...

最新文章

  1. 企业中常用的几种文件传输方法介绍
  2. Log4Net五步走
  3. java instanceof运算符_Java instanceof 运算符的使用方法
  4. 牛客网【每日一题】7月8日 Alliances
  5. python 计量经济 35岁 工作_Python在计量经济与统计学中的应用
  6. makefile之引用(3)
  7. [bbk2907]第3集 - Chapter 02 - RAC的安装过程中需要注意的要点
  8. @@IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT
  9. 配置Visual Studio Code用作51单片机C51代码编辑器,替代KeilC编辑代码事半功倍!
  10. 北京地区2009年春运火车票购买指南(V2.5)
  11. memcached介绍与作用和它的工作原理
  12. 大公司都在用的招聘分析模型,会EXCEL就行,白嫖党不要错过
  13. 励志语录关于奋斗青春
  14. Oracle中文排序 NLSSORT
  15. 《赐我》-一只白羊 同步歌词
  16. 如何安装虚拟机———一台电脑,多个系统体验
  17. Android 百度地图marker中图片不显示的解决方案
  18. rtmp一些状态信息详解-as连接FMS服务器报错状态汇总~~
  19. 动态分析Android App之动态调试
  20. 分辨率不同的ubuntu扩展显示器记录

热门文章

  1. vue-cli 如何打包上线的方法示例
  2. CSS媒体查询 @media
  3. 如何做一个听话的 “输入框”
  4. 总结Unity 初学者容易犯的编译与运行时错误(第三部分)
  5. ionic+angularjs开发hybrid App(环境配置+创建测试项目)
  6. Pinging ? with 32 bytes of data 故障解决
  7. rhel6硬盘或U盘安装注意的问题
  8. asp.net MVC2 初探四
  9. 在Eclipse上安装Activiti插件
  10. html+css常用小笔记(持续更新)