亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

avalon js實(shí)現(xiàn)仿google plus圖片多張拖動(dòng)排序

馬龍駒 / 2456人閱讀

摘要:支持多張圖片拖動(dòng)排序。解決方法是設(shè)置變量表示單元格在方向的在添加偏移的時(shí)候,增加判定條件。根源出現(xiàn)這個(gè)問(wèn)題的原因在于依次移動(dòng)目標(biāo)圖片到目標(biāo)位置,對(duì)多張目標(biāo)圖片,會(huì)有一個(gè)移動(dòng)先后的考量。

效果



拖動(dòng)+響應(yīng)式效果:http://v.youku.com/v_show/id_XMTM0MjQyMTI0OA==.html

要求

兩邊對(duì)齊布局,即圖片間間距一致,但左右兩邊的圖片與邊界的間距不一定等于圖片間間距,兼容ie7,8,firefox,chrome.

瀏覽器尺寸變化,在大于一定尺寸時(shí),每行自動(dòng)增加或減少圖片,自動(dòng)調(diào)整圖片間間距,以滿足兩邊對(duì)齊布局,這時(shí)每張圖片尺寸固定(這里是200*200px);而小于一定尺寸時(shí),每行圖片數(shù)量固定(這里最小列數(shù)是3),這時(shí)圖片總是等比例拉伸或縮放。

瀏覽器不同尺寸下,仍然可以拖動(dòng)排序。

圖片,拖動(dòng)代理里的圖片始終保持等比例且水平垂直居中。

拖動(dòng)到相應(yīng)位置時(shí),位置左右的圖片發(fā)生一定偏移。如果在最左邊或最右邊,則只是該行的第一張圖片或最后一張圖片發(fā)生偏移。

支持多張圖片拖動(dòng)排序。

實(shí)現(xiàn) 布局及css
    
inline-block+flex-box+text-align:justify

這里要兼容低版本瀏覽器,所以列表li布局用的是inline-block.而兩邊對(duì)齊布局
-低版本:inline-block+text-align:justify
-現(xiàn)代:inline-block+flex-box
具體參見(jiàn)本屌的模擬flexbox justify-content的space-between
這里沒(méi)有用flex-box的align-content:space-around是因?yàn)闊o(wú)法通過(guò)text-align:justify兼容低版本瀏覽器。
text-align:justify無(wú)法讓最左邊,最右邊文字自動(dòng)調(diào)整與box邊的間距。即使在外面box添加padidng,比如:

li{
    margin:0 1%;
    ...
}
#wrap{
    padding:0 1%;
}

看起來(lái)好像是最左邊,最右邊與box邊界的間距和li之間的間距一樣,都是2%了。實(shí)際上,外面box設(shè)置的padding是永遠(yuǎn)不會(huì)變的,而li之間的margin是它們之間間距的最小值。如果所有l(wèi)i之間的間距都是1%,這時(shí),一行上仍然有多余的空白,這些li會(huì)把空白均分了,這時(shí)它們之間的間距會(huì)大于1%.
具體的實(shí)現(xiàn)

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.后面可以看到單元格里面都是百分比,需要在外面限定最大尺寸。

圖片響應(yīng)式+水平垂直居中

具體參見(jiàn)本屌的css圖片響應(yīng)式+垂直水平居中
簡(jiǎn)單說(shuō),就是

添加一個(gè)“多余”的div,padding-top: 100%,使得整個(gè)box響應(yīng)式并且寬高比始終是1.

如果不考慮ie7,直接圖片

img{
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    position:absolute;
    margin: auto;
    padding: auto;
}

如果考慮ie7,

將上一點(diǎn)img樣式添加到這里的p,然后

p{
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    position:absolute;
    margin: auto;
    padding: auto;
}
img{
    display: inline-block;
    *display: inline;
    zoom:1;
    vertical-align: middle;
}
i{
    display: inline-block;
    *display: inline;
    zoom:1;
    vertical-align: middle;
    height:100%;
}

