js瀑布流效果,寬度自適應,當滾動條滾動到必定的位置按須要加載更多圖片,php
把最新取得的圖片動態從中間散開鋪向應有的位置。html
一打開網頁,刷新的效果,當瀏覽器窗口寬度只能容納三張圖片的時候:算法
當瀏覽器窗口寬度能夠容納4張圖片的時候:json
(附件)數組
完整代碼:瀏覽器
<!-- Author: XiaoWen Create a file: 2016-12-06 14:56:55 Last modified: 2017-01-12 18:29:28 Start to work: Finish the work: Other information: --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>瀑布流</title> <script src="js/tween.js"></script> <script src="js/time_move.js"></script> <style> *{ margin: 0; padding: 0; } img{ border: none; width: 220px; vertical-align: bottom; border-radius:8px; box-shadow:0 0 8px #ccc; margin: 10px; padding: 10px; } #box{ position: relative; margin:20px auto 0; } .nv{ float: left; position: absolute; } </style> </head> <body> <div id="box"> <div class="nv"><img src="img/1.jpg"></div> <div class="nv"><img src="img/2.jpg"></div> <div class="nv"><img src="img/3.jpg"></div> <div class="nv"><img src="img/4.jpg"></div> <div class="nv"><img src="img/5.jpg"></div> <div class="nv"><img src="img/6.jpg"></div> <div class="nv"><img src="img/7.jpg"></div> <div class="nv"><img src="img/8.jpg"></div> <div class="nv"><img src="img/9.jpg"></div> <div class="nv"><img src="img/10.jpg"></div> <div class="nv"><img src="img/11.jpg"></div> <div class="nv"><img src="img/12.jpg"></div> <div class="nv"><img src="img/13.jpg"></div> <div class="nv"><img src="img/14.jpg"></div> <div class="nv"><img src="img/15.jpg"></div> <div class="nv"><img src="img/16.jpg"></div> <div class="nv"><img src="img/17.jpg"></div> <div class="nv"><img src="img/18.jpg"></div> <div class="nv"><img src="img/19.jpg"></div> <div class="nv"><img src="img/20.jpg"></div> </div> <script> window.onload=function(){ //////// 佈局 var yx=document.documentElement.clientWidth; var yz=document.documentElement.clientHeight; var xw=260; //圖片寬度 var oImgw=220; //圖片實際寬度 var num=Math.floor(yx/xw); //把可視區域的寬/圖片寬度=該有幾張圖 ,不足1張時向下取整 var amet=box.getElementsByTagName('div'); box.style.width=xw*num+'px'; var n=[]; //保存第一行第張圖片的高度 for(var i=0;i<amet.length;i++){ if(i<num){ //第一行 amet[i].style.top=0; amet[i].style.left=i*xw+'px'; //下標*寬度 n.push(amet[i].offsetHeight); //保存到數組 }else{ var iMin=Math.min.apply(false,n); //獲取全部圖片中的最小高度 m=getkey(n,iMin); //返回最小值的下標 amet[i].style.top=iMin+'px'; //下一張的top=高度最小的那張圖片的高度 amet[i].style.left=(m*xw)+'px'; //下一張的位置=高度最小的那張圖片的下標*他的寬度 n[m]+=amet[i].offsetHeight; //把新加上的圖片和以前最高度小的圖片,讓他們兩張的高度加起來 //用這樣的方式把最小值改變,不然每次取到的最小值都是同樣的 } } function getkey(a,b){ var ikey=0; for(var i=0;i<a.length;i++){ if(a[i]==b){ ikey=i; break } } return ikey } //////// 滾動加載 var bopen=true; //運行結束才進行請求 window.onscroll=function(){ var yy=document.documentElement.scrollTop||document.body.scrollTop; var olist=amet[amet.length-1]; //最後一張圖片 //當上次運行結束,並用當頁面滾動到最後一張圖高度的一半以上纔開始加載 if(bopen&&yy+yz>olist.offsetHeight/2+olist.offsetTop){ bopen=false; var xhr=new XMLHttpRequest();; xhr.open('get','waterfall.php',true); xhr.send(); xhr.onreadystatechange=function(){ if(xhr.readyState==4&&xhr.status==200){ var alist=JSON.parse(xhr.responseText); //獲取數據,轉換text爲json for(var i=0;i<alist.length;i++){ //獲取每一個對象 var iMin=Math.min.apply(false,n); //獲取最小數 var m=getkey(n,iMin); //最小數在數組中的下標 var oImg=document.createElement('img'); //建立img標籤 oImg.src=alist[i].url; oImg.style.height=oImgw/alist[i].width*alist[i].height; var op=document.createElement('div'); op.className='nv'; op.appendChild(oImg); //把 img 插入 div 中 box.appendChild(op); //把 div 插入 #box op.style.top=yz+yy+'px'; op.style.left=(yz-xw)/2+'px'; //////// 讓合併到一塊兒的對象對象從四周散開 timeMove(op,{ left:m*xw, top:iMin },Tween.Sine.easeOut,1000); n[m]+=op.offsetHeight; } bopen=true; //運動完成 } } } } } </script> </body> </html>
動做插件1app
js/Tween.jside
/*Tween動畫算法,來源於FLASH中的ActionScript Tween類 命名空間Tween 整理:CJ(掛個名) 參數說明 curTime:當前時間,即動畫已經進行了多長時間,開始時間爲0 start:開始值 dur:動畫持續多長時間 alter:總的變化量 Elastic中的參數 extent:正弦波的幅度 cycle:正弦波的週期 Back中的s,過沖量,此處數值越大,過沖越大 相對應的下面還分easeIn,easeOut,easeInOut方法 easeIn() 加速度運動,初始速度爲0 easeOut() 減速度運動,結束速度爲0 easeInOut() 先加速後減速,開始與結束時速度都爲0 具體參見ActionScript 3.0 語言和組件參考 */ var Tween = { Linear:function (start,alter,curTime,dur) {return start+curTime/dur*alter;},//最簡單的線性變化,即勻速運動 Quad:{//二次方緩動 easeIn:function (start,alter,curTime,dur) { return start+Math.pow(curTime/dur,2)*alter; }, easeOut:function (start,alter,curTime,dur) { var progress =curTime/dur; return start-(Math.pow(progress,2)-2*progress)*alter; }, easeInOut:function (start,alter,curTime,dur) { var progress =curTime/dur*2; return (progress<1?Math.pow(progress,2):-((--progress)*(progress-2) - 1))*alter/2+start; } }, Cubic:{//三次方緩動 easeIn:function (start,alter,curTime,dur) { return start+Math.pow(curTime/dur,3)*alter; }, easeOut:function (start,alter,curTime,dur) { var progress =curTime/dur; return start-(Math.pow(progress,3)-Math.pow(progress,2)+1)*alter; }, easeInOut:function (start,alter,curTime,dur) { var progress =curTime/dur*2; return (progress<1?Math.pow(progress,3):((progress-=2)*Math.pow(progress,2) + 2))*alter/2+start; } }, Quart:{//四次方緩動 easeIn:function (start,alter,curTime,dur) { return start+Math.pow(curTime/dur,4)*alter; }, easeOut:function (start,alter,curTime,dur) { var progress =curTime/dur; return start-(Math.pow(progress,4)-Math.pow(progress,3)-1)*alter; }, easeInOut:function (start,alter,curTime,dur) { var progress =curTime/dur*2; return (progress<1?Math.pow(progress,4):-((progress-=2)*Math.pow(progress,3) - 2))*alter/2+start; } }, Quint:{//五次方緩動 easeIn:function (start,alter,curTime,dur) { return start+Math.pow(curTime/dur,5)*alter; }, easeOut:function (start,alter,curTime,dur) { var progress =curTime/dur; return start-(Math.pow(progress,5)-Math.pow(progress,4)+1)*alter; }, easeInOut:function (start,alter,curTime,dur) { var progress =curTime/dur*2; return (progress<1?Math.pow(progress,5):((progress-=2)*Math.pow(progress,4) +2))*alter/2+start; } }, Sine :{//正弦曲線緩動 easeIn:function (start,alter,curTime,dur) { return start-(Math.cos(curTime/dur*Math.PI/2)-1)*alter; }, easeOut:function (start,alter,curTime,dur) { return start+Math.sin(curTime/dur*Math.PI/2)*alter; }, easeInOut:function (start,alter,curTime,dur) { return start-(Math.cos(curTime/dur*Math.PI/2)-1)*alter/2; } }, Expo: {//指數曲線緩動 easeIn:function (start,alter,curTime,dur) { return curTime?(start+alter*Math.pow(2,10*(curTime/dur-1))):start; }, easeOut:function (start,alter,curTime,dur) { return (curTime==dur)?(start+alter):(start-(Math.pow(2,-10*curTime/dur)+1)*alter); }, easeInOut:function (start,alter,curTime,dur) { if (!curTime) {return start;} if (curTime==dur) {return start+alter;} var progress =curTime/dur*2; if (progress < 1) { return alter/2*Math.pow(2,10* (progress-1))+start; } else { return alter/2* (-Math.pow(2, -10*--progress) + 2) +start; } } }, Circ :{//圓形曲線緩動 easeIn:function (start,alter,curTime,dur) { return start-alter*Math.sqrt(-Math.pow(curTime/dur,2)); }, easeOut:function (start,alter,curTime,dur) { return start+alter*Math.sqrt(1-Math.pow(curTime/dur-1)); }, easeInOut:function (start,alter,curTime,dur) { var progress =curTime/dur*2; return (progress<1?1-Math.sqrt(1-Math.pow(progress,2)):(Math.sqrt(1 - Math.pow(progress-2,2)) + 1))*alter/2+start; } }, Elastic: {//指數衰減的正弦曲線緩動 easeIn:function (start,alter,curTime,dur,extent,cycle) { if (!curTime) {return start;} if ((curTime==dur)==1) {return start+alter;} if (!cycle) {cycle=dur*0.3;} var s; if (!extent || extent< Math.abs(alter)) { extent=alter; s = cycle/4; } else {s=cycle/(Math.PI*2)*Math.asin(alter/extent);} return start-extent*Math.pow(2,10*(curTime/dur-1)) * Math.sin((curTime-dur-s)*(2*Math.PI)/cycle); }, easeOut:function (start,alter,curTime,dur,extent,cycle) { if (!curTime) {return start;} if (curTime==dur) {return start+alter;} if (!cycle) {cycle=dur*0.3;} var s; if (!extent || extent< Math.abs(alter)) { extent=alter; s =cycle/4; } else {s=cycle/(Math.PI*2)*Math.asin(alter/extent);} return start+alter+extent*Math.pow(2,-curTime/dur*10)*Math.sin((curTime-s)*(2*Math.PI)/cycle); }, easeInOut:function (start,alter,curTime,dur,extent,cycle) { if (!curTime) {return start;} if (curTime==dur) {return start+alter;} if (!cycle) {cycle=dur*0.45;} var s; if (!extent || extent< Math.abs(alter)) { extent=alter; s =cycle/4; } else {s=cycle/(Math.PI*2)*Math.asin(alter/extent);} var progress = curTime/dur*2; if (progress<1) { return start-0.5*extent*Math.pow(2,10*(progress-=1))*Math.sin( (progress*dur-s)*(2*Math.PI)/cycle); } else { return start+alter+0.5*extent*Math.pow(2,-10*(progress-=1)) * Math.sin( (progress*dur-s)*(2*Math.PI)/cycle); } } }, Back:{ easeIn: function (start,alter,curTime,dur,s){ if (typeof s == "undefined") {s = 1.70158;} return start+alter*(curTime/=dur)*curTime*((s+1)*curTime - s); }, easeOut: function (start,alter,curTime,dur,s) { if (typeof s == "undefined") {s = 1.70158;} return start+alter*((curTime=curTime/dur-1)*curTime*((s+1)*curTime + s) + 1); }, easeInOut: function (start,alter,curTime,dur,s){ if (typeof s == "undefined") {s = 1.70158;} if ((curTime/=dur/2) < 1) { return start+alter/2*(Math.pow(curTime,2)*(((s*=(1.525))+1)*curTime- s)); } return start+alter/2*((curTime-=2)*curTime*(((s*=(1.525))+1)*curTime+ s)+2); } }, Bounce:{ easeIn: function(start,alter,curTime,dur){ return start+alter-Tween.Bounce.easeOut(0,alter,dur-curTime,dur); }, easeOut: function(start,alter,curTime,dur){ if ((curTime/=dur) < (1/2.75)) { return alter*(7.5625*Math.pow(curTime,2))+start; } else if (curTime < (2/2.75)) { return alter*(7.5625*(curTime-=(1.5/2.75))*curTime + .75)+start; } else if (curTime< (2.5/2.75)) { return alter*(7.5625*(curTime-=(2.25/2.75))*curTime + .9375)+start; } else { return alter*(7.5625*(curTime-=(2.625/2.75))*curTime + .984375)+start; } }, easeInOut: function (start,alter,curTime,dur){ if (curTime< dur/2) { return Tween.Bounce.easeIn(0,alter,curTime*2,dur) *0.5+start; } else { return Tween.Bounce.easeOut(0,alter,curTime*2-dur,dur) *0.5 + alter*0.5 +start; } } } };
動做插件2佈局
js/time_move.js動畫
function timeMove(obj, target, type, times, fn) { clearInterval(obj.timer); var iStartTime = new Date().getTime(); var oCur = {}; for(var sAttr in target) { if(sAttr == 'opacity') { oCur[sAttr] = Math.round(parseFloat(getStyle(obj, 'opacity'))*100); } else { oCur[sAttr] = parseInt(getStyle(obj, sAttr)); } } obj.timer = setInterval(function () { var iChangeTime = new Date().getTime(); var iScale = 1 - Math.max((iStartTime + times - iChangeTime)/times, 0); for(var sAttr in target) { var iCur = type(oCur[sAttr], target[sAttr] - oCur[sAttr], times * iScale, times); if(sAttr == 'opacity') { obj.style.opacity = iCur/100; obj.style.filter = 'alpha(opacity:' + iCur + ')'; } else { obj.style[sAttr] = iCur + 'px'; } } if(iScale == 1) { clearInterval(obj.timer); fn && fn(); } }, 30); } // 獲取屬性樣式 function getStyle(obj, sAttr) { if(obj.currentStyle) { return obj.currentStyle[sAttr]; } else { return getComputedStyle(obj, false)[sAttr]; } }
php後臺文件
/waterfall.php
<?php $data = array( array( 'url' => 'img/1.jpg', 'width' => 595, 'height' => 914, ), array( 'url' => 'img/2.jpg', 'width' => 900, 'height' => 1318, ), array( 'url' => 'img/3.jpg', 'width' => 600, 'height' => 850, ), array( 'url' => 'img/4.jpg', 'width' => 512, 'height' => 726, ), array( 'url' => 'img/5.jpg', 'width' => 567, 'height' => 850, ), array( 'url' => 'img/6.jpg', 'width' => 361, 'height' => 510, ), array( 'url' => 'img/7.jpg', 'width' => 510, 'height' => 765, ), array( 'url' => 'img/8.jpg', 'width' => 400, 'height' => 600, ), array( 'url' => 'img/9.jpg', 'width' => 460, 'height' => 690, ), array( 'url' => 'img/10.jpg', 'width' => 683, 'height' => 1024, ), array( 'url' => 'img/11.jpg', 'width' => 960, 'height' => 1280, ), array( 'url' => 'img/12.jpg', 'width' => 427, 'height' => 640, ), array( 'url' => 'img/13.jpg', 'width' => 607, 'height' => 914, ), array( 'url' => 'img/14.jpg', 'width' => 402, 'height' => 600, ), array( 'url' => 'img/15.jpg', 'width' => 720, 'height' => 480, ), array( 'url' => 'img/16.jpg', 'width' => 658, 'height' => 989, ), array( 'url' => 'img/17.jpg', 'width' => 641, 'height' => 960, ), array( 'url' => 'img/18.jpg', 'width' => 658, 'height' => 987, ), array( 'url' => 'img/19.jpg', 'width' => 600, 'height' => 900, ), array( 'url' => 'img/20.jpg', 'width' => 683, 'height' => 993, ), ); echo json_encode($data);