可拖动弹窗的JS和jQuery两种写法
Posted 云牧
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可拖动弹窗的JS和jQuery两种写法相关的知识,希望对你有一定的参考价值。
最近在慕课网上学习了一个网页可拖动对话框js实现的演示视频,这个demo中的例子是百度首页登录按钮的弹窗,如下图:
当点击左上角的登录按钮时,弹窗出现并自动居中,同时窗口可拖动的范围被限制在了可视区域内,即浏览器视窗的上下左右边界,弹窗无法移出移动出四个边界,也不会出现滚动条。
另一个效果就是,当改变窗口大小时,对话框自动居中。
这个视频中用了原生js,jQuery两种写法实现案例,但本质上,对话框居中,限制拖动范围的的计算思路是一致的。
为了简化页面,总结核心思路,我重新写了一个小demo,界面如下:
依旧保持着点击弹出按钮,对话框自动居中,拖动范围限制,改变窗口大小弹窗居中等效果,下面是本demo的html结构和CSS布局代码:
HTML结构代码
<div id="callout" class="button callout_button"><a href="#">弹出对话框</a></div> <div id="mask" class="mask"></div> <div class="dialog" id="dialog"> <div class="dialog_head" id="move_part">可拖拽部分</div> <div class="dialog_content"></div> <div class="button close_button" id="close"><a href="#">点我关闭对话框</a> </div> </div>
CSS样式代码
<style type="text/css"> a{text-decoration: none; color: #eee; display: block;} .button{width: 200px; height: 50px; border-radius: 20px; text-align:center;line-height: 50px;} .callout_button{background:#FF5B5B;margin:0 auto; } .callout_button:hover{background: red;} .close_button{background:#363636;margin:0 auto;} .close_button:hover{background: black;} .mask{width: 100%;height: 100%;background:#000;position: absolute;top: 0px;left:0px;opacity: 0.4;z-index: 8000; display: none;-moz-user-select: none; -webkit-user-select: none;} .dialog{width: 380px;background:#fff; position: absolute;z-index: 9000;padding-bottom: 10px; display: none;-moz-user-select: none; -webkit-user-select: none;} .dialog_head{width: 100%;height:50px;background:#4B4B4B;text-align: center;line-height: 50px;color: #eee; cursor: move;} .dialog_content{width: 100%;height:300px;} </style>
下面是重点的JS部分,先介绍
一、原生JS的写法:
这里有一个比较实用的技巧,首先定义一个g()函数用于获取对象
function g(id){return document.getElementById(id)};
这个函数用起来很方便,用于获取对象,在原生JS种可以少写很多代码,有一点JS封装的思想(感觉上,不知道说的对不对)。
弹出和关闭对话框
//点击弹出对话框 g(\'callout\').onclick = function(){ g(\'dialog\').style.display = \'block\'; g(\'mask\').style.display = \'block\'; autoCenter(g(\'dialog\')); }; //点击关闭对话框 g(\'close\').onclick = function(){ g(\'dialog\').style.display = \'none\'; g(\'mask\').style.display = \'none\'; };
点击拖动对话框有个重要的内容就是要设置对话框内容不可被选中
//禁止选中对话框内容 if(document.attachEvent) {//ie的事件监听,拖拽div时禁止选中内容,firefox与chrome已在css中设置过-moz-user-select: none; -webkit-user-select: none; g(\'dialog\').attachEvent(\'onselectstart\', function() { return false; }); }
点击弹出对话框中代码中的autoCenter()函数,让对话框保持自动居中
function autoCenter(el){ //获取可见窗口大小 var bodyW = document.documentElement.clientWidth; var bodyH = document.documentElement.clientHeight; //获取对话框宽、高 var elW = el.offsetWidth; var elH = el.offsetHeight; el.style.left = (bodyW - elW)/2 + \'px\'; el.style.top = (bodyH - elH)/2 + \'px\'; };
当窗口改变大小时,对话框自动居中
//窗口大小改变时,对话框始终居中 window.onresize = function(){ autoCenter(g(\'dialog\')); };
最核心的部分来了,对话框拖动的实现,这个效果的实现要分为三个步骤:
1.鼠标点击时,设置对话框可拖动,记录鼠标的初始位置;
2.鼠标拖动时,根据鼠标新位置更新对话框位置(有两种算法);
3.鼠标离开时移出对话框可拖动属性;
第一步:鼠标按下时
//声明需要用到的变量 var mx = 0,my = 0; //鼠标x、y轴坐标(相对于left,top) var dx = 0,dy = 0; //对话框坐标(同上) var isDraging = false; //不可拖动 //鼠标按下 g(\'move_part\').addEventListener(\'mousedown\',function(e){ var e = e || window.event; mx = e.pageX; //点击时鼠标X坐标 my = e.pageY; //点击时鼠标Y坐标 dx = g(\'dialog\').offsetLeft; dy = g(\'dialog\').offsetTop; isDraging = true; //标记对话框可拖动 });
第二步:鼠标移动时
document.onmousemove = function(e){ var e = e || window.event; var x = e.pageX; //移动时鼠标X坐标 var y = e.pageY; //移动时鼠标Y坐标 if(isDraging){ //判断对话框能否拖动 var moveX = dx + x - mx; //移动后对话框新的left值 var moveY = dy + y - my; //移动后对话框新的top值 g(\'dialog\').style.left = moveX +\'px\'; //重新设置对话框的left g(\'dialog\').style.top = moveY +\'px\'; //重新设置对话框的top }; };
前面提过更新对话框位置有两种算法,这里用的是第一种方法:
先算出鼠标移动的坐标偏移量,用对话框的位置(对话框top,left值)加上这个偏移量就是对话框新的位置;
这种方法是参考了另一篇博客,原文地址http://www.jb51.net/article/67663.htm,慕课网的教学视频中采用的是另一种算法:
先算出鼠标按下时的坐标和对话框位置(对话框top,left值)的距离,再用鼠标移动的新坐标减去得到的距离更新对话框位置;即
moveX = mx – (x – dx);
moveY = my – (y – dy);
无论哪种办法都可以实现对话框的拖动。
第三步:鼠标离开时
//鼠标离开 g(\'move_part\').addEventListener(\'mouseup\',function(){ isDraging = false; });
这一步比较简单,重新设置对话框不可拖动。
另一个比较重要的是限制对话框的拖动范围,代码如下(这段代码应插入到第二步的if判断中)。
//设置拖动范围 var pageW = document.documentElement.clientWidth; var pageH = document.documentElement.clientHeight; var dialogW = g(\'dialog\').offsetWidth; var dialogH = g(\'dialog\').offsetHeight; var maxX = pageW - dialogW; //X轴可拖动最大值 var maxY = pageH - dialogH; //Y轴可拖动最大值 moveX = Math.min(Math.max(0,moveX),maxX); //X轴可拖动范围 moveY = Math.min(Math.max(0,moveY),maxY); //Y轴可拖动范围 g(\'dialog\').style.left = moveX +\'px\'; //重新设置对话框的left g(\'dialog\').style.top = moveY +\'px\'; //重新设置对话框的top
限制对话框在可视窗口内拖动,原理就是设置合理的对话框的left、top值范围,其中
left值的范围是:【0,pageW – dialogW】
top值的范围是:【0,pageH – dialogH】
需要注意的是给这两个值设定范围的Math.max(),Math.min()方法。
下面是jQuery写法的具体代码,由于原理在JS部分中已有介绍,这里就不赘述了。
二、jQuery写法
$(document).ready(function(){ var $dialog = $("#dialog"); var $mask = $("#mask"); //自动居中对话框 function autoCenter(el){ var bodyW = $(window).width(); var bodyH = $(window).height(); var elW = el.width(); var elH = el.height(); $dialog.css({"left":(bodyW-elW)/2 + \'px\',"top":(bodyH-elH)/2 + \'px\'}); }; //点击弹出对话框 $("#callout").click(function(){ $dialog.css("display","block"); $mask.css("display","block"); autoCenter($dialog); }); //禁止选中对话框内容 if(document.attachEvent) {//ie的事件监听,拖拽div时禁止选中内容,firefox与chrome已在css中设置过-moz-user-select: none; -webkit-user-select: none; g(\'dialog\').attachEvent(\'onselectstart\', function() { return false; }); } //声明需要用到的变量 var mx = 0,my = 0; //鼠标x、y轴坐标(相对于left,top) var dx = 0,dy = 0; //对话框坐标(同上) var isDraging = false; //不可拖动 //鼠标按下 $("#move_part").mousedown(function(e){ e = e || window.event; mx = e.pageX; //点击时鼠标X坐标 my = e.pageY; //点击时鼠标Y坐标 dx = $dialog.offset().left; dy = $dialog.offset().top; isDraging = true; //标记对话框可拖动 }); //鼠标移动更新窗口位置 $(document).mousemove(function(e){ var e = e || window.event; var x = e.pageX; //移动时鼠标X坐标 var y = e.pageY; //移动时鼠标Y坐标 if(isDraging){ //判断对话框能否拖动 var moveX = dx + x - mx; //移动后对话框新的left值 var moveY = dy + y - my; //移动后对话框新的top值 //设置拖动范围 var pageW = $(window).width(); var pageH = $(window).height(); var dialogW = $dialog.width(); var dialogH = $dialog.height(); var maxX = pageW - dialogW; //X轴可拖动最大值 var maxY = pageH - dialogH; //Y轴可拖动最大值 moveX = Math.min(Math.max(0,moveX),maxX); //X轴可拖动范围 moveY = Math.min(Math.max(0,moveY),maxY); //Y轴可拖动范围 //重新设置对话框的left、top $dialog.css({"left":moveX + \'px\',"top":moveY + \'px\'}); }; }); //鼠标离开 $("#move_part").mouseup(function(){ isDraging = false; }); //点击关闭对话框 $("#close").click(function(){ $dialog.css("display","none"); $mask.css("display","none"); }); //窗口大小改变时,对话框始终居中 window.onresize = function(){ autoCenter($dialog); }; });
注意分析对比原生JS和jQuery的异同点!获取元素宽高,绑定事件等的写法………….
三、末尾
可拖拽对话框效果实现,JS和jQuery两种写法就是这样了,感谢前人栽阴!
同时学海无涯苦作舟,js插件不仅要会用,努力弄懂一个又一个效果的实现原理,自己能写出来才是真的懂了,共勉!!!
以上是关于可拖动弹窗的JS和jQuery两种写法的主要内容,如果未能解决你的问题,请参考以下文章