Web前端基础(12)JS实践案例--留言板

演示和源码

我的留言界面有一个留言板,留言板上面的纸条是可以随着鼠标拖动的,下面我们来实现一下可拖动的留言框。

演示效果:

html布局

1
2
3
4
5
6
7
8
9
<div class="nav">
<a href="javascript:;" id="register">注册信息</a>
</div>
<div class="d-box" id="d_box">
<div class="hd" id="drop">注册信息 (可以拖拽)
<span id="box_close">【关闭】</span>
</div>
<div class="bd"></div>
</div>

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
*{margin:0;padding:0;}
.nav{
height:30px;
background: #036663;
border-bottom:1px solid #369;
line-height: 30px;
padding-left:30px;
}
.nav a {
color:#fff;
text-align: center;
font-size:14px;
text-decoration: none;

}
.d-box{
width:400px;
height:300px;
border:5px solid #eee;
box-shadow:2px 2px 2px 2px #666;
position: absolute;
top:50%;
left:50%;
margin-top: -155px;
margin-left:-205px;

}
.hd{
width:100%;
height:25px;
background-color: #7c9299;
border-bottom:1px solid #369;
line-height: 25px;
color:white;
cursor: move;
}
#box_close{
float: right;
cursor: pointer;
}

javascript代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var box = document.getElementById("d-box");
var drop = document.getElementById("drop");

startDrop(drop, box);

function startDrop(current, move){
current.onmousedown = function(event){
var event = event || window.event;
var x = event.clientX - move.offsetLeft - 200; // 记录当前盒子的x 位置
var y = event.clientY - move.offsetTop - 150; // // 记录当前盒子的y位置
document.onmousemove = function(event) {
var event = event || window.event;
move.style.left = event.clientX - x + "px";
move.style.top = event.clientY - y + "px";
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
}
}
document.onmouseup = function() { // 鼠标弹起之后, 鼠标继续移动不应该操作
document.onmousemove = null;
}
}

技术点分析

绝对相对定位居中

绝对和相对定位元素要居中就需要根据元素尺寸和容器尺寸来计算位置。

1
2
3
4
5
6
7
width: 400px;
height: 300px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -150px;
margin-left: -200px;

event || window.event

event = event || window.event是我们在做事件处理时候区分IE和其他浏览器事件对象时常用的写法。在IE6/7/8 event为undefined 所以为了兼容IE浏览器的部分版本通常会这样写。

event.clientX和event.clientY

clientX 和 clientY 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标和竖直坐标。

1
2
var x = event.clientX - move.offsetLeft - 200;   // 记录当前盒子的x方向偏移量
var y = event.clientY - move.offsetTop - 150; // // 记录当前盒子的y方向偏移量

Selection对象

Selection对象所对应的是用户所选择的 ranges (区域),俗称拖蓝。默认情况下,该函数只针对一个区域,我们可以这样使用这个函数:

1
2
var selection = window.getSelection() ;
var range = selection.getRangeAt(0);

selection 被赋予一个 Selection对象
range 被赋予一个 Range 对象

调用 Selection.toString() 方法会返回被选中区域中的纯文本。要求变量为字符串的函数会自动对对象进行该处理,例如:

1
2
var selObj = window.getSelection();
window.alert(selObj);

removeAllRanges方法是将所有的区域都从选区中移除。
document.selection只有IE支持,window.getSelection()也只有FireFox和 Safari支持,都不是标准语法。

案例拓展

随机生成多个框

1
2
3
4
5
6
7
8
9
10
11
12
function createDropBox(num, beclone) {
var defaultIndex = 100;
beclone.style.zIndex = defaultIndex;
var bodyd = document.getElementsByTagName("body")[0];
for (var i = 0; i < num; i++) {
var clonedNode = beclone.cloneNode(true);
clonedNode.style.zIndex = defaultIndex + i;
clonedNode.style.top = (Math.round(Math.random() * 10) * 10) + "%";
clonedNode.style.left = (Math.round(Math.random() * 10) * 10) + "%";
bodyd.appendChild(clonedNode);
}
}

cloneNode方法将beclone标签克隆了num个,参数为true表示深度克隆(克隆标签本身和子标签)。

关闭拖动框

1
2
3
4
5
6
7
8
9
10
function addCloseListener(parent){
var closebox = parent.getElementsByClassName("box-close");
for(var i = 0; i < closebox.length; i++){
closebox[i].onclick = function(){
var del = this.parentNode.parentNode;
var bod = del.parentNode;
bod.removeChild(del);
}
}
}

根据层级获取到body节点,然后删除当前点击事件节点的可拖动框。