这两天又进一步学习了下JavaScript的面向对象方法,也看了简单的拖拽案例,顺便就尝试自己写写简单的拖拽效果作为练习
目标:实现子DIV在父DIV内的拖拽效果,并且不会突破父DIV边缘,在接近父DIV边缘时,自动吸附到边缘;
想法:
- 鼠标在子DIV区域内按下,子DIV获取onclick事件,计算鼠标位置和子DIV左边缘和上边缘的距离;
- 鼠标移动,生成一个虚线框的DIV,大小和子DIV一直,左边缘和上边缘与鼠标位置距离和之前测得的鼠标位置与子DIV距离保持一致,跟随鼠标移动,实现拖拽效果;
- 若鼠标移动范围超过父DIV边缘,则让虚线框DIV边缘位置与父边框边缘位置保持一致,从而防止突破父DIV边缘;
- 当鼠标在父边框内接近父边框边缘一定距离时,将父边框边缘位置赋给虚线框DIV边缘位置,从而实现吸附效果;
- 鼠标按键松开,将虚线框DIV的位置信息赋给子DIV,同时消除虚线框DIV。
实现:
HTML:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>拖拽</title>
</head>
<body>
<div id="div1">
<div id="div2"></div>
</div>
</body>
</html>
CSS:
#div2{
width: 80px;
height: 80px;
background: red;
position: absolute;
}
#div1{
width: 400px;
height: 400px;
background:gray;
position: relative;
}
.box {
border: dashed 1px black;
position: relative;
}
JavaScript:
window.onload = function(){
new Drag("div1", "div2", "20");
}
//拖拽对象构建函数
function Drag(fatherId, childId, touchDis){
var _this = this;
this.touchDis = touchDis;
this.disX = 0;
this.disY = 0;
this.oDiv1 = document.getElementById(fatherId);
this.oDiv2 = document.getElementById(childId);
//绑定鼠标点下事件处理函数
this.oDiv2.onmousedown = function(ev){
_this.mouseDown(ev);
}
}
//鼠标点下事件处理函数
Drag.prototype.mouseDown = function (ev){
var _this = this;
var oEvent = ev || event;
//保存鼠标位置和子DIV的左边缘与上边缘距离
this.disX = oEvent.clientX - this.oDiv2.offsetLeft + document.documentElement.scrollLeft;
this.disY = oEvent.clientY - this.oDiv2.offsetTop + document.documentElement.scrollTop;
//创建虚线框DIV(oBox),并添加到父DIV的子节点上
this.oBox = document.createElement('div');
this.oBox.className = 'box';
this.oBox.style.width = this.oDiv2.offsetWidth - 2 + 'px';
this.oBox.style.height = this.oDiv2.offsetHeight - 2 + 'px';
this.oBox.style.left = this.oDiv2.offsetLeft + 'px';
this.oBox.style.top = this.oDiv2.offsetTop + 'px';
this.oDiv1.appendChild(this.oBox);
//简单的鼠标事件捕获兼容处理,并绑定相应的事件处理函数
if(this.oDiv2.setCapture){
this.oDiv2.onmousemove = function(ev){
_this.mouseMove(ev);
}
this.oDiv2.onmouseup = function(){
_this.mouseUp();
}
this.oDiv2.setCapture();
}else{
document.onmousemove = function(ev){
_this.mouseMove(ev);
}
document.onmouseup = function(){
_this.mouseUp();
}
}
//禁用浏览器默认操作
return false;
}
//鼠标移动事件处理函数
Drag.prototype.mouseMove = function (ev){
var oEvent = ev || event;
var left = oEvent.clientX - this.disX + document.documentElement.scrollLeft;
var top = oEvent.clientY - this.disY + document.documentElement.scrollTop;
//检测鼠标是否在父DIV内,防止子DIV突破父DIV边界,同时通过判断鼠标和父DIV边缘距离实现边缘吸附效果
if(left < this.touchDis){
left = 0;
}else if(left > this.oDiv1.offsetWidth - this.oDiv2.offsetWidth - this.touchDis){
left = this.oDiv1.offsetWidth - this.oDiv2.offsetWidth;
}
if(top < this.touchDis){
top = 0;
}else if(top > this.oDiv1.offsetHeight - this.oDiv2.offsetHeight - this.touchDis){
top = this.oDiv1.offsetHeight - this.oDiv2.offsetHeight;
};
this.oBox.style.left = left + 'px';
this.oBox.style.top = top + 'px';
};
//鼠标松开事件处理函数
Drag.prototype.mouseUp = function(){
//解除鼠标点下和移动事件处理函数绑定
this.onmousemove = null;
this.onmousup = null;
//奖虚线框DIV位置信息赋给子DIV
this.oDiv2.style.left = this.oBox.offsetLeft + 'px';
this.oDiv2.style.top = this.oBox.offsetTop + 'px';
//移除虚线框DIV
this.oDiv1.removeChild(this.oBox);
if(this.oDiv2.releaseCapture){
this.oDiv2.releaseCapture();
}
};
实现效果如下:
传送门
写完后发现其实这样用面向对象方法来实现好像很蛋疼,好像没什么实用性,不过权当练习了……