面向对象思想-封装拖拽对象

来源:互联网 发布:乐高ev3编程视频教程 编辑:程序博客网 时间:2024/04/30 02:57

1、我们常常会通过修改元素的top,left,translate来其的位置发生改变。修改元素的left,top值,但会引起页面重绘,而transform不会,所以要优先使用transform
2、如何获取当前浏览器支持的transform兼容写法
3、获取元素的初始位置:
4、需要绑定的事件:mousedown,mousemove,mouseup
而在移动端,分别与之对应的则是touchstart、touchmove、touchend。
5、原理

当事件触发时,我们可以通过事件对象获取到鼠标的精切位置。这是实现拖拽的关键。当鼠标按下(mousedown触发)时,我们需要记住鼠标的初始位置与目标元素的初始位置,我们的目标就是实现当鼠标移动时,目标元素也跟着移动,根据常理我们可以得出如下关系:
移动后的鼠标位置 - 鼠标初始位置 = 移动后的目标元素位置 - 目标元素的初始位置
如果鼠标位置的差值我们用dis来表示,那么目标元素的位置就等于:
移动后目标元素的位置 = dis + 目标元素的初始位置

通过事件对象,我们可以精确的知道鼠标的当前位置,因此当鼠标拖动(mousemove)时,我们可以不停的计算出鼠标移动的差值,以此来求出目标元素的当前位置。这个过程,就实现了拖拽。

而在鼠标松开(mouseup)结束拖拽时,我们需要处理一些收尾工作。

6、封装原则

如何合理的处理属性与方法的位置。

  • 构造函数中: 属性与方法为当前实例单独拥有,只能被当前实例访问,并且每声明一个实例,其中的方法都会被重新创建一次。

  • 原型中: 属性与方法为所有实例共同拥有,可以被所有实例访问,新声明实例不会重复创建方法。

  • 模块作用域中:属性和方法不能被任何实例访问,但是能被内部方法访问,新声明的实例,不会重复创建相同的方法。

对于方法的判断比较简单。

  • 因为在构造函数中的方法总会在声明一个新的实例时被重复创建,因此我们声明的方法都尽量避免出现在构造函数中。

  • 而如果你的方法中需要用到构造函数中的变量,或者想要公开,那就需要放在原型中。

  • 如果方法需要私有不被外界访问,那么就放置在模块作用域中。

对于属性的判断

对于属性放置于什么位置需要在实际开发中不断的总结经验。

  • 如果属性值只能被实例单独拥有,比如person对象的name,只能属于某一个person实例,又比如这里拖拽对象中,某一个元素的初始位置,也仅仅只是这个元素的当前位置,这个属性,则适合放在构造函数中。

  • 而如果一个属性仅仅供内部方法访问,这个属性就适合放在模块作用域中。

模块封装代码:

; //文件合并时,防止前一个文件末尾没加分号  (function() {    //私有属性,内部使用,不需实例访问    var transform = getTransform();    function Drag(selector) {      this.elem = typeof selector == 'object' ? selector : document.getElementById(selector);      this.startX = 0;      this.startY = 0;      this.sourceX = 0;      this.sourceY = 0;      this.init();    }    Drag.prototype = {      constructor: Drag,      init: function() {        this.setDrag();      },      getStyle: function(property) {        return window.getComputedStyle ? window.getComputedStyle(this.elem, null).getPropertyValue(property) : this.currentStyle.getAttribute(property);      },      //获取当前元素的位置信息,注意与之前的不同之处      getPosition: function() {        var pos = { x: 0, y: 0 };        if (transform) {          var transformValue = this.getStyle(transform);          if (transformValue == 'none') {            this.elem.style[transform] = 'translate(0,0)';          } else {            var temp = transformValue.match(/-?\d+/g);            pos = {              x: parseInt(temp[4].trim()),              y: parseInt(temp[5].trim())            }          }        } else {          if (this.getStyle('position') == 'static') {            this.elem.style.position = 'relative';          } else {            pos = {              x: parseInt(this.getStyle('left') ? this.getStyle('left') : 0),              y: parseInt(this.getStyle('top') ? this.getStyle('top') : 0)            }          }        }        return pos;      },      // 用来设置当前元素的位置      setPosition: function(pos) {        if (transform) {          this.elem.style[transform] = 'translate(' + pos.x + 'px, ' + pos.y + 'px)';        } else {          this.elem.style.left = pos.x + 'px';          this.elem.style.top = pos.y + 'px';        }      },      setDrag: function() {        var self = this;        this.elem.addEventListener('mousedown', start, false);        function start(event) {          //鼠标初始位置          self.startX = event.pageX;          self.startY = event.pageY;          var pos = self.getPosition();          self.sourceX = pos.x;          self.sourceY = pos.y;          document.addEventListener('mousemove', move, false);          document.addEventListener('mouseup', end, false);        }        function move(event) {          // 获取鼠标当前位置          var curX = event.pageX;          var curY = event.pageY;          // 计算差值          var disX = curX - self.startX;          var disY = curY - self.startY;          self.setPosition({            x: (self.sourceX + disX).toFixed(),            y: (self.sourceY + disY).toFixed()          });        }        function end(event) {          document.removeEventListener('mousemove', move);          document.removeEventListener('mouseup', end);          //do other things        }      }    }    //私有方法    function getTransform() {      var transform = '',        divStyle = document.createElement('div').style,        transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'];      //通过循环找出浏览器识别的那个,in操作符用于判断是否识别      for (var i = 0, len = transformArr.length; i < len; i++) {        if (transformArr[i] in divStyle) {          return transform = transformArr[i];        }      }      return transform;    }    window.Drag = Drag;  })();  new Drag('target');  new Drag('target2');

html:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Document</title>  <style>  * {    padding: 0;    margin: 0;  }  #target,  #target2 {    width: 50px;    height: 50px;    background-color: orange;    cursor: move;  }  #target2 {    background-color: red;  }  </style></head><body>  <div style="height:1000px">hha</div>  <div id="target"></div>  <div id="target2"></div> </body></html>

jquery实例方法扩展:

// 通过扩展方法将拖拽扩展为jQuery的一个实例方法(function ($) {  $.fn.extend({    becomeDrag: function () {      new Drag(this[0]);      return this;   // 注意:为了保证jQuery所有的方法都能够链式访问,每一个方法的最后都需要返回this,即返回jQuery实例    }  })})(jQuery);

参考链接:http://www.jianshu.com/p/b3dee0e84454
http://www.jianshu.com/p/3f97570d22b4

原创粉丝点击