Ce qui suit est une explication très détaillée de la façon de faire glisser et d'ajuster l'ordre des images d'imitation Weibo. Il y a certainement des lacunes dans l'article. Bienvenue à critiquer et à corriger. Pas grand chose de bêtises, regardons le contenu spécifique.
Cliquez ici pour participerTéléchargement du code source
Qu'est-ce que le tri d'images par glisser-déposer ?
Tout comme Weibo, les utilisateurs sont autorisés à ajuster l'ordre de plusieurs images en les faisant glisser après le téléchargement.
Vous pouvez voir que Weibo a corrigé la taille de chaque image ici. Si vous êtes un peu plus strict, vous devez être comme l'article précédent, avec plusieurs conteneurs div réactifs de hauteur et de largeur égales à l'extérieur. , qui contient des images réactives à échelle proportionnelle.
Voici les exigences suivantes.
1. Bien sûr, l'image doit d'abord pouvoir être déplacée.
2. Déplacez l'image hors de sa position d'origine, faites-la glisser vers la position cible, et avant de terminer le glissement sans relâcher la souris, vous devez définir un espace réservé à la position cible pour permettre à l'utilisateur de prévisualiser l'effet après. le glissement est terminé.
3. Réactif. Une fois la taille modifiée, les exigences ci-dessus peuvent toujours être remplies.
4. Compatible avec autant de navigateurs que possible. En fait, j'ai écrit le précédent article pour ouvrir la voie à celui-ci, donc celui-ci est également compatible avec IE7.
Effet final
chrome
ie8
ie7
Le premier, c'est de glisser.
Le proxy utilisé ici signifie qu'il y a un div supplémentaire dans la mise en page d'origine, et l'objet réellement déplacé est ce div plus précisément,
.<div id='wrap' ms-controller='drag_sort' class='ms-controller'> <ul ms-mousemove='drag_move($event)'> <li ms-repeat='photo_list'> <div ms-mousedown='start_drag($event,$index,el)'> <div class="dummy"></div> <p ms-attr-id='wrap_img{{$index}}'><img ms-attr-src="el.src"><i></i></p> </div> </li> </ul> <div id='drag_proxy'></div> </div>
Liez mousedown à chaque cellule. Lorsque start_drag est déclenché, placez l'image dans la cellule dans le proxy
. notez-le. La position actuelle du clic de la souris, et la position du clic est utilisée comme point central du rectangle div du proxy (image), le proxy est affiché et l'image cliquée est masquée.start_drag:function(e,i,el){ var img=$('wrap_img'+i).firstChild,target_img_width=img.clientWidth,target_img_height=img.clientHeight; drag_sort.cell_size=$('wrap_img0').clientWidth; var xx=e.clientX-target_img_width/2,yy=e.clientY-target_img_height/2,offset=avalon($(drag_sort.container)).offset(),target=e.target.parentNode.parentNode.parentNode; $('drag_proxy').style.top=yy+avalon(window).scrollTop()-offset.top+'px'; $('drag_proxy').style.left=xx-offset.left+'px'; $('drag_proxy').style.width=target_img_width+'px'; $('drag_proxy').style.height=target_img_height+'px'; if(target&&target.nodeName=='LI'){ ori_src=el; // $('drag_proxy').innerHTML=target.querySelector('p').innerHTML; $('drag_proxy').innerHTML=$('wrap_img'+i).innerHTML; $('drag_proxy').style.display='block'; drag_sort.target_index=i; drag_flag=true; } if(isIE) target.setCapture(); avalon.bind(document,'mouseup',function(){ up(target); }); e.stopPropagation(); e.preventDefault(); }
Notez quelques points :
1.drag_sort.cell_size enregistre la taille de la cellule actuelle. Le rapport hauteur/largeur ici est de 1:1. La mise en page étant réactive, elle doit être enregistrée. Vous pourrez voir comment l’utiliser plus tard.
2. La cible de l'événement doit déterminer s'il est déclenché par la balise img, car la position du clic peut être la zone vide entre la cellule et l'image.
3.ori_src est utilisé pour enregistrer l'image de la cellule actuelle, car la cellule à la position d'origine de l'image sera supprimée lors du déplacement de la souris ultérieurement.
4.drag_sort.target_index enregistre l'index de la cellule actuelle, et comparera plus tard cet index avec l'index de la cellule vers laquelle l'agent se déplace.
5.drag_flag indique si le déplacement de la souris est autorisé.
6. Par exemple, target.setCapture(); sinon
Vous pouvez voir que le comportement par défaut du navigateur sera exécuté lors du glisser.
7.event.preventDefault(); doit également être ajouté, sinon le comportement par défaut du navigateur se produira. Par exemple, lorsque Firefox fera glisser une image, il ouvrira un nouvel onglet et affichera l'image.
Vient ensuite mousemove, qui est lié à la balise ul. Les événements tels que mousemove et mouseup sont généralement liés à plusieurs éléments parents communs qui doivent être déclenchés, réduisant ainsi le nombre d'objets auxquels l'événement est lié.
Spécifique
drag_move:function(e){ if(drag_flag){ var xx=e.clientX,yy=e.clientY,offset=avalon($(drag_sort.container)).offset(); var x=xx-offset.left,y=avalon(window).scrollTop()+yy-offset.top; var x_index=Math.floor(x/drag_sort.cell_size),y_index=Math.floor(y/drag_sort.cell_size),move_to=3*y_index+x_index; $('drag_proxy').style.top=y-drag_sort.cell_size/2+'px'; $('drag_proxy').style.left=x-drag_sort.cell_size/2+'px'; if(move_to!=drag_sort.target_index){ drag_sort.photo_list.removeAt(drag_sort.target_index); drag_sort.photo_list.splice(move_to,0,{src:'1.jpg'}); drag_sort.target_index=move_to; } } e.stopPropagation(); }
Quelques notes
1.drag_flag garantit que mousedown doit être déclenché avant que mousemove puisse être déclenché.
2.drag_sort.container est l'élément racine de la mise en page entière, voici
.#wrap{ position: relative; max-width: 620px; font-size: 0; } #drag_proxy{ position: absolute; border:1px solid #009be3; z-index: 100; display: none; }
Lors d'un calcul ultérieur, vous devez soustraire la gauche et le haut de l'élément racine.
3. La barre de défilement verticale du navigateur avalon(window).scrollTop() doit également être prise en compte lors du calcul.
4. La taille de chaque cellule est toujours la même, donc la position où le curseur se déplace directement est divisée par le nombre de lignes et de colonnes, et arrondie pour obtenir l'index de la cellule cible.
5.move_to!=drag_sort.target_index La cellule vers laquelle le curseur actuel est déplacé n'est pas la cellule où réside à l'origine l'image Supprimez la cellule à l'emplacement d'origine de l'image et insérez une cellule d'espace réservé dans la cellule cible. A ce moment, l'image déplacée n'a pas encore été placée dans la cellule cible, et l'index de la cellule initiale est enfin mis à jour
.Enfin, passez la souris
function up(target){ if(isIE) target.releaseCapture(); var target_index=drag_sort.target_index; if(ori_src&&target_index!=-1){ drag_sort.photo_list.splice(target_index,1); drag_sort.photo_list.splice(target_index,0,ori_src); } drag_holder=null; drag_flag=false; drag_sort.target_index=-1; $('drag_proxy').style.display='none'; avalon.unbind(document,'mouseup'); }
判断ori_src&&target_index!=-1目的在于排除在非绑定对象上mouseup这种无效操作。因为是在document上绑定mouseup,就要排除类似于随便在空白处点击这种情况。这时不能对单元格删除,插入。
然后是把各变量设为初始值。
图片效果:
HTML代码:
<div id='post_img' ms-controller='post_img'> <ul id='post_img_inner' ms-mousemove='onmousemove'> <li ms-repeat-el="post_img_list" class='inline-block' ms-mousedown='onmousedown($event,$index,el)' ms-attr-id='post_img_item{{$index}}'> <img ms-src='el' class='uploaded_img'></li> </ul> </div>
JS代码:
var drag_holder=null,index=-1,ori_src=null,drag_flag=false;//拖动的代理,原图片,原图片的src var post_img = avalon.define('post_img', function(vm) { vm.post_img_list=[];//保存所有图片的src vm.onmousedown=function(e,i,el){ $('drag_proxy').style.display='block'; var target=e.target.parentNode; var xx = e.clientX; var yy = e.clientY; $('drag_proxy').style.top=yy+'px'; $('drag_proxy').style.left=xx+'px'; if(target&&target.nodeName=='LI'){ ori_src=el; index=target.getAttribute('id').substring(13); $('drag_proxy').innerHTML=target.innerHTML; post_img.post_img_list.splice(i, 1, 'about:blank'); } drag_flag=true; }; vm.onmousemove=function(e){ if(drag_flag){//如果点下了图片 var xx = e.clientX; var yy = e.clientY; $('drag_proxy').style.top=yy+'px'; $('drag_proxy').style.left=xx+'px'; var x=xx-avalon($('post_img')).offset().left; var y=yy-avalon($('post_img')).offset().top; //例子没有考虑滚动条的情况 var x_index=Math.floor(x/100);//图片尺寸100*100 var y_index=Math.floor(y/100); post_img.post_img_list.splice(index, 1);//删除当前图片的li var target_index=3*y_index+x_index;//目标图片的位置(3*3) if(post_img.post_img_list.indexOf('about:blank')!=target_index) //如果图片数组中没有src=about:blank这个占位置的li post_img.post_img_list.splice(target_index, 0, 'about:blank'); //添加src=about:blank index=target_index; //会触发很多次move,所以触发一次就改动一次 } }; }); document.onmouseup=function(e){ drag_holder=null; if(ori_src){ post_img.post_img_list.splice(index, 1); //删除src=about:blank post_img.post_img_list.splice(index, 0,ori_src); //添加原图片 } $('drag_proxy').style.display='none'; $('drag_proxy').innerHTML=''; drag_flag=false; };
以上代码实现了avalon js仿微博拖动图片排序的功能,本文写的不好还请见谅。