Home > Article > Web Front-end > avalon js implements imitating Weibo drag image sorting_javascript skills
The following is a very detailed explanation of how to drag and adjust the order of imitation Weibo pictures. There are definitely deficiencies in the article. Welcome to criticize and correct. Not much nonsense, let’s look at the specific content.
Click here to enterSource code download
What is drag-and-drop image sorting?
Just like Weibo, users are allowed to adjust the order of several pictures by dragging them after uploading.
You can see that Weibo has fixed the size of each picture here. If you are a little stricter, you need to be like the previous article, with several responsive div containers of equal height and width outside. , which contains proportionally scaled responsive images.
The following are the requirements.
1. Of course, the image must be draggable first.
2. Move the image out of its original position, drag it to the target position, and before completing the dragging without releasing the mouse, you need to set a placeholder at the target position to allow the user to preview the effect after the drag is completed.
3. Responsive. After the size is changed, the above requirements can still be completed.
4. Compatible with as many browsers as possible. In fact, I wrote the previous article to pave the way for this one, so this one is also compatible with IE7.
Final effect
chrome
ie8
ie7
First is dragging.
The proxy used here means that there is an extra div in the original layout, and the actual dragged object is this div. Specifically,
<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>
Bind mousedown to each cell. When start_drag is triggered, put the img in the cell into the proxy9a1189f368bbe10179643504d09abef916b28748ea4df4d9c2150843fecfba68. At the same time, get the size of the image and write it down. The current mouse click position, and the click position is used as the center point of the proxy div rectangle (picture), the proxy is displayed, and the clicked picture is hidden.
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(); }
Note a few points:
1.drag_sort.cell_size records the size of the current cell. The aspect ratio here is 1:1. Because the layout is responsive, it needs to be recorded. You can see how to use this later.
2. The target of the event needs to determine whether it is triggered by the img tag, because the click position may be the blank area between the cell and the picture.
3.ori_src is used to save the picture of the current cell, because the cell at the original position of the picture will be deleted when mousemove later.
4.drag_sort.target_index records the index of the current cell, and will later compare this index with the index of the cell to which the agent moves.
5.drag_flag indicates whether mousemove is allowed.
6. For ie, target.setCapture(); must be used, otherwise
You can see that the browser's default behavior will be executed when dragging.
7.event.preventDefault(); must also be added, otherwise the browser's default behavior will occur. For example, when Firefox drags an image, it will open a new tab and display the image.
Then comes mousemove, which is bound to the ul tag. Events like mousemove and mouseup are usually bound to several common parent elements that need to be triggered, thus reducing the number of objects to which the event is bound.
Specific
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(); }
A few notes
1.drag_flag ensures that mousedown must be triggered before mousemove can be triggered.
2.drag_sort.container is the root element of the entire layout, here is 32dd1458d427f4db45ae1fb40a9399c016b28748ea4df4d9c2150843fecfba68.
#wrap{ position: relative; max-width: 620px; font-size: 0; } #drag_proxy{ position: absolute; border:1px solid #009be3; z-index: 100; display: none; }
When calculating later, you need to subtract the left and top of the root element.
3. The vertical scroll bar of the avalon(window).scrollTop() browser should also be considered when calculating.
4. The size of each cell is always the same, so the position where the cursor moves directly is divided by the number of rows and columns, and rounded to get the index of the target cell.
5.move_to!=drag_sort.target_index The cell that the current cursor is moved to is not the cell where the picture originally resides. Delete the cell at the original location of the picture and insert a placeholder cell in the target cell. At this time, the dragged The image has not been placed in the target cell yet, and the index of the initial cell is finally updated.
Finally, mouseup
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仿微博拖动图片排序的功能,本文写的不好还请见谅。