圖片響應(yīng)式

img{
    max-width: 100%;
    max-height: 100%;
}
選中圖片

google plus是按住ctrl,點(diǎn)擊圖片,完成多選,這里是點(diǎn)擊"方框"(這里的)。
點(diǎn)擊后,把當(dāng)前圖片的index傳給保存選中圖片index的數(shù)組(這里的selected_index)。如果該index不存在,則添加;已存在,則刪除。而"方框"此時(shí)根據(jù)數(shù)組中是否存在該index調(diào)整樣式。

    
  • ...
var photo_sort=avalon.define({
    selected_index:[],//選中圖片的index列表,
    ...
    select:function(i){
        var selected_index=photo_sort.selected_index,
        selected_photo=photo_sort.selected_photo,//存儲(chǔ)選中圖片的名字(id)
        photo=photo_sort.photo_list[i].$model.src;//這里以圖片的src為標(biāo)志
        if(selected_photo.indexOf(photo)==-1){//選中圖片的index列表不存在,添加
            selected_index.ensure(i);
            selected_photo.ensure(photo);
        }else{
            selected_index.remove(i);
            selected_photo.remove(photo);
        }
    }
});

圖片的選中狀態(tài)必須用selected_photo.indexOf(photo)==-1判斷,最后會(huì)解釋為什么這樣做.

mousedown

這里用了遮罩層,并在上面綁定mousedown事件。


...
        var photo_sort=avalon.define({
            $id:"photo_sort",
            photo_list:[],//圖片列表
            selected_photo:[],//選中圖片的id列表
            selected_index:[],//選中圖片的index列表
            drag_flag:false,
            sort_array:[],//范圍列表,
            cell_size:0,//每個(gè)單元格尺寸,這里寬高比為1
            target_index:-1,//最終目標(biāo)位置的index
            col_num:0,//列數(shù)
            x_index:-1,//當(dāng)前拖動(dòng)位置的x方向index
            ...
        });
