JavaScript 闭包风格的拖拽
🌙
手机阅读
本文目录结构
1
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>闭包的拖拽</title>
<style>
div{width: 100px;height: 100px;position: absolute;left: 0;top: 0;background: red;cursor: move;}
#div2{left: 200px;top:20px;background: darkblue;}
#div3{left: 350px;top:30px;background: olive;}
</style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>
<script src="event.js"></script>
<script>
var oDivs=document.getElementsByTagName("div");
for(var i= 0,len=oDivs.length;i<len;i++){
(function(ele) {
on(ele,"mousedown",down)
var x=null,y=null,mx=null,my=null;
function down(e){
x=this.offsetLeft;
y=this.offsetTop;
mx= e.pageX;
my= e.pageY;
if(ele.setCapture){
ele.setCapture();
on(ele,"mousemove",move);
on(ele,"mouseup",up);
}else{
on(document,"mousemove",move);
on(document,"mouseup",up);
}
e.preventDefault();
}
function move(e){
ele.style.left=x+(e.pageX-mx)+"px";
ele.style.top=y+(e.pageY-my)+"px";
}
function up(e){
if(ele.releaseCapture){
ele.releaseCapture();
off(ele,"mousemove",move);
off(ele,"mouseup",up);
}else{
off(document,"mousemove",move)
off(document,"mouseup",up)
}
}
})(oDivs.item(i));
}
</script>
优化
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>闭包的拖拽</title>
<style>
div{width: 100px;height: 100px;position: absolute;left: 0;top: 0;background: red;cursor: move;}
#div2{left: 200px;top:20px;background: darkblue;}
#div3{left: 350px;top:30px;background: olive;}
</style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>
<script src="event.js"></script>
<script>
var oDivs=document.getElementsByTagName("div");
var DRAG=(function() {
/*下面的方法都是可以重用的;*/
//*module model 模块模式 三种情况*/
/*1、变量要保护,2、里面的一些函数或属性还要重复使用;3、变量共享(数据共享的)*/
var x=null,y=null,mx=null,my=null,flag=0;
function down(e){
x=this.offsetLeft;
y=this.offsetTop;
mx= e.pageX;
my= e.pageY;
if(this.setCapture){
this.setCapture();
on(this,"mousemove",move);
on(this,"mouseup",up);
}else{
this._move=bindThis(this,move);
this._up=bindThis(this,up);
on(document,"mousemove",this._move);
on(document,"mouseup",this._up);
}
e.preventDefault();
flag++;
this.innerHTML="一共拖了"+flag+"次";
}
function move(e){
this.style.left=x+(e.pageX-mx)+"px";
this.style.top=y+(e.pageY-my)+"px";
}
function up(e){
if(this.releaseCapture){
this.releaseCapture();
off(this,"mousemove",move);
off(this,"mouseup",up);
}else{
off(document,"mousemove",this._move);
off(document,"mouseup",this._up);
}
}
return {down:down,move:move,up:up}
})();
for(var i= 0,len=oDivs.length;i<len;i++) {
on(oDivs[i],"mousedown",DRAG.down)
}
/*
*//*属于模块化开发,单利模式*//*
DRAG.down();
DRAG.move();
*//*module model 模块模式*/
</script>
面向对象的拖拽
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>闭包的拖拽</title>
<style>
div{width: 100px;height: 100px;position: absolute;left: 0;top: 0;background: red;cursor: move;}
#div2{left: 200px;top:20px;background: darkblue;}
#div3{left: 350px;top:30px;background: olive;}
</style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>
<script src="event.js"></script>
<script>
/*每一个单独行为,是依赖一个主体/上下文
* 每一个主体是一个类的实例
* 类是一种统筹管理的方式
* */
function Drag(ele){
//初始化的,构造函数;
this.x=null;
this.y=null;
this.mx=null;
this.my=null;
this.ele=ele;
/*下面是强制指向当前的实例*/
this._down=bindThis(this,this.down);
this._move=bindThis(this,this.move);
this._up=bindThis(this,this.up);
on(this.ele,"mousedown",this._down)
}
Drag.prototype.down=function(e){
/*下面的this是Drag的实例*/
this.x=this.ele.offsetLeft;
this.y=this.ele.offsetTop;
this.mx= e.pageX;
this.my= e.pageY;
if(this.ele.setCapture){
this.ele.setCapture();
on(this.ele,"mousemove",this._move);
on(this.ele,"mouseup",this._up);
}else{
on(document,"mousemove",this._move);
on(document,"mouseup",this._up);
}
};
Drag.prototype.move=function(e){
this.ele.style.left=this.x+(e.pageX-this.mx)+'px';
this.ele.style.top=this.y+(e.pageY-this.my)+'px';
};
Drag.prototype.up=function(e){
if(this.ele.releaseCapture){
this.ele.releaseCapture();
off(this.ele,"mousemove",this._move);
off(this.ele,"mouseup",this._up);
}else{
off(document,"mousemove",this._move);
off(document,"mouseup",this._up);
}
};
var obj1=new Drag(div1);
var obj1=new Drag(div2);
var obj1=new Drag(div3);
</script>
面向对象+设计模式+继承
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>闭包的拖拽</title>
<style>
div{width: 100px;height: 100px;position: absolute;left: 0;top: 0;background: red;cursor: move;}
#div2{left: 200px;top:20px;background: darkblue;}
#div3{left: 350px;top:30px;background: olive;}
</style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>
<script src="event.js"></script>
<script>
/*每一个单独行为,是依赖一个主体/上下文
* 每一个主体是一个类的实例
* 类是一种统筹管理的方式
* */
function EventEimter(){}
EventEimter.prototype.on=function(type,fn){
if(!this[type]){
this[type]=[];
}
for(var i=0;i<this[type].length;i++){
if(this[type][i]==fn)return;
}
this[type].push(fn)
};
EventEimter.prototype.fire=function(type,obj,e){
var ary=this[type];
if(ary){
for(var i=0;i<ary.length;){
if(typeof ary[i]=="function"){
ary[i].call(obj,e);
i++;
}else{
ary.splice(i,1);
}
}
}
};
EventEimter.prototype.off=function(type,fn){
var ary=this[type];
if(ary){
for(var i=0;i<ary.length;i++){
if(ary[i]==fn){
ary[i]=null;
return;
}
}
}
};
function Drag(ele){
//初始化的,构造函数;
this.x=null;
this.y=null;
this.mx=null;
this.my=null;
this.ele=ele;
/*下面是强制指向当前的实例*/
this._down=bindThis(this,this.down);
this._move=bindThis(this,this.move);
this._up=bindThis(this,this.up);
on(this.ele,"mousedown",this._down)
}
Drag.prototype=new EventEimter();
Drag.prototype.down=function(e){
/*下面的this是Drag的实例*/
this.x=this.ele.offsetLeft;
this.y=this.ele.offsetTop;
this.mx= e.pageX;
this.my= e.pageY;
if(this.ele.setCapture){
this.ele.setCapture();
on(this.ele,"mousemove",this._move);
on(this.ele,"mouseup",this._up);
}else{
on(document,"mousemove",this._move);
on(document,"mouseup",this._up);
}
this.fire("dragStar",this.ele,e)
};
Drag.prototype.move=function(e){
this.ele.style.left=this.x+(e.pageX-this.mx)+'px';
this.ele.style.top=this.y+(e.pageY-this.my)+'px';
this.fire("dragMove",this.ele,e)
};
Drag.prototype.up=function(e){
if(this.ele.releaseCapture){
this.ele.releaseCapture();
off(this.ele,"mousemove",this._move);
off(this.ele,"mouseup",this._up);
}else{
off(document,"mousemove",this._move);
off(document,"mouseup",this._up);
}
this.fire("dragEnd",this.ele,e)
};
var obj1=new Drag(div1);
obj1.on("dragStar",zIndexplus);
obj1.on("dragStar",clearEffect);
obj1.on("dragMove",getSpeed);
obj1.on("dragEnd",drop);
obj1.on("dragEnd",fly);
var obj2=new Drag(div2);
var obj3=new Drag(div3);
/*左右反弹*/
function fly(){
clearTimeout(this.flytimer);
var maxRight=(document.documentElement.clientWidth||document.body.clientWidth)-this.offsetWidth;
this.speed*=0.93;
if(this.offsetLeft+this.speed>=maxRight){
this.style.left=maxRight+"px";
this.speed*=-1;
}else if(this.offsetLeft+this.speed<=0){
this.style.left=0;
this.speed*=-1;
}else{
this.style.left=this.offsetLeft+this.speed+"px";
}
if(Math.abs(this.speed)>=0.5){/*定时器停止的条件*/
this.flytimer=window.setTimeout(bindThis(this,arguments.callee),30);
}
}
/*自由落体*/
var g=9.8;
var flag=0;
function drop(){
clearTimeout(this.droptimer);
var maxBottom=(document.documentElement.clientHeight||document.body.clientHeight)-this.offsetHeight;
if(!this.dropSpeed){
this.dropSpeed=g;
}else{
this.dropSpeed+=g;
}
/*下面是摩擦系数*/
this.dropSpeed*=0.93;
/*下面是边界判断*/
if(this.offsetTop+this.dropSpeed>=maxBottom){
this.style.top=maxBottom+"px";
this.dropSpeed*=-1;
flag++;
}else{
this.style.top=this.offsetTop+this.dropSpeed+"px";
flag=0;
}
if(flag<2){
this.droptimer=window.setTimeout(bindThis(this,arguments.callee),30);
}
}
var zIndex=1;
function zIndexplus(){
this.style.zIndex=++zIndex;//解决图片覆盖的;
}
function clearEffect(){
clearTimeout(this.flytimer);
clearTimeout(this.droptimer);
}
function getSpeed(e){
/*加动画效果的代码*/
if(!this.prevX){
//记录第一次/上一次move事件触发的时候鼠标X轴位置;
this.prevX= e.clientX;
}else{
this.speed= e.clientX-this.prevX;//速度=这次位置-上次位置;
this.prevX= e.clientX;//改变this.prevX;记录本次的位置
//两次move事件之间的事件间大体是一样的;
// 速度=单位时间的距离;
}
/*动画代码结束*/
}
</script>
event.js
/*on:是负责往数组里安排一个队列的,程序池*/
function on(ele,type,fn){
/*约定type如果以self开头的字符串,就是自定义事件,如果不是的,就是系统的事件*/
if(/^self/.test(type)){//判断是否是自定义事件,这里是自定义事件;
if(!ele[type]){
ele[type]=[];
}
var aryEvent=ele[type];
for(var i=0;i<aryEvent.length;i++){//防止同一个方法被同事件绑定;
if(aryEvent[i]==fn)return;
}
aryEvent.push(fn);
}else{
if(ele.addEventListener){
ele.addEventListener(type,fn);
}else{
if(!ele["aEvent"+type]){
ele["aEvent"+type]=[];
//bind3(ele,type,run);//只会执行一次,防止重复绑定;上一次封装的事件库是用bind解决的
ele.attachEvent("on"+type,function(){run.call(ele)})//放在这里,因为是在if里,所以是有条件执行的,而且这里是只执行一次;防止重复绑定;
}
var aryEvent=ele["aEvent"+type];
for(var i=0;i<aryEvent.length;i++){//防止同一个方法被同事件绑定;
if(aryEvent[i]==fn)return;
}
aryEvent.push(fn);
}
}
}
/*run:负责具体的执行,在这里把IE兼容性全部解决掉;run方法是由系统的事件来触发的,真正绑定的是run方法*/
function run(){//run方法只用在IE678,解决系统事件的兼容性问题;;
var e=window.event;
e.target= e.srcElement;
e.pageX=(document.documentElement.scrollLeft||document.body.scrollLeft)+ e.clientX;
e.pageY=(document.documentElement.scrollTop||document.body.scrollTop)+ e.clientY;
e.stopPropagation=function(){e.cancelBubble=true;}//阻止事件传播;
e.preventDefault=function(){e.returnValue=false;}//阻止事件默认行为;
var a=this["aEvent"+e.type];
for(var i=0;i< a.length;){
/*下面是防止数组塌陷的*/
if(typeof a[i]=="function"){//这个是和off呼应的,off里有为null的值;
a[i].call(this,e);//以后给元素写的方法,约定好都要写一个e的参数,这样就不需要再解决IE兼容性了;
i++;
}else{
a.splice(i,1);
}
}
}
/*fire是写在某一个方法最后,任何浏览器任何自定义事件都可以用*/
function fire(selfType,e){//第一个参数是自定义事件的类型;第二个事件是系统事件对象;
var ary=this[selfType];
if(ary){
for(var i=0;i<ary.length;i++){
if(typeof ary[i]=="function"){
ary[i].call(this,e);
i++
}else{
ary.splice(i,1);
}
}
}
}
function off(ele,type,fn){
if(/^self/.test(type)){//自定义事件
var ary=ele[type];
if(ary){
for (var i=0;i<ary.length;i++){
if(ary[i]==fn){
ary[i]==null;
return;
}
}
}
}else{
if(ele.removeEventListener){
ele.removeEventListener(type,fn);
}else {
var aryEvent=ele["aEvent"+type];
if(aryEvent&& aryEvent.length){
for(var i=0;i<aryEvent.length;i++){
if(aryEvent[i]==fn){
aryEvent[i]=null;
return;
}
}
}
}
}
}
function bindThis(obj,fn){
return function(e){fn.call(obj,e)}
}