可拖拽的弹出框

闲来无聊,拿来许久以前的可拖拽弹出框特效分享给过路的。
以百度首页的登录框为样版,来一一说明怎么实现相同的效果。喜欢的也可以来看看原文
原文

1.基本思路

1.1 概述

可拖拽弹出框,顾名思义:弹出,可以拖拽。简单明了。看到百度首页的登录弹出框,还多了几个,总结了一下,如下几条:
1.点击登录弹出登录框
2.点击小叉叉,关闭登录框
3.登录框弹出的同时有个遮罩层遮罩覆盖了除登录框以外的内容
4.鼠标在登录框上部分时,可以拖拽,任意摆放位置,并且不会跑出可视区域
5.每次改变浏览器大小时,弹出框都会再次居中

1.2 复习几个js知识

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
网页可见区域宽: document.body.clientWidth  
网页可见区域高: document.body.clientHeight
网页可见区域宽: document.body.offsetWidth (包括边线的宽)
网页可见区域高: document.body.offsetHeight (包括边线的高)
网页正文全文宽: document.body.scrollWidth
网页正文全文高: document.body.scrollHeight
网页被卷去的高: document.body.scrollTop
网页被卷去的左: document.body.scrollLeft
网页正文部分上: window.screenTop
网页正文部分左: window.screenLeft
屏幕分辨率的高: window.screen.height
屏幕分辨率的宽: window.screen.width
屏幕可用工作区高度: window.screen.availHeight
屏幕可用工作区宽度: window.screen.availWidth

获取元素宽度:oDiv.offsetWidth
获取元素高度:oDiv.offsetHeight

获取坐标
(处理兼容:var e = event || window.event;)
相对于屏幕:e.screenX,e.screenY
相对浏览器窗口:e.clientX,e.clientY
相对文档:e.pageX || e.clientX + scrollX,
e.pageY || e.clientY + scrollY;

1.3 js设计原理

1.3.1 点击登录弹出登录框

页面加载初,css设置弹出框默认隐藏,点击登录按钮,js设置样式弹出框显示

1
mask.style.display = 'block';

1.3.2 点击小叉叉,关闭登录框

点击小叉叉,js设置样式弹出框再次隐藏

1
mask.style.display = 'none';

1.3.3 登录框弹出的同时有个遮罩层…

这里做一下说明,我这里的遮罩层直接包裹在了登录框外,上面说的弹出框隐藏出现的,实际上是遮罩层隐藏出现,为了说明问题,我还是当做弹出框对待

1
2
3
4
5
6
7
<div class="mask" id="mask">
<div class="login" id="login">
<div class="title-dragable" id="dragable">
<sapn class="close" id="close">×</span>
</div>
</div>
</div>

1.3.4 拖拽不会跑出可视区域

鼠标对弹出框拖拽时,对left和top值进行判断处理,使得弹出框极限时只能在可是区域内沿边移动

1
2
3
4
left = left <= 0 ? 0 : left;
left = left >= (mask.offsetWidth - node.offsetWidth) ? (mask.offsetWidth - node.offsetWidth) : left;
top = top <= 0 ? 0 : top;
top = top >= (mask.offsetHeight - node.offsetHeight) ? (mask.offsetHeight - node.offsetHeight) : top;

更为详细的说明下面代码中都有注释详细说明,如下

2.代码

2.1 html代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<div class="container" id="container">
<div class="header">
<ul>
<li><a href="##">糯米</a></li>
<li><a href="##">新闻</a></li>
<li><a href="##">hao123</a></li>
<li><a href="##">地图</a></li>
<li><a href="##">视频</a></li>
<li><a href="##">视频贴吧</a></li>
<li><a href="javascript:;" id="dl">登录</a></li>
<li><a href="##">设置</a></li>
<li class="more"><a href="##">更多商品</a></li>
</ul>
</div>
<div class="content">
</div>
<div class="footer">

</div>
<!-- 登录弹出框-->
<div class="mask" id="mask">
<div class="login" id="login">
<div class="title-dragable" id="dragable">
<sapn class="close" id="close">×</span>
</div>
</div>
</div>
</div>

