首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

avalonjs实现仿googleplus图片多张拖动排序附源码下载_javascript技巧

2020-11-27 来源:华佗小知识
源码下载:http://xiazai.jb51.net/201509/yuanma/drag_sort1(jb51.net).rar

效果展示如下:

google plus


拖动+响应式效果:

要求

1. 两边对齐布局,即图片间间距一致,但左右两边的图片与边界的间距不一定等于图片间间距,兼容ie7,8,firefox,chrome.
2. 浏览器尺寸变化,在大于一定尺寸时,每行自动增加或减少图片,自动调整图片间间距,以满足两边对齐布局,这时每张图片尺寸固定(这里是200*200px);而小于一定尺寸时,每行图片数量固定(这里最小列数是3),这时图片总是等比例拉伸或缩放。
3. 浏览器不同尺寸下,仍然可以拖动排序。
4. 图片,拖动代理里的图片始终保持等比例且水平垂直居中。
5. 拖动到相应位置时,位置左右的图片发生一定偏移。如果在最左边或最右边,则只是该行的第一张图片或最后一张图片发生偏移。
6. 支持多张图片拖动排序。

实现

布局及css

 
 
 
  • 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,点击图片,完成多选,这里是点击"方框"(这里的``)。
    点击后,把当前图片的index传给保存选中图片index的数组(这里的selected_index)。如果该index不存在,则添加;已存在,则删除。而"方框"此时根据数组中是否存在该index调整样式。

    
    
    

    mousedown

    这里用了遮罩层,并在上面绑定mousedown事件。

    
    
    

    鼠标点下,选中的图片的遮罩出现,这里是对其添加`.photo_maskon`

    
    
    

    mousemove

    
    
    

    几点说明
    - 关于当前拖动到的位置判定

    图中每个单元格的竖线,在水平方向把单元格分为两边。每个竖线把一行分为5部分,判断的时候,看鼠标当前的`e.clientX`在5个部分里的哪一部分。

    - 这里在判断的时候用了排序。具体的,把每个竖线的x坐标和当前鼠标位置的x坐标保存到数组(这里的`sort_array`),排好序,然后`indexOf`看当前鼠标位置的x坐标在数组中的位置,即可得到当前拖动的目标位置。

    如果不用排序的话,代码会像这样

    
    
    

    - 后面删除当前鼠标位置的x坐标,空出位置,留给下一次mousemove事件的x坐标。
    - 关于当前拖动的目标位置左右的图片发生一定偏移,无非就是对目标位置左右的图片加上相应的class.

    
    
    

    这里需要注意,当代理拖动到最左边或最右边时,由于布局是`inline-block`,此时目标位置所在行的上一行(如果有)的最后一个单元格或下一行(如果有)的第一个单元格也会发生偏移。

    解决方法是设置变量`x_index`,表示单元格在x方向的index.在添加偏移class的时候,增加判定条件

  • ...
  • mouseup

    function onMouseUp(target){
     if(photo_sort.drag_flag){
     for(var i=0,len=photo_sort.selected_index.size();itarget_index;j--)
     data[j].src=data[j-1].src;
     data[target_index].src=temp;
     }
     }
     photo_sort.target_index=-1;//各种重置,初始化
     photo_sort.sort_array=[];
     photo_sort.col_num=0;
     photo_sort.x_index=-1;
     photo_sort.selected_index=[];
     $('drag_proxy').style.display='none';
     photo_sort.drag_flag=false;
     avalon.unbind(document,'mouseup');
     if(isIE)
     target.releaseCapture();
     }
     }
    

    这里主要就是对图片列表的重排。
    - 目标位置在选中图片之前

    先把原始图片保存在`temp`,然后把从目标位置图片到原始图片前一位置的图片,依次后移一个位置,最后把`temp`放到目标位置。
    - 目标位置在选中图片之后

    和上面差不多,只不过这里是把从目标位置图片到原始图片后一位置的图片,依次前移一个位置。

    注意

    不能像`data[j]=data[j+1]`这样赋值,因为avalon不支持单个转换,如果想更新,需要将整个子VM重新赋以一个新的对象。也就是定义一个arr,然后从头开始向里面添加model,最后`photo_sort.photo_list.clear()`删除所有图片,`photo_sort.photo_list=arr`重新赋值,更新视图。

    后记

    事实上,google plus在细节上还做了
    - 框选图片
    - 如果有滚动条,且拖动位置快要超出当前界面,滚动条会自动上移或下移。
    这两个本屌就不做了,原理也是很简单的。

    显示全文