start_drag:function(e,index){
    if(photo_sort.selected_index.size()){//有選中的圖片
        photo_sort.target_index=index;//避免用戶沒(méi)有拖動(dòng)圖片,但點(diǎn)擊了圖片,設(shè)置默認(rèn)目標(biāo)即當(dāng)前點(diǎn)擊圖片
        photo_sort.cell_size=this.clientWidth;
        var xx=e.clientX-photo_sort.cell_size/2,yy=e.clientY-photo_sort.cell_size/2;//點(diǎn)下圖片,設(shè)置代理位置以點(diǎn)擊點(diǎn)為中心
        $("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;//設(shè)置代理中選擇圖片的數(shù)量
        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;//將選中的圖片中最后一張作為代理對(duì)象的"封面"
            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

鼠標(biāo)點(diǎn)下,選中的圖片的遮罩出現(xiàn),這里是對(duì)其添加.photo_maskon

mousemove
drag_move:function(e){
    if(photo_sort.drag_flag){
        var xx=e.clientX,yy=e.clientY,offset=avalon($("wrap")).offset();
        var offsetX=xx-offset.left,offsetY=yy-offset.top;
        photo_sort.sort_array.push(offsetX);//把當(dāng)前鼠標(biāo)位置添加的范圍列表
        photo_sort.sort_array.sort(function(a,b){//對(duì)范圍列表排序
            return parseInt(a)-parseInt(b);//轉(zhuǎn)為數(shù)值類型,否則會(huì)出現(xiàn)"1234"<"333"
        });
        //從已排序的范圍列表中找出當(dāng)前鼠標(biāo)位置的index,即目標(biāo)位置水平方向的index
        var x_index=photo_sort.sort_array.indexOf(offsetX),y_index=Math.floor(offsetY/(photo_sort.cell_size+20)),
        size=photo_sort.photo_list.size();
        photo_sort.x_index=x_index;
        photo_sort.target_index=photo_sort.col_num*y_index+x_index;//目標(biāo)在所有圖片中的index
        if(photo_sort.target_index>size)//目標(biāo)位置越界
            photo_sort.target_index=size;
        photo_sort.sort_array.remove(offsetX);//移除當(dāng)前位置
        $("drag_proxy").style.top=avalon(window).scrollTop()+yy-photo_sort.cell_size/2+"px";
        $("drag_proxy").style.left=xx-photo_sort.cell_size/2+"px";
    }
    e.stopPropagation();
}

幾點(diǎn)說(shuō)明

關(guān)于當(dāng)前拖動(dòng)到的位置判定

圖中每個(gè)單元格的豎線,在水平方向把單元格分為兩邊。每個(gè)豎線把一行分為5部分,判斷的時(shí)候,看鼠標(biāo)當(dāng)前的e.clientX在5個(gè)部分里的哪一部分。

這里在判斷的時(shí)候用了排序。具體的,把每個(gè)豎線的x坐標(biāo)和當(dāng)前鼠標(biāo)位置的x坐標(biāo)保存到數(shù)組(這里的sort_array),排好序,然后indexOf看當(dāng)前鼠標(biāo)位置的x坐標(biāo)在數(shù)組中的位置,即可得到當(dāng)前拖動(dòng)的目標(biāo)位置。
如果不用排序的話,代碼會(huì)像這樣

var target;
if(x>50+50){
    if(x>3*100+3*100+50+50){//最后一部分
        target=4;
    }else{
        target=(x-50-50)/(50+100+50);
    }
}else
    target=0;

后面刪除當(dāng)前鼠標(biāo)位置的x坐標(biāo),空出位置,留給下一次mousemove事件的x坐標(biāo)。

關(guān)于當(dāng)前拖動(dòng)的目標(biāo)位置左右的圖片發(fā)生一定偏移,無(wú)非就是對(duì)目標(biāo)位置左右的圖片加上相應(yīng)的class.

.prev{
    right: 40px;
}
.next{
    left: 40px;
}
    
  • ...

這里需要注意,當(dāng)代理拖動(dòng)到最左邊或最右邊時(shí),由于布局是inline-block,此時(shí)目標(biāo)位置所在行的上一行(如果有)的最后一個(gè)單元格或下一行(如果有)的第一個(gè)單元格也會(huì)發(fā)生偏移。

解決方法是設(shè)置變量x_index,表示單元格在x方向的index.在添加偏移class的時(shí)候,增加判定條件。

  • ...
  • 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.photo_list=data;//更新數(shù)據(jù)
                    photo_sort.target_index=-1;//各種重置,初始化
                    photo_sort.sort_array=[];
                    photo_sort.col_num=0;
                    photo_sort.x_index=-1;
                    photo_sort.selected_photo.clear();
                    photo_sort.selected_index.clear();
                    $("drag_proxy").style.display="none";
                    photo_sort.drag_flag=false;
                    avalon.unbind(document,"mouseup");
                    if(isIE)
                        target.releaseCapture();
                }
            }

    這里主要就是對(duì)圖片列表的重排。

    目標(biāo)位置在選中圖片之前

    先把原始圖片保存在temp,然后把從目標(biāo)位置圖片到原始圖片前一位置的圖片,依次后移一個(gè)位置,最后把temp放到目標(biāo)位置。

    目標(biāo)位置在選中圖片之后

    和上面差不多,只不過(guò)這里是把從目標(biāo)位置圖片到原始圖片后一位置的圖片,依次前移一個(gè)位置。

    說(shuō)明

    不能像data[j]=data[j+1]這樣賦值,進(jìn)而更新視圖。因?yàn)閍valon不支持單個(gè)轉(zhuǎn)換,如果想更新,需要將整個(gè)子VM重新賦以一個(gè)新的對(duì)象。也就是photo_sort.photo_list=sortedData重新賦值,更新視圖。

    前面判斷圖片選中狀態(tài)為什么用selected_photo.indexOf(photo),而不是selected_index.indexOf(i),是因?yàn)楦乱晥D后,avalon不能自動(dòng)更新當(dāng)前圖片的index,也就是說(shuō)如果圖片一出來(lái)就是第一張,那它的index就永遠(yuǎn)是0,不會(huì)跟著它的位置改變。

    移動(dòng)順序問(wèn)題 重現(xiàn)

    這里為了方便查看順序,稍微修改了下html.

    可以看到,拖動(dòng)第2,3張圖片到第8,9張圖片之間,結(jié)果應(yīng)該是第8張圖片在第二行最左邊,然后向右依次是第2,3張圖片,最后是第9張圖片.而這里顯然不是想要的結(jié)果。

    根源

    出現(xiàn)這個(gè)問(wèn)題的原因在于
    依次移動(dòng)目標(biāo)圖片到目標(biāo)位置,對(duì)多張目標(biāo)圖片,會(huì)有一個(gè)移動(dòng)先后的考量。具體的,

    假設(shè)上圖要移動(dòng)的目標(biāo)圖片是第2,3張圖片,先移動(dòng)第2張圖片到目標(biāo)位置,這時(shí)第3張圖片會(huì)在第2張原來(lái)的位置上,這時(shí)成為第2張。但是前面,

            function onMouseUp(target){
                if(photo_sort.drag_flag){
                    for(var i=0,len=photo_sort.selected_index.size();i
    

    還是在依次遍歷目標(biāo)圖片,selected_index=[2,3];,下一個(gè)會(huì)遍歷現(xiàn)在的第3張圖片.

    解決

    解決方法很容易想到,就是先移動(dòng)第3張圖片,后移動(dòng)第2張圖片.
    上面的例子是目標(biāo)位置在選中圖片之后,當(dāng)然目標(biāo)位置在選中圖片之前也存在這個(gè)問(wèn)題。
    具體到代碼上

    function onMouseUp(target){
        if(photo_sort.drag_flag){
            photo_sort.selected_index.sort(function(a,b){//對(duì)范圍列表排序
                return parseInt(a)-parseInt(b);
            });
            var size=photo_sort.selected_index.size();
            var data=photo_sort.photo_list,target_index=photo_sort.target_index,
            pos_arr=photo_sort.selected_index.$model,
            result=data.slice(0,data.size());
            pos_arr.push(target_index);//pos_arr存放選中的目標(biāo)圖片+目標(biāo)位置,并排好序
            pos_arr.sort(function(a,b){//對(duì)范圍列表排序
                return parseInt(a)-parseInt(b);
            });
            var target_pos=pos_arr.indexOf(target_index),temp;
            //目標(biāo)位置在選中圖片之后,從目標(biāo)位置開(kāi)始,依次向前遍歷目標(biāo)圖片
            for(var i=target_pos-1;i>=0;i--){
                var item_index=pos_arr[i];
                temp=data[item_index].$model;
                for(var j=item_index;jtarget_index;j--)
                    data[j].$model=data[j-1].$model;
                data[target_index].$model=temp;
            }
            photo_sort.photo_list=data;//更新數(shù)據(jù)
            ...
        }
    }

    實(shí)際上就是以目標(biāo)位置為中心,向左右兩邊遍歷選中圖片。具體的

    選中圖片是第1,2,8,9張圖片,目標(biāo)位置是4.這時(shí)pos_arr=[1,2,4,8,9];,然后先遍歷4之前的選中圖片,2->1,然后是4之后的選中圖片,8->9.這樣就避免了移動(dòng)順序問(wèn)題。

    后記

    事實(shí)上,google plus在細(xì)節(jié)上還做了

    框選圖片

    如果有滾動(dòng)條,且拖動(dòng)位置快要超出當(dāng)前界面,滾動(dòng)條會(huì)自動(dòng)上移或下移。
    這兩個(gè)本屌就不做了,原理也是很簡(jiǎn)單的。

    下載

    文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/86002.html

    相關(guān)文章

    • avalon js實(shí)現(xiàn)仿google plus圖片多張拖動(dòng)排序

      摘要:支持多張圖片拖動(dòng)排序。解決方法是設(shè)置變量表示單元格在方向的在添加偏移的時(shí)候,增加判定條件。根源出現(xiàn)這個(gè)問(wèn)題的原因在于依次移動(dòng)目標(biāo)圖片到目標(biāo)位置,對(duì)多張目標(biāo)圖片,會(huì)有一個(gè)移動(dòng)先后的考量。 效果 showImg(https://segmentfault.com/img/bVp0ye);showImg(https://segmentfault.com/img/bVp0GA);拖動(dòng)+響應(yīng)式效果...

      pekonchan 評(píng)論0 收藏0
    • avalon js+css3實(shí)現(xiàn)roundabout 圖片輪播

      摘要:效果效果就像優(yōu)酷綜藝頻道頁(yè)面的圖片輪播。本屌之前做過(guò)這個(gè)參見(jiàn)仿優(yōu)酷頻道首頁(yè)的圖片切換效果不過(guò)用的是類似的庫(kù)做的。 roundabout效果 效果就像優(yōu)酷綜藝頻道頁(yè)面的圖片輪播。本屌之前做過(guò)這個(gè)roundabout,參見(jiàn)仿優(yōu)酷頻道首頁(yè)的圖片切換效果,不過(guò)用的是類似jquery的庫(kù)做的。盡管js代碼不到200行,但還是顯得有點(diǎn)復(fù)雜。于是乎,本屌盤(pán)算著可不可以用更少的代碼完成這個(gè)效果。順便說(shuō)...

      AlphaGooo 評(píng)論0 收藏0
    • avalon js+css3實(shí)現(xiàn)roundabout 圖片輪播

      摘要:效果效果就像優(yōu)酷綜藝頻道頁(yè)面的圖片輪播。本屌之前做過(guò)這個(gè)參見(jiàn)仿優(yōu)酷頻道首頁(yè)的圖片切換效果不過(guò)用的是類似的庫(kù)做的。 roundabout效果 效果就像優(yōu)酷綜藝頻道頁(yè)面的圖片輪播。本屌之前做過(guò)這個(gè)roundabout,參見(jiàn)仿優(yōu)酷頻道首頁(yè)的圖片切換效果,不過(guò)用的是類似jquery的庫(kù)做的。盡管js代碼不到200行,但還是顯得有點(diǎn)復(fù)雜。于是乎,本屌盤(pán)算著可不可以用更少的代碼完成這個(gè)效果。順便說(shuō)...

      Awbeci 評(píng)論0 收藏0
    • MV* 框架 與 DOM操作為主 JS庫(kù) 的案例對(duì)比

      摘要:中定義的處理業(yè)務(wù)邏輯與提供數(shù)據(jù)源,中的綁定負(fù)責(zé)渲染與響應(yīng)用戶點(diǎn)擊拖拽等行為,這樣就最大保證了視圖邏輯相分離。遠(yuǎn)離的世界,圍繞層控制器路由從后端放到前端,更加適合開(kāi)發(fā)。 最近分別使用 Zepto 和 Avalon框架寫(xiě)了個(gè) SPA項(xiàng)目,貼出來(lái)討論下 JS DOM操作為主 JS庫(kù) 與 MV* 框架的對(duì)比 案例(MV* 框架 與 DOM操作 JS庫(kù) 實(shí)例對(duì)比) 購(gòu)物車頁(yè)面 JS業(yè)務(wù)邏輯...

      springDevBird 評(píng)論0 收藏0

    發(fā)表評(píng)論

    0條評(píng)論

    最新活動(dòng)
    閱讀需要支付1元查看
    <