javascript實(shí)現(xiàn)瀑布流加載圖片原理
講一下大概的原理吧
功能描述:
- 根據(jù)不同菜單的屬性值分別加載不同的數(shù)據(jù)
- 下拉滾動(dòng)條到一定位置預(yù)加載圖片,滾動(dòng)條拉到最底下的時(shí)候渲染html;
- 鼠標(biāo)移到菜單,切換各個(gè)圖片列表;
- 鼠標(biāo)移到圖片列表上,顯示詳細(xì)信息;
技術(shù)實(shí)現(xiàn)方案:
先梳理一下從加載到顯示的流程:
1. 加載數(shù)據(jù)
2. 拼接HTML寫入到頁(yè)面
3. 檢查剛剛寫入的HTML中的img是否全部加載完成,如果是,進(jìn)入5、否則進(jìn)入4
4. 等待圖片加載完成
5. 計(jì)算每個(gè)元素的位置
一開(kāi)始的時(shí)候最頭疼的是如何定位的問(wèn)題,后來(lái)經(jīng)過(guò)朋友指導(dǎo)終于解決:計(jì)算總共有多少列圖片并且把每一列的高度都放到一個(gè)數(shù)組里面。每當(dāng)一張圖片加載完成的時(shí)候就查找這個(gè)數(shù)組里面最小的值,并且定位當(dāng)前圖片的top設(shè)置為這個(gè)值,完成后把這個(gè)圖片的高度加上數(shù)組里面的最小值并且返回到數(shù)組里面,依次類推。
PS:因?yàn)檫@個(gè)功能代碼太多,只能作基本的簡(jiǎn)單分解代碼了:
// 創(chuàng)建用于記錄每列高度的數(shù)組
_getLowestCol: function() {
t._cols = new Array(5),min = 0;
// 初始化為0
for (var i = 0; i < t._cols.length; i++) {
if (cols[i] < cols[min]) {
min = i;
}
return min;
}
},
_reposition: function() {
t._grids.each(function(i, grid) {
//先顯示出來(lái)
grid = $(grid).show();
var height = grid.outerHeight(), min = t._getLowestCol();
// 定位
grid.animate({
left: (t._colWidth + t._colSpacing) * min,
top: t._cols[min],
opacity: 1
},1000);
// 記錄高度
t._cols[min] += height;
});
}
其次開(kāi)發(fā)過(guò)程中遇到的難題是:因?yàn)槿缟蠄D所示,鼠標(biāo)移動(dòng)到菜單欄需要切換圖片列表,并且分別需要用瀑布流加載不同類型的數(shù)據(jù)。所以要處理在切換頁(yè)面的時(shí)候如何才能做到每個(gè)頁(yè)面只執(zhí)行一次代碼請(qǐng)求接口,而不需要每一次切換都重新請(qǐng)求數(shù)據(jù)接口,僅僅執(zhí)行切換顯示圖片列表的操作就可以了。
考慮到每一個(gè)菜單都有一個(gè)自定義屬性,所以這個(gè)問(wèn)題輕易地解決了:建立一個(gè)對(duì)象來(lái)記錄當(dāng)前菜單是否已經(jīng)執(zhí)行過(guò)代碼,如果沒(méi)有就執(zhí)行請(qǐng)求數(shù)據(jù) ?!?/p>
var isLoad = {};//是否載入過(guò)
labelType.mouseover(function() {
var i = $(this).index();
var api = _this.attr('api');//接口標(biāo)識(shí)
if(! isLoad[ api ]){
isLoad[ api ] = i;
loadData(wrapper, api);
}
});
以下為全部代碼:
html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<style type="text/css">
*{margin:0;padding:0;}
ul,li{ list-style-type:none;}
li img{width:100%;list-style:none;}
</style>
</head>
<body>
<div class="photo_box">
<ul id="container" style="border:1px solid #000;width:80%;height:600px;overflow:hidden;margin:0 auto;position: relative;">
</ul>
<div id="loading" class="loading" style="text-align: center;margin-top: 20px;font-size: 1.2em;">加載中...</div>
<div id="more" class="more"style="text-align: center;margin-top: 20px;font-size: 1.2em;"><input type="button" value="更 多" id="clear" /></div>
</div>
<script type="text/javascript" src="../../lib/seajs/sea.js"></script>
<script type="text/javascript" src="../../lib/base/1.0.x/base.js"></script>
<script type="text/javascript">
seajs.use(['lib/jquery/1.11.x/index.js', '_example/waterFall_1.1/waterfall.js'], function($, waterFall) {
waterFall.init({
container: $('#container'),
dataURL: 'http://www.woxiu.com/index.php?action=Index/Main&do=ApiZhuboGrade',
dataType: 'jsonp',
template: '<% for (var i = 0; i < data.length; i++) { %>' +
'<li style="display: none;">' +
'<img src=" <%-data[i].room_img%> ">' +
'</li>' +
'<% } %>',
colWidth: 200,
colSpacing: 10,
rowSpacing: 15,
page: 1,
pageEnd: 8,
});
// 限制同時(shí)展示的頁(yè)數(shù)
var loadCounter = 1;
function pageNum(){
if (loadCounter >= 3) {
$('#more').show();
$('#loading').hide();
return true;
} else {
loadCounter++;
$('#more').hide();
$('#loading').show();
}
return false;
}
$('#clear').click(function() {
loadCounter = 1;
waterFall._loadNext();
});
});
</script>
</body>
js:
/**
* 瀑布流布局組件類
* @param {Object} options 組件設(shè)置
* @param {NodeList} options.container 瀑布流容器
* @param {String} options.dataURL 數(shù)據(jù)地址
* @param {String} [options.dataType='jsonp'] 數(shù)據(jù)類型,json或jsonp
* @param {String} options.template 模板編輯
* @param {Number} [options.colWidth] 圖片大小。
* @param {Number} [options.colSpacing] 列間隔。
* @param {Number} [options.rowSpacing] 行間隔。
* @param {Number} [options.page=1] 數(shù)據(jù)開(kāi)始頁(yè)碼
* @param {Number} [options.pageEnd] 數(shù)據(jù)末尾頁(yè)碼
* @pageNum() 函數(shù),如果不需要現(xiàn)在加載也是,需要把函數(shù)里面的判斷去掉。
從加載到顯示的流程
1. 加載數(shù)據(jù)
2. 拼接HTML寫入到頁(yè)面
3. 檢查剛剛寫入的HTML中的img是否全部加載完成,如果是,進(jìn)入5、否則進(jìn)入4
4. 等待圖片加載完成
5. 計(jì)算每個(gè)元素的位置
*/
define(function(require, exports, module) {
'use strict';
var Tmpl = require('lib/tmpl/2.1.x/index.js'),
$ = require('lib/jquery/1.11.x/index.js');
var waterFall = {
init: function(options) {
var t = this;
t._container = options.container;
t._template = options.template;
t._colWidth = options.colWidth;
t._colSpacing = options.colSpacing;
t._rowSpacing = options.rowSpacing;
t.dataURL = options.dataURL;
t.dataType = options.dataType;
t.page = options.page;
t.pageEnd = options.pageEnd;
t._switch = false;
//計(jì)算有幾列 總寬度 / (列寬 + 列間隔)
t._totalCols = parseInt(t._container.width() / (t._colWidth + t._colSpacing));
// 創(chuàng)建用于記錄每列高度的數(shù)組
t._cols = new Array(t._totalCols);
// 初始化為0
for (var i = 0; i < t._cols.length; i++) {
t._cols[i] = 0;
}
t._loadingPage = options.page || 0;
t._loadNext(options);
//下拉滾動(dòng)條加載
var lastTime = new Date().getTime();
$(window).scroll(function() {
if ( !t._switch ) {
//判斷是否滾動(dòng)過(guò)快,在ie下
var thisTime = new Date().getTime();
if (thisTime - lastTime < 50) {
console.log(thisTime - lastTime);
lastTime = thisTime;
return;
}
if ($(window).scrollTop() + $(window).height() >= document.documentElement.scrollHeight) {
lastTime = thisTime;
t._loadNext();
}
}
});
},
//加載器
_loadNext: function(t) {
var t = this;
t._switch = true;
//請(qǐng)求數(shù)據(jù)
if (!t.trigger) {
$.ajax({
url: t.dataURL,
data: { page: ++t._loadingPage },
dataType:t.dataType,
success: function(response){
t.trigger = t._completeLoading(response);
},
error:function(){console.log('Error! 請(qǐng)求有誤');}
});
}
return false;
},
//加載完數(shù)據(jù)調(diào)用此函數(shù)
_completeLoading: function(result) {
var t = this;
if (t._loadingPage >= t.pageEnd) {
$('#more').hide();
$('#loading').html('<p>已是最后一頁(yè)了喔 ^_^ ^_^</p>');
return true;
}
else {
//if (!pageNum()) {
t._add(result);
//};
}
return false;
},
//添加格子
_add: function(result) {
var t = this, grids = '';
//調(diào)用模板
var content = Tmpl.render(t._template, {data:result.data});
//原始定位
t._grids = $(content).css({
position: 'absolute',
left: t._container.width(),
top: t._container.height(),
width: t._colWidth,
opacity: 0
});
//把Html添加到容器
t._container.append(t._grids);
// 執(zhí)行一次_reposition,如果所有圖片都加載完成,該方法返回true,否則返回false
if ( !t._reposition() ) {
// 有圖片未加載完,監(jiān)聽(tīng)onload和onerror
t._grids.find('img').bind('load error', function() {
this.loaded = true;
// 有圖片加載完成,再次執(zhí)行_reposition
if (t._grids) {
t._reposition();
}
});
}
},
// 此方法用于獲取高度最低的列
_getLowestCol: function() {
var cols = this._cols, min = 0;
for (var i = 1; i < cols.length; i++) {
if (cols[i] < cols[min]) {
min = i;
}
}
return min;
},
//定位
_reposition: function() {
var t = this, allImgsLoaded = true;
// 檢測(cè)圖片是否全部加載完成
t._grids.find('img').each(function(i, img) {
if (!img.loaded && !img.complete) {
allImgsLoaded = false;
}
return allImgsLoaded;
});
if (allImgsLoaded) {
t._grids.each(function(i, grid) {
//先顯示出來(lái)
grid = $(grid).show();
var height = grid.outerHeight(), min = t._getLowestCol();
// 非第一行的時(shí)候,要加上行間隔
if (t._cols[min]) { t._cols[min] += t._rowSpacing; }
// 定位
grid.animate({
left: (t._colWidth + t._colSpacing) * min,
top: t._cols[min],
opacity: 1
},1000);
// 記錄高度
t._cols[min] += height;
});
// 重設(shè)外層容器高度為最高列高度
t._container.css( 'height', Math.max.apply(Math, t._cols) );
t._switch = false;
delete t._grids;
}
return allImgsLoaded;
},
}
return waterFall;
});
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)javascript程序設(shè)計(jì)有所幫助。
- js圖片加載效果實(shí)例代碼(延遲加載+瀑布流加載)
- 利用JS實(shí)現(xiàn)簡(jiǎn)單的瀑布流加載圖片效果
- JavaScript實(shí)現(xiàn)瀑布流以及加載效果
- javascript實(shí)現(xiàn)瀑布流動(dòng)態(tài)加載圖片原理
- javascript實(shí)現(xiàn)仿百度圖片的瀑布流加載效果
- JavaScript實(shí)現(xiàn)圖片自動(dòng)加載的瀑布流效果
- 解析javascript瀑布流原理實(shí)現(xiàn)圖片滾動(dòng)加載
- javascript瀑布流式圖片懶加載實(shí)例解析與優(yōu)化
- javascript瀑布流式圖片懶加載實(shí)例
- js實(shí)現(xiàn)動(dòng)態(tài)加載數(shù)據(jù)瀑布流
相關(guān)文章
微信小程序 自定義復(fù)選框?qū)崿F(xiàn)代碼實(shí)例
這篇文章主要介紹了微信小程序 自定義復(fù)選框?qū)崿F(xiàn)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
使用JS來(lái)動(dòng)態(tài)操作css的幾種方法
這篇文章主要介紹了使用JS來(lái)動(dòng)態(tài)操作css的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
Javascript結(jié)合css實(shí)現(xiàn)網(wǎng)頁(yè)換膚功能
現(xiàn)在網(wǎng)站換皮膚是比較常見(jiàn)的功能,大多數(shù)論壇都有的,要想實(shí)現(xiàn)這樣效果可以看如下代碼.2009-11-11
IE6中使用position導(dǎo)致頁(yè)面變形的解決方案(js代碼)
IE6中使用position導(dǎo)致頁(yè)面變形,影響用戶體驗(yàn),通過(guò)搜索可以通過(guò)js來(lái)實(shí)現(xiàn)。2011-01-01
js中hasOwnProperty的屬性及實(shí)例用法詳解
在本篇文章里小編給大家整理的是一篇關(guān)于js中hasOwnProperty的屬性及實(shí)例用法詳解內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)下。2021-11-11
JavaScript實(shí)現(xiàn)簡(jiǎn)單的四則運(yùn)算計(jì)算器完整實(shí)例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單的四則運(yùn)算計(jì)算器,結(jié)合完整實(shí)例形式分析了javascript基于表單相應(yīng)實(shí)現(xiàn)加減乘除數(shù)學(xué)運(yùn)算的操作技巧,需要的朋友可以參考下2017-04-04
javascript 觸發(fā)HTML元素綁定的函數(shù)
只能觸發(fā)函數(shù)的執(zhí)行,并不能完全模擬出實(shí)際的點(diǎn)擊。2010-09-09
javascript在網(wǎng)頁(yè)中實(shí)現(xiàn)讀取剪貼板粘貼截圖功能
這篇文章主要介紹了在網(wǎng)頁(yè)中實(shí)現(xiàn)讀取剪貼板粘貼截圖功能,即可以把剪貼板的截圖Ctrl+V粘貼到網(wǎng)頁(yè)的一個(gè)輸入框中,例如QQ截圖、旺旺截圖或者其它截圖軟件,需要的朋友可以參考下2014-06-06
改變checkbox默認(rèn)選中狀態(tài)及取值的實(shí)現(xiàn)代碼
下面小編就為大家?guī)?lái)一篇改變checkbox默認(rèn)選中狀態(tài)及取值的實(shí)現(xiàn)代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05

