参考:cloudgamer大神的博文(推荐)。
事件绑定:bind和bindAsEventListener。
bind(obj,fun)可以将函数fun绑定到对象obj上,但是在fun函数中绑定参数。
function bind(obj,fun) //将函数fun绑定到某个对象obj
{
return function()
{
return fun.apply(obj,arguments);
}
}
bindAsEventListener(obj,fun)同bind可以将函数fun绑定到对象obj上,但是可以在fun函数中绑定参数,同时会将event作为第一个参数。
var bindAsEventListener = function(obj, fun) //将函数绑定到对象的某个事件上,作为事件处理函数
{
var args = Array.prototype.slice.call(arguments).slice(2);
return function(event)
{
return fun.apply(obj, [event || window.event].concat(args));
}
}
如果传入参数形如bindAsEventListener(this,this.clickEvent,name,age....)的形式。那么bindAsEventListener首先会利用Array.prototype.slice.call(argument).slice(2)的方法,将arguments作为一个参数列表,利用call方法将arguments参数列表转化成为数组的参数传入到Array中去,然后再可以调用Array.slice(2)的方法截取从[2,arguments.length)的参数。具体测试代码为:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<script type="text/javascript">
var array=new Array(1,2,3,4,5,6,7);
array=array.slice(2); //截取数组[2,array.length)中的数据
//alert(array);
function test(a,b,name,age,password)
{
alert(arguments); //arguments可以获取所有的参数列表
alert(Array.prototype.slice.call(arguments).slice(2)); //截取从[2,arguments.length)的参数列表,弹出xuzengqiang,12,123456
}
test(1,2,"xuzengqiang",12,"123456");
</script>
<body>
</body>
</html>
bindAsEventListener最后的return语句中apply的参数列表为[event || window.event].contact(args);这里表示将event事件作为fun的第一个参数。args保存的参数列表作为fun的后续参数。
bindAsEventListener和bind的测试用例如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<script type="text/javascript">
var bind=function(obj,fun) //将函数fun绑定到对象obj上
{
return function()
{
return fun.apply(obj,arguments);
}
}
var bindAsEventListener=function(obj,fun)
{
var args = Array.prototype.slice.call(arguments).slice(2);
return function(event)
{
return fun.apply(obj, [event || window.event].concat(args)); //将事件event绑定到eventFun作为第一个参数
}
}
var Class=
{
create:function()
{
return function()
{
this.initialize.apply(this,arguments);
}
}
};
var bindTest=Class.create();
bindTest.prototype=
{
initialize:function(obj)
{
var $button=document.getElementById(obj);
var name="xuzengqiang";
//$button.οnclick=bindAsEventListener(this,this.clickEvent,name); //name作为clickEvent的参数
$button.οnclick=bind(this,this.bindClick);
},
clickEvent:function(e,name)
{
alert(name+"你竟敢点击我!");
},
bindClick:function()
{
alert("绑定点击事件!");
}
}
window.οnlοad=function()
{
new bindTest("bind");
}
</script>
<body>
<button id="bind">点击</button>
</body>
</html>
效果图预览:其中8个点可以任意方向拖动,用来改变容器大小,容器本身可以拖动。
实现:主要利用methoBind()绑定8个方向点的拖动函数,通过mousedown事件来触发this.dataInit进行数据初始化开始缩放,
this.dataInit主要设置缩放程序this._fun和缩放参数,然后利用mousemove事件触发resize方法进行拖放后容器样式的设置,mouseup触发Stop方法停止拖放。
缩放原理:
以向上拖动和向下拖动为例:
向上拖动的时候:下侧必须固定,同时高度也要发生变化
方式一:自增或自减,每次更新拖动前后的坐标,然后让高度自增或自减拖动前后的坐标差值,这样做相对而言叫麻烦,但是思路清晰,需要每次都更新拖动前的坐标,将这次拖动后的坐标作为下一次拖动前的坐标。
方式二:只记录鼠标按下时坐标位置,然后每次鼠标拖动的时候,只记录每次拖动后的坐标与鼠标按下时坐标和容器高度的变化,不需要进行高度自增或自减操作,只需进行赋值即可。推荐方式二:
首先记录高度的变化:
this.styleHeight=Math.max(this.sideDown-e.clientY,0);
top值的变化:(其中this.bottomPosition表示最底边的高度位置)
this.styleTop=this.bottomPosition-this.styleHeight;
top值和容器高度变化的分析:
向下拖动,这时候保证顶部不移动,top值不用发生改变,只需修改高度即可。
<span style="font-family:Microsoft YaHei;">this.styleHeight=Math.max(e.clientY-this.sideUp,0);</span>
高度分析:
div层的拖动原理:只需修改left和top值,width和height不会发生改变。
方式一:获取鼠标拖动前位置(startX,startY),然后当鼠标拖动的时候记录拖动后的坐标(e.clientX,e.clientY)。这个时候容器的left和top分别自增对应坐标的差值即可。
每拖动一次重新修改startX=e.clientX,startY=e.clientY即可。
this.styleLeft+=e.clientX-this.startX;
this.styleTop+=e.clientY-this.startY;
this.startX=e.clientX;
this.startY=e.clientY;
方式二:同样只需记录鼠标按下的坐标,然后记录每次鼠标拖动后的坐标(e.clientX,e.clientY),找出拖动后的坐标与鼠标按下坐标和left、top值的关系。
以left变更为例:
this.styleLeft=e.clientX-this.dragLeft;
分析:
完整代码:(css样式方面不做分析)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>test</title>
<style type="text/css">
*{margin:0;padding:0}
.borderDiv{width:100px;height:100px;border:1px dashed #AFAFAF;position:absolute;top:100px;left:30px;
cursor:move;z-index:4;}
.move{width:6px;height:6px;background:#FFFFFF;border:2px solid #AFAFAF;position:absolute;border-radius:10px;z-index:5;}
.left,.right{cursor:e-resize;top:50%;margin-top:-5px;}
.leftBottomMove,.rightTopMove{cursor:ne-resize}
.leftTopMove,.rightBottomMove{cursor:nw-resize}
.top,.bottom{cursor:n-resize}
.leftTopMove{top:-5px;left:-5px;}
.top{left:50%;margin-left:-5px;top:-5px}
.rightTopMove{right:-5px;top:-5px}
.left{left:-5px}
.right{right:-5px}
.leftBottomMove{bottom:-5px;left:-5px}
.bottom{bottom:-5px;left:50%;margin-left:-5px}
.rightBottomMove{bottom:-5px;right:-5px}
</style>
</head>
<script type="text/javascript">
var isIE=(document.all)?true:false;
function $()
{
if(arguments.length==1 && typeof arguments[0] == "string")
{
return document.getElementById(arguments[0]);
}
};
var Class=
{
create:function()
{
return function()
{
this.initialize.apply(this,arguments);
}
}
};
Object.extend=function(destination,source)
{
for(var property in source)
{
destination[property]=source[property];
}
return destination;
};
Object.prototype.extend=function(obj)
{
return Object.extend.apply(this,[this,obj]);
};
var Event=(function()
{
return {
addEventHandler:function(target,eventType,fun)
{
if(target.addEventListener)
{
target.addEventListener(eventType,fun,false);
}
else if(target.attachEvent)
{
target.attachEvent("on"+eventType,fun);
}
else
{
target["on"+eventType]=fun;
}
},
removeEventHandler:function(target,eventType,fun)
{
if(target.removeEventListener)
{
target.removeEventListener(eventType,fun,false);
}
else if(target.detachEvent)
{
target.detachEvent("on"+eventType,fun);
}
else
{
target["on"+evenetType]=false;
}
}
}
}());
function bind(obj,fun) //将函数fun绑定到某个对象obj
{
return function()
{
return fun.apply(obj,arguments);
}
}
var bindAsEventListener = function(obj, fun) //将函数绑定到对象的某个事件上,作为事件处理函数
{
var args = Array.prototype.slice.call(arguments).slice(2);
return function(event)
{
return fun.apply(obj, [event || window.event].concat(args));
}
}
//扩展document中的getElementsByClassName方法,即通过class类名的值获取元素对象
document.getElementsByClassName=function(className)
{
var elements=new Array(),
allElements=document.getElementsByTagName('*') || document.all;
for(var i=0,maxLen=allElements.length; i<maxLen; i++)
{
var child=allElements[i],
classNames=child.className.split(' ');
for(var j=0,max=classNames.length;j<max;j++) //不推荐for(var j=0;j<classNames.length;j++)方式,因为每次都会计算长度
{
if(className==classNames[j])
{
elements.push(child);
break;
}
}
}
return elements;
}
var SimpleDrag=Class.create();
SimpleDrag.prototype=
{
initialize:function(obj,options) //obj为容器对象,
{
this.content=$(obj);
this._resize = bindAsEventListener(this,this.resize);
this._stop = bind(this,this.Stop);
},
setOptions:function(options) //参数设置
{
},
methodBind:function(obj) //八个方向点方法绑定
{
var current=document.getElementsByClassName(obj)[0],fun; //fun为方法
if(!current) return ;
switch(obj)
{
case "top":
fun=this.up;
break;
case "bottom":
fun=this.down;
break;
case "left":
fun=this.left;
break;
case "right":
fun=this.right;
break;
case "leftTopMove":
fun=this.leftUp;
break;
case "rightTopMove":
fun=this.rightUp;
break;
case "leftBottomMove":
fun=this.leftDown;
break;
case "rightBottomMove":
fun=this.rightDown;
break;
default: //否则对容器对象进行拖拽
fun=this.drag;
}
Event.addEventHandler(current,"mousedown",bindAsEventListener(this,this.dataInit,fun)); //fun作为dataInit的参数
},
dataInit:function(e,fun) //数据初始化
{
//防止事件冒泡,IE:e.cancelBubble=true,FF:e.stopPropagation()
e.stopPropagation?e.stopPropagation():(e.cancelBubble=true);
this._fun=fun;
this.styleWidth=this.content.clientWidth; //容器可以宽度,不包括边框和滚动条
this.styleHeight=this.content.clientHeight;
this.styleLeft=this.content.offsetLeft; //容器向左偏移的距离
this.styleTop=this.content.offsetTop;
this.sideLeft = e.clientX - this.styleWidth; //左侧定位参数,e.clientX表示事件发生位置相对于浏览器的横坐标
this.sideRight = e.clientX + this.styleWidth;
this.sideUp = e.clientY - this.styleHeight;
this.sideDown = e.clientY + this.styleHeight;
this.dragLeft=e.clientX-this.styleLeft;
this.dragTop=e.clientY-this.styleTop;
this.rightPosition=this.styleWidth+this.styleLeft; //最右边的位置
this.bottomPosition=this.styleHeight+this.styleTop; //最底部的位置
Event.addEventHandler(document,"mousemove",this._resize);
Event.addEventHandler(document,"mouseup",this._stop);
},
resize:function(e) //当拖动后重新修改容器的大小
{
this._fun(e); //改变
with(this.content.style)
{
width=this.styleWidth+"px",height=this.styleHeight+"px";
top=this.styleTop+"px",left=this.styleLeft+"px";
}
},
up:function(e) //向上移动,此时容器的top值也要随之改变,从而保证下侧固定
{
this.styleHeight=Math.max(this.sideDown-e.clientY,0);
this.styleTop=this.bottomPosition-this.styleHeight;
},
down:function(e)
{
this.styleHeight=Math.max(e.clientY-this.sideUp,0);
},
left:function(e)
{
this.styleWidth=Math.max(this.sideRight-e.clientX,0);
this.styleLeft=this.rightPosition-this.styleWidth;
},
right:function(e)
{
this.styleWidth=Math.max(e.clientX-this.sideLeft,0);
},
leftUp:function(e)
{
this.left(e);
this.up(e);
},
rightUp:function(e)
{
this.right(e);
this.up(e);
},
leftDown:function(e)
{
this.left(e);
this.down(e);
},
rightDown:function(e)
{
this.right(e);
this.down(e);
},
drag:function(e)
{
this.styleLeft=e.clientX-this.dragLeft;
this.styleTop=e.clientY-this.dragTop;
},
Stop:function() //停止缩放
{
Event.removeEventHandler(document,"mousemove",this._resize);
Event.removeEventHandler(document,"mouseup",this._stop);
}
}
window.οnlοad=function()
{
var resize=new SimpleDrag("borderDiv");
resize.methodBind("top"); //向上移动
resize.methodBind("bottom"); //向下移动
resize.methodBind("left"); //向左移动
resize.methodBind("right"); //向右移动
resize.methodBind("leftTopMove");
resize.methodBind("rightTopMove");
resize.methodBind("leftBottomMove");
resize.methodBind("rightBottomMove");
resize.methodBind("borderDiv");
}
</script>
<body style="">
<div class="borderDiv" id="borderDiv">
<div class="leftTopMove move"></div>
<div class="top move"></div>
<div class="rightTopMove move"></div>
<div class="left move"></div>
<div class="right move"></div>
<div class="leftBottomMove move"></div>
<div class="bottom move"></div>
<div class="rightBottomMove move"></div>
</div>
</body>
</html>