源码下载:(jb51.net).rar
效果展示如下:
google plus
拖动+响应式效果:
要求
1. 两边对齐布局,即图片间间距一致,但左右两边的图片与边界的间距不一定等于图片间间距,兼容ie7,8,firefox,chrome.
2. 浏览器尺寸变化,在大于一定尺寸时,每行自动增加或减少图片,自动调整图片间间距,以满足两边对齐布局,这时每张图片尺寸固定(这里是200*200px);而小于一定尺寸时,每行图片数量固定(这里最小列数是3),这时图片总是等比例拉伸或缩放。
3. 浏览器不同尺寸下,仍然可以拖动排序。
4. 图片,拖动代理里的图片始终保持等比例且水平垂直居中。
5. 拖动到相应位置时,位置左右的图片发生一定偏移。如果在最左边或最右边,则只是该行的第一张图片或最后一张图片发生偏移。
6. 支持多张图片拖动排序。
实现
布局及css
<div> <ul> <li> <a href="javascript:;"></a> <div></div> <div> <div></div> <p><img><i></i></p> </div> </li> <li></li> </ul> </div> inline-block+flex-box+text-align:justify
这里要兼容低版本浏览器,所以列表li布局用的是inline-block.而两边对齐布局
-低版本:inline-block+`text-align:justify`
-现代:inline-block+`flex-box`
具体参见本屌的模拟flexbox justify-content的space-between
这里没有用flex-box的`align-content:space-around`是因为无法通过`text-align:justify`兼容低版本浏览器。
`text-align:justify`无法让最左边,最右边文字自动调整与box边的间距。即使在外面box添加padidng,比如:
li{ margin:0 1%; ... } #wrap{ padding:0 1%; }
看起来好像是最左边,最右边与box边界的间距和li之间的间距一样,都是2%了。实际上,外面box设置的padding是永远不会变的,而li之间的margin是它们之间间距的最小值。如果所有li之间的间距都是1%,这时,一行上仍然有多余的空白,这些li会把空白均分了,这时它们之间的间距会大于1%.
具体的实现
li{ list-style-type: none; display:inline-block; *display: inline; zoom:1; max-width: 200px; max-height: 200px; width: 28%; border:1px solid red; position: relative; overflow: hidden; margin:10px 2%; } li[class='justify_fix']{ border:none; } .justify { display: flex; align-items: flex-start; flex-flow: row wrap; justify-content: space-between; text-align: justify; text-justify: inter-ideograph; *zoom: 1; -moz-text-align-last: justify; -webkit-text-align-last: justify; text-align-last: justify; } @media (-webkit-min-device-pixel-ratio:0) { .justify:after { content: ""; display: inline-block; width: 100%; } }
这里要加上`max-width`,`max-height`.后面可以看到单元格里面都是百分比,需要在外面限定最大尺寸。
图片响应式+水平垂直居中
具体参见本屌的css图片响应式+垂直水平居中
选中图片
google plus是按住ctrl,点击图片,完成多选,这里是点击"方框"(这里的`<a></a>`)。
点击后,把当前图片的index传给保存选中图片index的数组(这里的selected_index)。如果该index不存在,则添加;已存在,则删除。而"方框"此时根据数组中是否存在该index调整样式。
<div ms-controller='photo_sort'> <ul> <li ms-repeat='photo_list'> <a href="javascript:;" ms-class-selected_icon='selected_index.indexOf($index)>-1' ms-click='select($index)'></a> ... </li> <li></li> </ul> </div> var photo_sort=avalon.define({ selected_index:[],//选中图片的index列表, ... select:function(i){ var selected_index=photo_sort.selected_index; if(selected_index.indexOf(i)==-1)//选中图片的index列表不存在,添加 photo_sort.selected_index.ensure(i); else photo_sort.selected_index.remove(i); } });
mousedown
这里用了遮罩层,并在上面绑定mousedown事件。
<a href="javascript:;" ms-class-selected_icon='selected_index.indexOf($index)>-1' ms-click='select($index)'></a> <div ms-mousedown='start_drag($event,$index)'></div> var photo_sort=avalon.define({ $id:'photo_sort', photo_list:[],//图片列表 selected_index:[],//选中图片的index列表 drag_flag:false, sort_array:[],//范围列表, cell_size:0,//每个单元格尺寸,这里宽高比为1 target_index:-1,//最终目标位置的index col_num:0,//列数 x_index:-1,//当前拖动位置的x方向index ... }); start_drag:function(e,index){ if(photo_sort.selected_index.size()){//有选中的图片 photo_sort.target_index=index;//避免用户没有拖动图片,但点击了图片,设置默认目标即当前点击图片 photo_sort.cell_size=this.clientWidth; var xx=e.clientX-photo_sort.cell_size/2,yy=e.clientY-photo_sort.cell_size/2;//点下图片,设置代理位置以点击点为中心 $('drag_proxy').style.top=yy+avalon(window).scrollTop()+'px'; $('drag_proxy').style.left=xx+'px'; $('drag_proxy').style.width=photo_sort.cell_size+'px'; $('drag_proxy').style.height=photo_sort.cell_size+'px'; drag_proxy.select_num=photo_sort.selected_index.length;//设置代理中选择图片的数量 if(drag_proxy.select_num>0){ var drag_img=photo_sort.photo_list[photo_sort.selected_index[drag_proxy.select_num-1]]; drag_proxy.src=drag_img.src;//将选中的图片中最后一张作为代理对象的"封面" photo_sort.drag_flag=true; $('drag_proxy').style.display='block'; } //cell_gap:图片间间距,first_gap:第一张图片和外部div间间距 var wrap_width=avalon($('wrap')).width(),wrap_offset=$('wrap').offsetLeft,first_left=$('wrap_photo0').offsetLeft, second_left=$('wrap_photo1').offsetLeft,first_gap=first_left-wrap_offset,cell_gap=second_left-first_left; photo_sort.col_num=Math.round((wrap_width-2*first_gap+(cell_gap-photo_sort.cell_size))/cell_gap); for(var i=0;i<photo_sort.col_num;i++)//把一行图片里的每张图片中心坐标x方向的值作为分割点,添加到范围列表 photo_sort.sort_array.push(first_gap+cell_gap*i+photo_sort.cell_size/2); var target=this.parentNode; avalon.bind(document,'mouseup',function(e){ onMouseUp(target); }); if(isIE) target.setCapture();//让ie下拖动顺滑 e.stopPropagation(); e.preventDefault(); } }
鼠标点下,选中的图片的遮罩出现,这里是对其添加`.photo_maskon`
<div ms-class-photo_maskon='drag_flag&&selected_index.indexOf($index)>-1' ms-mousedown='start_drag($event,$index)'></div>
mousemove