摘要:支持多張圖片拖動排序。解決方法是設置變量表示單元格在方向的在添加偏移的時候,增加判定條件。根源出現這個問題的原因在于依次移動目標圖片到目標位置,對多張目標圖片,會有一個移動先后的考量。
效果
拖動+響應式效果:http://v.youku.com/v_show/id_XMTM0MjQyMTI0OA==.html
兩邊對齊布局,即圖片間間距一致,但左右兩邊的圖片與邊界的間距不一定等于圖片間間距,兼容ie7,8,firefox,chrome.
瀏覽器尺寸變化,在大于一定尺寸時,每行自動增加或減少圖片,自動調整圖片間間距,以滿足兩邊對齊布局,這時每張圖片尺寸固定(這里是200*200px);而小于一定尺寸時,每行圖片數量固定(這里最小列數是3),這時圖片總是等比例拉伸或縮放。
瀏覽器不同尺寸下,仍然可以拖動排序。
圖片,拖動代理里的圖片始終保持等比例且水平垂直居中。
拖動到相應位置時,位置左右的圖片發生一定偏移。如果在最左邊或最右邊,則只是該行的第一張圖片或最后一張圖片發生偏移。
支持多張圖片拖動排序。
實現 布局及cssinline-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圖片響應式+垂直水平居中
簡單說,就是
添加一個“多余”的div,padding-top: 100%,使得整個box響應式并且寬高比始終是1.
如果不考慮ie7,直接圖片
img{ top: 0; bottom: 0; left: 0; right: 0; position:absolute; margin: auto; padding: auto; }
如果考慮ie7,
將上一點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%; }
圖片響應式
img{ max-width: 100%; max-height: 100%; }選中圖片
google plus是按住ctrl,點擊圖片,完成多選,這里是點擊"方框"(這里的)。
點擊后,把當前圖片的index傳給保存選中圖片index的數組(這里的selected_index)。如果該index不存在,則添加;已存在,則刪除。而"方框"此時根據數組中是否存在該index調整樣式。
var photo_sort=avalon.define({ selected_index:[],//選中圖片的index列表, ... select:function(i){ var selected_index=photo_sort.selected_index, selected_photo=photo_sort.selected_photo,//存儲選中圖片的名字(id) photo=photo_sort.photo_list[i].$model.src;//這里以圖片的src為標志 if(selected_photo.indexOf(photo)==-1){//選中圖片的index列表不存在,添加 selected_index.ensure(i); selected_photo.ensure(photo); }else{ selected_index.remove(i); selected_photo.remove(photo); } } });
圖片的選中狀態必須用selected_photo.indexOf(photo)==-1判斷,最后會解釋為什么這樣做.
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,//每個單元格尺寸,這里寬高比為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;imouseup鼠標點下,選中的圖片的遮罩出現,這里是對其添加.photo_maskon
mousemovedrag_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);//把當前鼠標位置添加的范圍列表 photo_sort.sort_array.sort(function(a,b){//對范圍列表排序 return parseInt(a)-parseInt(b);//轉為數值類型,否則會出現"1234"<"333" }); //從已排序的范圍列表中找出當前鼠標位置的index,即目標位置水平方向的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;//目標在所有圖片中的index if(photo_sort.target_index>size)//目標位置越界 photo_sort.target_index=size; photo_sort.sort_array.remove(offsetX);//移除當前位置 $("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(); }幾點說明
關于當前拖動到的位置判定
圖中每個單元格的豎線,在水平方向把單元格分為兩邊。每個豎線把一行分為5部分,判斷的時候,看鼠標當前的e.clientX在5個部分里的哪一部分。
這里在判斷的時候用了排序。具體的,把每個豎線的x坐標和當前鼠標位置的x坐標保存到數組(這里的sort_array),排好序,然后indexOf看當前鼠標位置的x坐標在數組中的位置,即可得到當前拖動的目標位置。
如果不用排序的話,代碼會像這樣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;后面刪除當前鼠標位置的x坐標,空出位置,留給下一次mousemove事件的x坐標。
關于當前拖動的目標位置左右的圖片發生一定偏移,無非就是對目標位置左右的圖片加上相應的class.
.prev{ right: 40px; } .next{ left: 40px; }
- ...
這里需要注意,當代理拖動到最左邊或最右邊時,由于布局是inline-block,此時目標位置所在行的上一行(如果有)的最后一個單元格或下一行(如果有)的第一個單元格也會發生偏移。
解決方法是設置變量x_index,表示單元格在x方向的index.在添加偏移class的時候,增加判定條件。...
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;//更新數據 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(); } }
這里主要就是對圖片列表的重排。
目標位置在選中圖片之前
先把原始圖片保存在temp,然后把從目標位置圖片到原始圖片前一位置的圖片,依次后移一個位置,最后把temp放到目標位置。
目標位置在選中圖片之后
和上面差不多,只不過這里是把從目標位置圖片到原始圖片后一位置的圖片,依次前移一個位置。
說明
不能像data[j]=data[j+1]這樣賦值,進而更新視圖。因為avalon不支持單個轉換,如果想更新,需要將整個子VM重新賦以一個新的對象。也就是photo_sort.photo_list=sortedData重新賦值,更新視圖。
前面判斷圖片選中狀態為什么用selected_photo.indexOf(photo),而不是selected_index.indexOf(i),是因為更新視圖后,avalon不能自動更新當前圖片的index,也就是說如果圖片一出來就是第一張,那它的index就永遠是0,不會跟著它的位置改變。
移動順序問題 重現這里為了方便查看順序,稍微修改了下html.
可以看到,拖動第2,3張圖片到第8,9張圖片之間,結果應該是第8張圖片在第二行最左邊,然后向右依次是第2,3張圖片,最后是第9張圖片.而這里顯然不是想要的結果。
出現這個問題的原因在于
依次移動目標圖片到目標位置,對多張目標圖片,會有一個移動先后的考量。具體的,
假設上圖要移動的目標圖片是第2,3張圖片,先移動第2張圖片到目標位置,這時第3張圖片會在第2張原來的位置上,這時成為第2張。但是前面,
function onMouseUp(target){ if(photo_sort.drag_flag){ for(var i=0,len=photo_sort.selected_index.size();i還是在依次遍歷目標圖片,selected_index=[2,3];,下一個會遍歷現在的第3張圖片.
解決解決方法很容易想到,就是先移動第3張圖片,后移動第2張圖片.
上面的例子是目標位置在選中圖片之后,當然目標位置在選中圖片之前也存在這個問題。
具體到代碼上function onMouseUp(target){ if(photo_sort.drag_flag){ photo_sort.selected_index.sort(function(a,b){//對范圍列表排序 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存放選中的目標圖片+目標位置,并排好序 pos_arr.sort(function(a,b){//對范圍列表排序 return parseInt(a)-parseInt(b); }); var target_pos=pos_arr.indexOf(target_index),temp; //目標位置在選中圖片之后,從目標位置開始,依次向前遍歷目標圖片 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;//更新數據 ... } } 實際上就是以目標位置為中心,向左右兩邊遍歷選中圖片。具體的
后記
選中圖片是第1,2,8,9張圖片,目標位置是4.這時pos_arr=[1,2,4,8,9];,然后先遍歷4之前的選中圖片,2->1,然后是4之后的選中圖片,8->9.這樣就避免了移動順序問題。事實上,google plus在細節上還做了
框選圖片
如果有滾動條,且拖動位置快要超出當前界面,滾動條會自動上移或下移。
這兩個本屌就不做了,原理也是很簡單的。下載
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/111159.html
摘要:支持多張圖片拖動排序。解決方法是設置變量表示單元格在方向的在添加偏移的時候,增加判定條件。根源出現這個問題的原因在于依次移動目標圖片到目標位置,對多張目標圖片,會有一個移動先后的考量。 效果 showImg(https://segmentfault.com/img/bVp0ye);showImg(https://segmentfault.com/img/bVp0GA);拖動+響應式效果...
摘要:效果效果就像優酷綜藝頻道頁面的圖片輪播。本屌之前做過這個參見仿優酷頻道首頁的圖片切換效果不過用的是類似的庫做的。 roundabout效果 效果就像優酷綜藝頻道頁面的圖片輪播。本屌之前做過這個roundabout,參見仿優酷頻道首頁的圖片切換效果,不過用的是類似jquery的庫做的。盡管js代碼不到200行,但還是顯得有點復雜。于是乎,本屌盤算著可不可以用更少的代碼完成這個效果。順便說...
摘要:效果效果就像優酷綜藝頻道頁面的圖片輪播。本屌之前做過這個參見仿優酷頻道首頁的圖片切換效果不過用的是類似的庫做的。 roundabout效果 效果就像優酷綜藝頻道頁面的圖片輪播。本屌之前做過這個roundabout,參見仿優酷頻道首頁的圖片切換效果,不過用的是類似jquery的庫做的。盡管js代碼不到200行,但還是顯得有點復雜。于是乎,本屌盤算著可不可以用更少的代碼完成這個效果。順便說...
摘要:中定義的處理業務邏輯與提供數據源,中的綁定負責渲染與響應用戶點擊拖拽等行為,這樣就最大保證了視圖邏輯相分離。遠離的世界,圍繞層控制器路由從后端放到前端,更加適合開發。 最近分別使用 Zepto 和 Avalon框架寫了個 SPA項目,貼出來討論下 JS DOM操作為主 JS庫 與 MV* 框架的對比 案例(MV* 框架 與 DOM操作 JS庫 實例對比) 購物車頁面 JS業務邏輯...
閱讀 3338·2023-04-26 03:05
閱讀 1458·2019-08-30 13:09
閱讀 1906·2019-08-30 13:05
閱讀 885·2019-08-29 12:42
閱讀 1385·2019-08-28 18:18
閱讀 3446·2019-08-28 18:09
閱讀 512·2019-08-28 18:00
閱讀 1712·2019-08-26 12:10