尝试封装一个本身的模块

上一周学了闭包和模块,这一周仍然是随着@波同砚,试着封装了一个拖拽模块。过程当中阅历了一些迂回,最最先我是盘算只用style.left的体式格局,然则这个须要设置position:absolute。可能对代码形成肯定影响。虽然CSS的transform会影响兼容,但这里我照样运用了这个属性的translate来完成挪动。

只用style完成的代码

话不多说,直接上代码:

html和css,这里必需设置position,第一次写这段代码的时刻忘了,结果只管JS写对了,结果完全出不来….真是短路了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>进修</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        #box{
            width: 200px;
            height: 200px;
            background: #6f6;
            font-size: 20px;
            cursor:move;
            position: absolute;
        }
    </style>

</head>
<body>
  <div id="box"></div>
  <script src="js/drag_module.js"></script>
</body>
</html>

重点!!JS

;    //这个分号是为了防备其他的模块末了遗忘加分号,致使毛病。
(function() {
  
  //组织函数,属于每个实例
  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();
    },

    //用于猎取元素当前的位置信息
    getPosition: function() {
      var that = this;
      var pos = {};
      pos = {
        x: that.elem.offsetLeft,
        y: that.elem.offsetTop
      };
      return pos;
    },
    //用来设置当前元素的位置
    setPosition: function(pos) {
      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 currentX = event.pageX; //当前的鼠标x位置
        var currentY = event.pageY; //当前的鼠标y位置

        var distanceX = currentX - self.startX; //鼠标挪动的间隔x
        var distanceY = currentY - self.startY; //鼠标挪动的间隔y

        self.setPosition({
          x: self.sourceX + distanceX,
          y: self.sourceY + distanceY
        });

      }

      function end(event) {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', end);
      }
    }
  };
  
  //暴露在外
  window.Drag = Drag;
})();


new Drag('box');

这段代码是比较好邃晓的,在一最先看波大神的代码时,关于translate的应用实际上我没看太邃晓,因为没想到为啥要用到正则……

虽然比较简单,然则我们照样要剖析一下这段代码的道理:

1.自实行函数里有一个组织函数Drag(),在组织函数里我们设置的要领和属性时每个组织函数实例独占的,比方他们的位置信息等。而在原型里的有三个要领:分别是猎取元素位置信息的getPosition()、设置元素位置的setPosition()和绑定事宜的setDrag(),这三个因为是公用的,为了节约资本,我们就放在原型里了。

2.这段代码实行的道理是:当鼠标按下时,猎取元素初始位置信息sourceX/Y、鼠标初始位置信息startX/Y;当鼠标挪动完成时,猎取鼠标新的位置currentX/Y,两个鼠标位置相减就可以获得鼠标挪动的间隔distanceX/Y,这同时也是元素挪动的间隔,然后,我们把这个值赋给元素的style.left/top。元素的拖拽就完成了。

transform和style的连系

因为手艺的生长,越来越多的装备最先支撑CSS3了,加上style的资本占用的更多,效力方面存在题目,所以我们斟酌运用transform。

浏览器的兼容写法

我们首先在函数Drag()前加上私有属性:

var transform = getTransform();

鄙人面再加上私有要领:

function getTransform() {
    var transform = "",
      divStyle = document.createElement('div').style,
      transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'],
      i = 0,
      l = transformArr.length;

    for (; i < l; i++) {
      if (transformArr[i] in divStyle) {
        return transform = transformArr[i];
      }
    }
    return transform;
  }

PS:记着createElement()这个要领,下次推断浏览器兼容时用得着!

我们还须要在getPosition()的下面加上一个函数,用一样的情势:

getTranslate: function() {
      var val = {};
      var transformValue = document.defaultView.getComputedStyle(this.elem, false)[transform];
      if(transformValue=='none'){
        val={x:0,y:0};
      }else{
        var transformArr = transformValue.match(/-?\d+/g);
        val = {
          x: Number(transformArr[4]),
          y: Number(transformArr[5])
        };
      }


      return val;
    },

PS:之所以要推断transformValue是不是为none,是因为在初始化状况是,元素未被设置transform属性,如许正则以后的数组是找不到[4][5] 的,所以我们让val的两个属性为0,也就是稍后会成为的transform的translateX和translateY的值。

继承写代码。上面一段我们用来提取translate的X、Y值。看下面一段:

getPosition: function() {
      var that = this;
      var pos = {};
      if(transform){
        var val=this.getTranslate();
        pos={
          x:val.x,
          y:val.y
        };
      }else{
        pos = {
          x: that.elem.offsetLeft,
          y: that.elem.offsetTop
        };
      }
      return pos;
    },

注重上面一段代码我们修正的的内容,在这里我们增加了一个推断:即当支撑transform属性的浏览器存在时,我们会用transform属性修正元素的值,把之前在getTranslate中获得的x、y赋值给pos的x、y。

在上面一段代码中,我们会依据浏览器的状况,用差别的要领取到雷同的值,val的值来自getTranslate(),是我们从元素的transform中提取出来的。一样,鄙人面的setPosition()中,我们也要设置if推断。

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';
      }
    },

这一段没什么好讲的,就是用差别的情势赋值罢了。

到这里,这个模块就封装终了了。接下来让我们看看完全代码:

;
(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();
    },

    //用于猎取元素当前的位置信息
    getPosition: function() {
      var that = this;
      var pos = {};
      if(transform){
        var val=this.getTranslate();
        pos={
          x:val.x,
          y:val.y
        };
      }else{
        pos = {
          x: that.elem.offsetLeft,
          y: that.elem.offsetTop
        };
      }
      return pos;
    },

    //猎取translate值
    getTranslate: function() {
      var val = {};
      var transformValue = document.defaultView.getComputedStyle(this.elem, false)[transform];
      if(transformValue=='none'){
        val={x:0,y:0};
      }else{
        var transformArr = transformValue.match(/-?\d+/g);
        val = {
          x: Number(transformArr[4]),
          y: Number(transformArr[5])
        };
      }


      return val;
    },
    //用来设置当前元素的位置
    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 currentX = event.pageX; //当前的鼠标x位置
        var currentY = event.pageY; //当前的鼠标y位置

        var distanceX = currentX - self.startX; //鼠标挪动的间隔x
        var distanceY = currentY - self.startY; //鼠标挪动的间隔y

        self.setPosition({
          x: self.sourceX + distanceX,
          y: self.sourceY + distanceY
        });

      }

      function end(event) {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', end);
      }
    }
  };
  //私有要领,用来猎取transform的兼容写法
  function getTransform() {
    var transform = "",
      divStyle = document.createElement('div').style,
      transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'],
      i = 0,
      l = transformArr.length;

    for (; i < l; i++) {
      if (transformArr[i] in divStyle) {
        return transform = transformArr[i];
      }
    }
    return transform;
  }
  //暴露在外
  window.Drag = Drag;
})();


new Drag('box');
    原文作者:WE2008311
    原文地址: https://segmentfault.com/a/1190000013053894
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