Maison  >  Article  >  interface Web  >  Explication détaillée de l'encapsulation d'une propre instance de module

Explication détaillée de l'encapsulation d'une propre instance de module

小云云
小云云original
2018-01-30 17:16:081472parcourir

Essayez d'encapsuler un module glisser-déposer. J'ai connu quelques rebondissements dans le processus. Au début, j'avais prévu de n'utiliser que style.left, mais cela nécessitait une position de réglage : absolue. Cela peut avoir un certain impact sur le code. Bien que la transformation CSS affectera la compatibilité, j'utilise toujours ici la traduction de cet attribut pour terminer le déplacement.

Code complété avec le style uniquement

Pas grand chose à dire, passons directement au code :

html et css, la position doit être définie ici, c'est la première fois J'écris ce code je l'avais oublié à l'époque, mais au final, même si le JS était écrit correctement, l'effet ne pouvait pas sortir du tout... C'était vraiment court-circuité

<!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>

Le point ! ! 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');

Ce code est relativement facile à comprendre. Lorsque j'ai regardé pour la première fois le code de Bo Dashen, je n'ai en fait pas compris l'utilisation de la traduction car je n'ai pas réfléchi à la raison pour laquelle les expressions régulières étaient utilisées. ......

Bien que ce soit relativement simple, il faut quand même analyser le principe de ce code :

1 Il y a un constructeur Drag() dans la fonction auto-exécutable. . Les méthodes et propriétés que nous définissons dans la fonction sont uniques à chaque instance de constructeur, comme leurs informations de localisation, etc. Il existe trois méthodes dans le prototype : getPosition() pour obtenir des informations sur la position de l'élément, setPosition() pour définir la position de l'élément et setDrag() pour lier les événements. Puisque ces trois méthodes sont publiques, afin d'économiser des ressources, nous les mettons dans le fichier. prototype.

2. Le principe d'exécution de ce code est le suivant : lorsque la souris est enfoncée, les informations de position initiale de l'élément sourceX/Y et les informations de position initiale de la souris startX/Y sont obtenues ; le mouvement est terminé, la nouvelle position de la souris est obtenue currentX/Y, soustrayez les deux positions de la souris pour obtenir la distanceX/Y que la souris déplace, qui est également la distance parcourue par l'élément. Ensuite, nous attribuons cette valeur à celle de l'élément. style.left/top. Le glissement des éléments est réalisé.

La combinaison de la transformation et du style

En raison du développement de la technologie, de plus en plus d'appareils commencent à prendre en charge CSS3. De plus, le style consomme plus de ressources et a des problèmes d'efficacité, c'est pourquoi nous. Pensez à utiliser transform.

Écriture compatible avec le navigateur

Nous ajoutons d'abord un attribut privé avant la fonction Drag() :

var transform = getTransform();

Ajoutez une méthode privée ci-dessous :

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 : N'oubliez pas la méthode createElement(), elle sera utile la prochaine fois pour déterminer la compatibilité des navigateurs !

Nous devons également ajouter une fonction sous getPosition() sous la même forme :

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 : La raison pour laquelle nous devons déterminer si transformValue vaut none est parce que dans l'état d'initialisation Oui, l'élément n'a pas été défini avec l'attribut transform, donc le tableau après régularisation ne peut pas trouver [4][5], nous définissons donc les deux attributs de val à 0, qui sont les valeurs de TranslateX et TranslateY qui deviendront transform plus tard .

Continuez à écrire du code. Dans le paragraphe ci-dessus, nous avons utilisé pour extraire les valeurs X et Y de translation. Regardez le paragraphe suivant :

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

Faites attention au contenu du code ci-dessus que nous avons modifié. Ici, nous avons ajouté un jugement : lorsqu'un navigateur prenant en charge l'attribut transform existe, nous utiliserons l'attribut transform. pour modifier l'élément Value, attribuez les x et y précédemment obtenus dans getTranslate aux x et y de pos.

Dans le morceau de code ci-dessus, nous utiliserons différentes méthodes pour obtenir la même valeur selon le navigateur. La valeur de val provient de getTranslate(), que nous extrayons de la transformation de l'élément. De même, dans setPosition() ci-dessous, nous devons également définir le jugement 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';
      }
    },

Il n'y a rien à dire dans ce paragraphe, il s'agit simplement d'attribuer des valeurs sous différentes formes.

À ce stade, le module est empaqueté. Examinons ensuite le code complet :

;
(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');

Recommandations associées :

implémentation du module d'encapsulation de variables globales javascript code_javascript skills

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn