Maison  >  Article  >  interface Web  >  JavaScript implémente l'effet glisser-déposer dans les pages Web PC_javascript skills

JavaScript implémente l'effet glisser-déposer dans les pages Web PC_javascript skills

WBOY
WBOYoriginal
2016-05-16 15:10:551482parcourir

Il y a quelques années, j'ai participé à la conception et au développement d'un projet de site Web immobilier. J'étais responsable du travail front-end. Le chef de projet ayant des exigences relativement élevées, j'ai fait référence à de nombreuses excellentes fonctionnalités de l'immobilier. sites Web et je voulais collecter les excellentes conceptions et idées d'autres personnes. Lorsque nous nous sommes réunis, le projet de conception et la mise en œuvre des fonctions à cette époque ont simplement été modifiés encore et encore. Un bon effet obtenu aujourd'hui devra peut-être être repoussé au lendemain. ça, n'en parlons pas. Parlons-en. Parlons du cas que nous allons expliquer aujourd'hui. Je ne sais pas si vous avez visité Soufun.com (il n'est pas du tout soupçonné de publicité. Soufun peut-il payer. quelques frais de publicité ?), il y a une fonction que le chef de produit apprécie particulièrement, à savoir la suivante :

C'est l'effet actuel, peut-être quelques changements. L'effet original est que l'image à l'intérieur peut être déplacée vers le haut, le bas, la gauche et la droite, puis le numéro du bâtiment affiché sur la maison se déplace également avec l'image. time, js La capacité n'était pas assez bonne et les exigences du chef de projet n'étaient pas satisfaites, mais plus tard, le chef de projet a rejeté cet effet et l'a remplacé par un autre effet

Bien que le chef de projet ne souhaitait pas cet effet, cela m’a laissé un nœud dans le cœur à ce moment-là, et je ne peux pas l’oublier encore aujourd’hui.

D'accord, c'est mon intention initiale en écrivant ce blog aujourd'hui. J'espère qu'il pourra fournir une idée aux étudiants qui souhaitent obtenir ce genre d'effet de traînée, mais qui ne savent pas comment y parvenir, afin de ne pas partir. aucun regret pour leur jeunesse. Bien sûr, il existe de nombreuses façons d'implémenter le glisser-déposer. Ici, je ne présenterai qu'une seule méthode en JavaScript, et je comprendrai lentement le principe !

D'accord, les blagues sont terminées, passons aux choses sérieuses. Il faut d'abord comprendre ce qu'est la traînée. Vous le savez, et je le sais, mais j'ai quand même envie de le décrire :

Le glisser-déposer est un conteneur. Vous pouvez utiliser la souris pour le faire glisser sur la page, la description précise doit être, déplacez la souris vers le conteneur, puis appuyez sur la souris, faites attention à ne pas la relâcher. puis faites glisser La souris et le conteneur peuvent suivre la souris. Lorsque vous relâchez la souris, le conteneur s'arrête là. Un exemple concret est qu'il y a une boîte sur la table, puis je bouge. la boîte. Quand ma main s’arrête, la boîte s’arrête, enlève-la, la boîte ne bouge pas, héhé, je comprends !

Ne pensez pas que ce qui précède est beaucoup de bêtises, nous pouvons en tirer beaucoup d'informations, le résumé est le suivant :

Glisser = souris vers le bas + mouvement de la souris + souris vers le haut

Cela termine une tâche de glisser-déposer. Eh bien, il s'avère que c'est le principe du glisser-déposer. Si vous souhaitez implémenter le glisser-déposer, vous pouvez naturellement implémenter les trois actions ci-dessus pour simuler l'effet glisser-déposer. . Eh bien, cela correspond à la syntaxe en JavaScript. Il suffit de mettre en œuvre ces 3 actions :

.

onmousedown, onmousemove, onmouseup

Le code implémenté doit être :

obj.onmousedown = function(ev){
   obj.onmousemove = function(ev){
 
   } ;
   obj.onmouseup = function(ev){
   
   };
   
}

Pourquoi les deux actions suivantes devraient-elles y être écrites ? Réfléchissons bien. D'accord, l'idée générale de la première étape est là. L'étape suivante consiste à réfléchir à la manière de faire bouger l'objet avec la souris. L'idée est probablement la suivante :

Tout d'abord, l'objet doit être positionné, car nous devons manipuler ses valeurs gauche et supérieure pour le faire bouger. Ensuite, nous devons considérer le déplacement de la souris lui-même. savoir que la souris s'est déplacée À quelle distance se trouve-t-elle ? Donnez ensuite cette distance à l'objet. L'objet se déplace-t-il à la même distance que la souris ? Haha, j'ai quelques idées, et c'est mignon ~ Le problème maintenant est de savoir comment obtenir la distance de la souris. Si vous avez besoin d'en savoir plus, veuillez consulter le modèle de boîte, je n'entrerai pas dans les détails ici. De nombreux maîtres ont également des blogs connexes. J'en utilise un. Voici une photo pour le montrer :

.

Explication : La case bleue est la largeur et la hauteur de l'écran, la case noire épaisse est la largeur et la hauteur de la zone visible du navigateur (effet de réduction du navigateur), la case noire fine est l'objet à faire glisser par la souris , comme le montre la figure, obtenez les coordonnées de la souris , vous pouvez utiliser event.clientX, event.clientY pour l'obtenir, oh;

Le principe général de calcul peut se référer à la figure ci-dessous :

Explication : La gauche est la position initiale, la droite est la position cible, l'origine est la position de la souris, la grande case noire est la largeur visible du navigateur, la petite case noire est l'objet glisser, voir l'état Faites glisser l'objet vers la position cible et obtenez la souris La position finale de la souris, puis soustrayez la différence entre la souris et l'objet, puis attribuez-la aux valeurs supérieure et gauche de l'objet. peut également obtenir la différence de position de la souris, puis ajouter la différence aux valeurs initiales en haut et à gauche. Nous utilisons le premier. Le deuxième type est également possible, essayez-le vous-même :

.

 obj.onmousedown = function(ev){
  var ev = ev || event;
  var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;
 
  document.onmousemove = function(ev){
    var ev = ev || event;
    obj.style.left = ev.clientX - disX + 'px';
    obj.style.top = ev.clientY - disY + 'px';
  };
  document.onmouseup = function(ev){
    var ev = ev || event;
    document.onmousemove = document.onmouseup = null;
  };
}

这里说明一下:onmousemove和onmouseup之所以用document对象而不用obj对象,是因为如果用obj对象,鼠标在obj内部还好,如果在obj外面的话,拖拽会很怪异,你也可以改成obj体会一下,最后我们在鼠标弹起的时候将事件都清空;

上面的基本拖拽就算完成了,但是细心的同学一定会问,如果页面上有文字的话,拖拽物体会将文字选中,这效果岂不是怪怪的,没错,这是因为拖拽的时候触发了浏览器的默认选择事件,所以,在拖拽的时候,我们要清除这个默认事件,那怎么清除呢?

下面给一个兼容性写法:

if(ev.stopPropagation){
   ev.stopPropagation();
}else{
  ev.cancelBubble = true; //兼容IE
}
//简写成
ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;

将上面的代码放在onmousedown下,鼠标按下就清除浏览器默认事件,文字就不会被选中了,好了,一个简单的拖拽效果就完成了,当然你现在是看不到效果,之所以不给demo链接是为了让你自己试着写一写,这样印象更深刻,

好了,那问题又来了,到这里就这样完了吗?。。。。。。按本人的风格,当然没有,干货还在后面!

如果我想实现这样一个效果,就是这一个大的容器里面(可以是box,也可以是document),怎么样能让我们的拖拽对象不跑出去呢,换句话说,拖到边缘就拖不动了,耶,是不是很多人想要实现的效果,哈哈,我们看看实现的原理是什么:

现实生活中,一个物体在一个盒子里跑不出去,是因为有堵墙,那我们只要能模拟出这堵墙,就可以把物体框起来,那这堵墙要怎么做呢?我们可以换个思路,当拖拽对象拖到边缘的时候,比如说拖到右边,我们将它的left固定住,是不是就不能再往右了,因为left值不能再加了,那么拖到底部,同理我们将top值固定住,就不能再往下拖了,理解吗?

最终的结果就是如下:

//左侧
if(obj.offsetLeft <=0){
  obj.style.left = 0;
};
//右侧
if(obj.offsetLeft >= pWidth - oWidth){
  obj.style.left = pWidth - oWidth + 'px'; 
};
//上面
if(obj.offsetTop <= 0){
  obj.style.top = 0; 
};
//下面
if(obj.offsetTop >= pHeight - oHeight){
  obj.style.top = pHeight - oHeight + 'px'; 
};

说明:pWidth,pHeight 表示父级元素的宽高(这里是表示相对于父级的宽高限制),oWidth,oHeigt表示拖拽元素的宽高

最后,我将整个拖拽代码整理了一下:

/*
      参数说明:
      元素绝对定位,父级相对定位,如果父级为window,则可以不用
      传一个参数,表示父级为window,物体相对于window范围拖动
      传2个参数,则父级为第二个参数,物体相对于父级范围拖动
      参数为id值
    */
    function drag(obj,parentNode){
      var obj = document.getElementById(obj);
      if(arguments.length == 1){
        var parentNode = window.self; 
        var pWidth = parentNode.innerWidth,pHeight = parentNode.innerHeight;  
      }else{
        var parentNode = document.getElementById(parentNode);
        var pWidth = parentNode.offsetWidth,pHeight = parentNode.offsetHeight;
      }
      obj.onmousedown = function(ev){
        var ev = ev || event;
        var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;
        var oWidth = obj.offsetWidth,oHeight = obj.offsetHeight;
         
        //阻止冒泡时间
        ev.stopPropagation &#63; ev.stopPropagation() : ev.cancelBubble = true;
       
         
        document.onmousemove = function(ev){
          var ev = ev || event;
          obj.style.left = ev.clientX - disX + 'px';
          obj.style.top = ev.clientY - disY + 'px';
           
          //左侧
          if(obj.offsetLeft <=0){
            obj.style.left = 0;
          };
          //右侧
          if(obj.offsetLeft >= pWidth - oWidth){
            obj.style.left = pWidth - oWidth + 'px'; 
          };
          //上面
          if(obj.offsetTop <= 0){
            obj.style.top = 0; 
          };
          //下面
          if(obj.offsetTop >= pHeight - oHeight){
            obj.style.top = pHeight - oHeight + 'px'; 
          };
        };
        document.onmouseup = function(ev){
          var ev = ev || event;
          document.onmousemove = document.onmouseup = null;
        };
      }
         
    }

说明:我这里处理的效果是,如果传一个参数,表示相对的对象是window对象,如果传2个参数,第一个是拖拽对象,第二个为相对父级

开篇就说了,搜房网的那个图片拖拽效果是我的一个心结,我写了一个类似的效果,供大家参考,因为自己没有买服务器,所以效果我就不展示了,直接把代码贴出来,供大家参考:

css:

<style>
.box{
  width:600px;
  height:400px;
  margin:50px auto;
  position:relative;
  overflow:hidden;
}
#box{
  width:1000px;
  height:800px;
  position:absolute;
  left:50%;
  top:50%;
  margin:-400px 0 0 -500px;
}
#pic{ width:800px; height:600px; background:url(images/pic1.jpg) no-repeat; position:absolute; left:100px; top:100px; }
#pic:hover{
  cursor:move;
}
</style>

html:

<div class="box">
    <div id="box">
      <div id="pic"></div>
    </div>
  </div>

javascript:

window.onload = function(){
     
    drag("pic","box");
    function drag(obj,parentNode){
      var obj = document.getElementById(obj);
      if(arguments.length == 1){
        var parentNode = window.self; 
        var pWidth = parentNode.innerWidth,pHeight = parentNode.innerHeight;  
      }else{
        var parentNode = document.getElementById(parentNode);
        var pWidth = parentNode.offsetWidth,pHeight = parentNode.offsetHeight;
      }
      obj.onmousedown = function(ev){
        var ev = ev || event;
        var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;
        var oWidth = obj.offsetWidth,oHeight = obj.offsetHeight;
         
        //阻止冒泡时间
        ev.stopPropagation &#63; ev.stopPropagation() : ev.cancelBubble = true;
       
         
        document.onmousemove = function(ev){
          var ev = ev || event;
          obj.style.left = ev.clientX - disX + 'px';
          obj.style.top = ev.clientY - disY + 'px';
           
          //左侧
          if(obj.offsetLeft <=0){
            obj.style.left = 0;
          };
          //右侧
          if(obj.offsetLeft >= pWidth - oWidth){
            obj.style.left = pWidth - oWidth + 'px'; 
          };
          //上面
          if(obj.offsetTop <= 0){
            obj.style.top = 0; 
          };
          //下面
          if(obj.offsetTop >= pHeight - oHeight){
            obj.style.top = pHeight - oHeight + 'px'; 
          };
        };
        document.onmouseup = function(ev){
          var ev = ev || event;
          document.onmousemove = document.onmouseup = null;
        };
      }
         
    }
     
     
  }

效果完全是用的那个封装代码块,引用起来也挺方便,有人会问了,你这用的id获取DOM元素,一个页面只能用一次啊,如果页面多次使用呢,有道理,解决方案之一,那就命名不同的id呗,又不犯法,方案二,获取id的地方改成获取class,但是要注意的是,getElementsByClassName是获取的class集合,需要改写一下,这里我就不写了,有兴趣的同学自行改写一下,好了,到这里真的结束了!

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