面向对象中,尽量避免函数嵌套;公共用的东西放在构造函数(constructor)里面,初始位置是公共的东西,大家都能用;尽量保证所有的this指向实例;
Drag.js 拖拽
拖拽三个函数,按下
down
,移动move
,抬起up
class Drag{
// 构造函数 实例可以调用 私有属性和方法
constructor(opt){
// 保证opt存在,不出错
opt=opt||{};
if(!opt.el) return;
this.el=opt.el; // 获取这个元素
this.l=null;
this.t=null;
this.x=null;
this.y=null;
this.DOWN=processThis(this.down,this);
this.MOVE=this.UP=null;
this.xtimer=this.ytimer=null;
on(this.el,'mousedown',this.DOWN);
}
down(e){
// 按下的时候保存元素的初始位置 事件.clientX/clientY:鼠标落脚点距离浏览器边框的距离;offsetX/offsetY:鼠标落脚点距离物体自身边距的距离,也就是鼠标落脚点到物体的距离;[元素.offsetLeft/offsetTop]:表示元素自身的宽度和高度,元素才有offsetLeft/offsetTop
this.x=e.clientX; // 鼠标落脚点距离浏览器边框的距离
this.y=e.clientY;
this.l=this.el.offsetLeft; //元素的宽高
this.t=this.el.offsetTop;
this.MOVE=processThis(this.move,this);
this.UP=processThis(this.up,this);
//分浏览器来进行事件调用-背景背选中的问题和失去焦点的问题;
if(this.el.setCapture){
// 标准浏览器
this.el.setCapture();
on(this.el,'mousemove',this.MOVE);
on(this.el,'mouseup',this.UP);
}else{
on(document,'mousemove',this.MOVE);
on(document,'mouseup',this.UP);
//阻止默认事件
e.preventDefault();
}
//跟拖拽无关的:按下的时候,停止定时器
clearTimeout(this.xtimer);
clearTimeout(this.ytimer);
}
move(e){
// 求出最新的位置
var l=e.clientX-this.x+this.l;
var t=e.clientY-this.y+this.t;
// 最大的边界
var maxL=(document.documentElement.clientWidth||document.body.clientWidth)-this.el.offsetWidth;
var maxT=(document.documentElement.clientHeight||document.body.clientHeight)-this.el.offsetHeight;
// 边界判断
if(l<=0){
l=0;
}else if(l>=maxL){
l=maxL;
}
if(t<=0){
t=0;
}else if(t>=maxT){
t=maxT;
}
this.el.style.left=l+'px';
this.el.style.top=t+'px';
}
up(){
//IE释放焦点捕获
if(this.el.releaseCapture){
this.el.releaseCapture();
off(this.el,'mousemove',this.MOVE);
off(this.el,'mouseup',this.UP);
}else{
off(document,'mousemove',this.MOVE);
off(document,'mouseup',this.UP);
}
}
}
event.js 事件函数
事件的绑定和解除绑定 改变事件函数里面的this
//给自己事件池绑定许多方法,即都绑到数组中去了;
function on(ele,type,fn){
// 浏览器的判断
if(ele.addEventListener){
ele.addEventListener(type.fn,false);
}else{
// IE浏览器
if(!ele['on'+type]){
ele['on'+type]=[]; // 给ele['on'+type]属性上赋值一个空数组
//这里用来解决run的重复绑定问题;
// 绑定事件
ele.attachEvent('on'+type,function(){
run.call(ele);
})
}
//解决重复问题
for(var i=0; i<ele['on'+type].length; i++){
if(ele['on'+type][i]==fn) return;
}
a.push(fn);
}
}
//拿到数组,顺序调用(是函数,才能调用)
function run(){
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.preventDefault=function(){
e.returnValue=false;
};
e.stopPropagation=function(){
e.cancelBubble=true;
};
if(this['on'+e.type].length){
for(var i=0; i<this['on'+e.type].length; i++){
if(typeof this['on'+e.type][i]==='function'){
this['on'+e.type][i].call(this,e);
}else{
this['on'+e.type].splice(i,1);
i--;
}
}
}
}
//拿到数组,循环匹配,匹配到谁,赋值为null;
function off(ele,type,fn){
if(ele.removeEventListener){
ele.removeEventListener(type,fn,false);
}else{//IE
var a=ele['on'+type];
if(a.length){
for(var i=0; i<a.length; i++){
if(a[i]===fn){
a[i]=null;
break;
}
}
}
}
}
// 改变事件函数里面的this指向
function processThis(fn,argThis){
return function(e){
e=e||window.event;
fn.call(argThis,e);
}
}
测试代码
<script>
var oDiv=document.getElementById('div');
var drag1=new Drag({
el:oDiv
});
drag1.on('myDown',fn1).on('myDown',fn2).on('myDown',fn3).on('myMove',fn4).on('myMove',fn5).on('myUp',fn6).on('myUp',fn7);
function fn1(){
console.log('down行为下的:'+1)
}
function fn2(){
console.log('down行为下的:'+2)
}
function fn3(){
console.log('down行为下的:'+3)
}
function fn4(){
console.log('move行为下的:'+4)
}
function fn5(){
console.log('move行为下的:'+5)
}
function fn6(){
console.log('up行为下的:'+6)
}
function fn7(){
console.log('up行为下的:'+7)
}
</script>
网友评论