首頁 > web前端 > js教程 > 主體

封裝一個自己的模組實例詳解

小云云
發布: 2018-01-30 17:16:08
原創
1478 人瀏覽過

試著封裝了一個拖曳模組。過程中經歷了一些曲折,我打算只用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>
  <p id="box"></p>
  <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 = "",
      pStyle = document.createElement('p').style,
      transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'],
      i = 0,
      l = transformArr.length;

    for (; i < l; i++) {
      if (transformArr[i] in pStyle) {
        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 = "",
      pStyle = document.createElement('p').style,
      transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'],
      i = 0,
      l = transformArr.length;

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


new Drag('box');
登入後複製

相關推薦:

javascript全域變數封裝模組實作程式碼_javascript技巧

#

以上是封裝一個自己的模組實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!