阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      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)}
      }
      
      目录
      目录