2.2 css代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
* {
padding: 0;
margin: 0;
}
.container {
min-width: 1000px;
width: 100%;
margin: 0 auto;
}
.header {
height: 24px;
margin: 19px 0 5px;
}
.header ul {
height: 24px;
float: right;
margin-right: 20px;
}
.header ul li {
float: left;
list-style: none;
line-height: 24px;
margin-left: 20px;
}
.header ul li a {
color: #333;
font-weight: 700;
font-size: 13px;
text-decoration: underline;
}
.header ul .more {
width: 60px;
height: 23px;
background: #38f;
line-height: 24px;
text-align: center;
overflow: hidden;
border-bottom: 1px solid #38f;
margin-left: 19px;
margin-right: 2px;
}
.header ul .more a {
font-size: 13px;
color: #fff;
text-decoration: none;
}
.mask {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .3);
position: absolute;
top: 0;
left: 0;
z-index: 99;
display: none;
}
.login {
width: 393px;
height: 505px;
background: #FFF;
position: absolute;
top: 50%;
left: 50%;
}
.title-dragable {
width: 391px;
height: 46px;
background-color: #f7f7f7;
border: 1px solid #ddd;
cursor: move;
}

.close {
display: block;
float: right;
width: 16px;
height: 16px;
font-size: 18px;
cursor: pointer;
text-align: center;
line-height: 16px;
margin: 15px;
color: #ccc;
}
.close:hover {
color: #333;
}

2.3 js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
window.onload = function() {
//点击登录弹出登录框
var dl = document.getElementById('dl');
var mask = document.getElementById('mask');
dl.onclick = function() {
mask.style.display = 'block';
center();
}
//点击小叉叉关闭登录框
var close = document.getElementById('close');
close.onclick = function() {
mask.style.display = 'none';
}
//开始为登录框添加鼠标拖动效果
var dragBar = document.getElementById('dragable');
dragBar.onmousedown = function(e) {
var e = e || window.e;
var node = this.parentNode;
// 获取当前鼠标z相对dragBar的坐标,记录下来,供拖拽时使用
var offsetX = e.offsetX;
var offsetY = e.offsetY;
//添加鼠标在dragBar按下且未松开时的window事件
window.onmousemove = function(e) {
var e = e || window.e;
// 再次获取当前鼠标的位置坐标
var moveX = e.clientX;
var moveY = e.clientY;
// 计算拖动时应有的偏移量
var left = moveX - offsetX;
var top = moveY - offsetY;
//对偏移量进行处理,使得被拖拽的元素不会跑出可视范围,算是获得好的客户体验吧
left = left <= 0 ? 0 : left;
left = left >= (mask.offsetWidth - node.offsetWidth) ? (mask.offsetWidth - node.offsetWidth) : left;
top = top <= 0 ? 0 : top;
top = top >= (mask.offsetHeight - node.offsetHeight) ? (mask.offsetHeight - node.offsetHeight) : top;
//将处理过的偏移量添加到拖拽元素样式
node.style.top = top + 'px';
node.style.left = left + 'px';
}
//鼠标按键松开,拖拽结束
window.onmouseup = function() {
window.onmousemove = null;
}
}
//处理login弹出框,使得每次浏览器窗口大小改变,login弹出框居中
var login = document.getElementById('login');
var container = document.getElementById('container');
window.onresize = function() {
center();
}
//封装成单独函数,便于调用
function center() {
mask.style.width = document.body.clientWidth>container.offsetWidth?document.body.clientWidth+'px':container.offsetWidth+'px';
var left = (mask.offsetWidth - login.offsetWidth) / 2;
var top = (mask.offsetHeight - login.offsetHeight) / 2;
login.style.top = top + 'px';
login.style.left = left + 'px';
}
}

3、补充说明

移动端时不支持的!移动端时不支持的!移动端时不支持的!重要的事情说三遍。对于移动端,拖拽效果貌似没什么必要,毕竟只是个登录框,移动端屏幕也就那么大(iPad之类的当我没说)。不过移动端的拖拽会有另一篇做介绍,以及功能实现。

4、在线演示

在线演示