门户里添加了一个图片频道,看现在的瀑布流这么火,于是想实现一下看看效果。
网上搜索到一个叫waterflow的瀑布流例子,研究了一下,发现要改造起来也不难,下面一步步来实现。
1.新建一个门户列表页瀑布流模板list_waterflow.htm,里面的内容可以先复制list.htm的贴进来。
因为是用ajax方式加载文章列表的,所以原来用loop循环的方式显示列表就可以抛弃了,列表html结构如下:
<div class="waterflow-container">
<div>
<div id="infscr-loading" style="display: block; ">
<img alt="Loading..." src="ajax-loader.gif">
<div>加载中...</div>
</div>
<div id="noshow" style="display: none; ">
<div>就这些了</div>
</div>
添加样式:
/*瀑布流样式*/
.waterflow-container{position:relative;font-size:12px;border:1px solid #ccc;padding:0;margin:0;text-align:center;background-color:white;}
.hide {display:none;}
#infscr-loading{
position: fixed;
bottom: 40px;
left: 50%;
top:50%;
width: 150px;
text-align: center;
margin-left: -75px;
z-index: 99;
}
#infscr-loading div{
display: block;
padding: 5px 10px 5px 10px;
background-color: #FAFAEF;
border: 1px solid #AAA;
border-radius: 6px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
-moz-box-shadow: 0 0 18px #999;
-webkit-box-shadow: 0 0 18px #999;
box-shadow: 0 0 18px #999;
}
#noshow {
position: fixed;
bottom: 40px;
left: 50%;
top:50%;
width: 150px;
text-align: center;
margin-left: -75px;
z-index: 99;
}
#noshow div{
display: block;
padding: 5px 10px 5px 10px;
background-color: #FAFAEF;
border: 1px solid #AAA;
border-radius: 6px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
-moz-box-shadow: 0 0 18px #999;
-webkit-box-shadow: 0 0 18px #999;
box-shadow: 0 0 18px #999;
}
添加控制js:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.windswaterflow.js"></script>
<script type="text/javascript">
var j = jQuery.noConflict();
j(document).ready(function(){
j(".waterflow-container").windswaterflow({
itemSelector: '.box',
loadSelector: '#infscr-loading',
noSelector: '#noshow',
boxTemplate: '<div class="box hide"><a href="#"><div class="img"><img src="%img%" style="height:%height%px;" alt="" /></div></a><div class="title">%title%</div><div class="like btn">喜欢</div><div class="comments btn">评论</div></div>',
columnWidth: 210,
marginWidth: 24,
marginHeight: 16,
ajaxServer: 'portal.php?mod=list&catid='+{$catid}+'&waterflow=true',
boxParam: 'num',
pageParam: 'page',
maxPage: 0,
init: false,
initBoxNumber: 20,
scroll: true,
scrollBoxNumber: 10,
callback: function() {
}
});
});
</script>
2.在source\module\portal\portal_list.php文件里,82行增加ajax提供数据的代码
if(isset($_GET['waterflow'])){
$wheresql = category_get_wheresql($cat);
$list = category_get_list($cat,$wheresql,$page);
echo json_encode($list['list']);
die();
}
这样门户的瀑布流就基本实现了。
jquery.windswaterflow.js内容如下:
(function($) {
$.fn.windswaterflow = function(options) {
//初始化状态
var _init = 0, _isminCols = false, _isnoShow = false;
var defaults = {
itemSelector: '',
loadSelector: '',
noSelector: '',
boxTemplate: '',
columnWidth: 240,
marginWidth: 14,
marginHeight: 16,
minCols: 3,
maxPage: 0,
align: 'center',
ajaxServer: '',
boxParam: '',
pageParam: 'page',
pageNumber: 1,
init: false,
initBoxNumber: 20,
scroll: false,
scrollBoxNumber: 10,
callback: null
};
//参数合并
var param = $.extend({}, defaults, options || {});
//如果没有元素和TPL则返回
if (param.itemSelector == '' || param.tplSelector == '') {
return;
}
if (param.loadSelector != '') {
//$(param.loadSelector).hide();
}
if (param.noSelector != '') {
$(param.noSelector).hide();
}
if ($(this).css('text-align') != undefined) {
param.align = $(this).css('text-align');
}
function _min(_arr) {
return Math.min.apply(Math, _arr);
};
function _max(_arr) {
return Math.max.apply(Math, _arr);
};
function findShortIndex(_arr) {
var index = 0, i;
for (i in _arr) {
if (_arr[i] < _arr[index]) {
index = i;
}
}
return index;
};
function findLongIndex(_arr) {
var index = 0, i;
for (i in _arr) {
if (_arr[i] > _arr[index]) {
index = i;
}
}
return index;
};
if (param.init) {
//如果有初始化,则清空原来的
$(this).html('');
}
//BOX个数
var _boxCount = $(param.itemSelector).length;
//每个BOX的宽度
var _boxWidth = param.columnWidth + param.marginWidth;
//包含层的宽度
var _containerWidth = $(this).width();
//计算出列数
var _showCols = Math.floor(_containerWidth / _boxWidth);
//得到居中后的左边padding
var _containerPadding = 0;
if (param.align == 'left') {
_containerPadding = 0;
}
else if (param.align == 'right') {
_containerPadding = _containerWidth % _boxWidth;
}
else {
_containerPadding = (_containerWidth % _boxWidth) / 2;
}
//如果小于最小列,则左边距为0
if (_showCols < param.minCols) {
_containerPadding = 0;
_showCols = param.minCols;
_isminCols = true;
}
//计算出行数
var _tpRows = $(param.itemSelector).length / _showCols;
var _showRows = Math.floor(_tpRows) == _tpRows ? _tpRows : _tpRows + 1;
//记录每行当前的高度
var _colsTopArr = [];
//初始化为0
for (var len = 0; len < _showCols; len++) {
_colsTopArr.push(0);
};
var selector = $(this).selector;
function setPosition(wrap, boxs, op) {
//临时 最短列序号,左位置值,上位置值
var _tpShortColIdx, _tpLeftPos, _tpTopPos, _tpLen = $(boxs).length;
if (op == "resize" || op == "init") {
$(wrap).width()
_isminCols = false;
_containerWidth = $(wrap).width();
_showCols = Math.floor(_containerWidth / _boxWidth);
//得到居中后的左边padding
if (param.align == 'left') {
_containerPadding = 0;
}
else if (param.align == 'right') {
_containerPadding = _containerWidth % _boxWidth;
}
else {
_containerPadding = (_containerWidth % _boxWidth) / 2;
}
//如果小于最小列,则左边距为0
if (_showCols < param.minCols) {
_containerPadding = 0;
_showCols = param.minCols;
_isminCols = true;
}
//计算出行数
_tpRows = $(boxs).length / _showCols;
_showRows = Math.floor(_tpRows) == _tpRows ? _tpRows : _tpRows + 1;
//初始化为0
_colsTopArr.length = 0;
for (var len = 0; len < _showCols; len++) {
_colsTopArr.push(0);
};
}
//在第一次加载时无高度的情况下
//chrome不能自已加载 $.browser.safari &&
if (op == null) {
$(boxs).imagesLoaded(function() {
$(boxs).each(function(index) {
var _tpShortColIdx = index;
if (_tpShortColIdx < _showCols && op != "add") {
_tpLeftPos = _boxWidth * _tpShortColIdx + _containerPadding + "px";
$(this).css({ "top": "0", "left": _tpLeftPos, "width": param.columnWidth + "px", "margin": "0" });
}
else {
_tpShortColIdx = findShortIndex(_colsTopArr);
_tpLeftPos = _boxWidth * _tpShortColIdx + _containerPadding + "px";
_tpTopPos = _colsTopArr[_tpShortColIdx] + "px";
$(this).css({ "top": _tpTopPos, "left": _tpLeftPos, "width": param.columnWidth + "px", "margin": "0" });
}
if (op == "add") {
$(this).appendTo(wrap);
}
_colsTopArr[_tpShortColIdx] = _colsTopArr[_tpShortColIdx] + $(this).height() + param.marginHeight;
//全部加入后增加外框
if (index == _tpLen - 1) {
$(wrap).height(_max(_colsTopArr) + "px");
if (_isminCols) {
//设置以后回不去
//$(wrap).width((_boxWidth * _showCols + _containerPadding + param.marginWidth) + "px");
}
if (op == "add") {
if ($.browser.msie) {
$(".hide").animate({ opacity: 'show' }, 2000);
}
else {
$(".hide").animate({ opacity: 'show' }, 1000);
}
if (param.loadSelector != '') {
$(param.loadSelector).hide();
}
}
_SolStatus = 0;
}
});
});
}
else {
//将所有元素放到各自己的位置
$(boxs).each(function(index) {
var _tpShortColIdx = index;
if (_tpShortColIdx < _showCols && op != "add") {
_tpLeftPos = _boxWidth * _tpShortColIdx + _containerPadding + "px";
$(this).css({ "top": "0", "left": _tpLeftPos, "width": param.columnWidth + "px", "margin": "0" });
}
else {
_tpShortColIdx = findShortIndex(_colsTopArr);
_tpLeftPos = _boxWidth * _tpShortColIdx + _containerPadding + "px";
_tpTopPos = _colsTopArr[_tpShortColIdx] + "px";
$(this).css({ "top": _tpTopPos, "left": _tpLeftPos, "width": param.columnWidth + "px", "margin": "0" });
}
if (op == "add" || op == "init") {
$(this).appendTo(wrap);
}
_colsTopArr[_tpShortColIdx] = _colsTopArr[_tpShortColIdx] + $(this).height() + param.marginHeight; //parseInt($(this).css("marginTop")) * 2 + parseInt($(this).css("paddingTop")) + parseInt($(this).css("paddingBottom"));
//全部加入后增加外框
if (index == _tpLen - 1) {
$(wrap).height(_max(_colsTopArr) + "px");
if (_isminCols) {
//设置以后回不去
//$(wrap).width((_boxWidth * _showCols + _containerPadding + param.marginWidth) + "px");
}
if (op == "add") {
if ($.browser.msie) {
$(".hide").animate({ opacity: 'show' }, 2000);
}
else {
$(".hide").animate({ opacity: 'show' }, 1000);
}
}
else {
$(".hide").animate({ opacity: 'show' }, 0);
}
if (param.loadSelector != '') {
$(param.loadSelector).hide();
}
_SolStatus = 0;
if (op == "add" || op == "init") {
//每增加一次,页面加1
param.pageNumber++;
}
}
});
}
if (param.callback) {
param.callback();
}
};
if (_boxCount > 0) {
setPosition(selector, param.itemSelector);
}
//初始化完成
_init = 1;
//添加元素进去(JSON)
function appendBox(data, op) {
var newBox = [], len = Number(data.length), idx = 0;
_boxCount += len;
$.each(data, function(i) {
//通过imgReady获取图片高度
imgReady(data[i].img, function() {
//data[i].height = parseInt(this.height); //?不知道高度值是否可靠
//这里模版化BOX edit by winds 2012.4.26
var temp = "";
var matchs = param.boxTemplate.match(/\%[a-zA-Z0-9]+\%/gi);
for (var j = 0, mlen = matchs.length; j < mlen; j++) {
if (temp == "")
temp = param.boxTemplate;
var re_match = matchs[j].replace(/[\%\%]/gi, "");
temp = temp.replace(matchs[j], data[i][re_match]).replace(/[\r\t\n]/g, "");
}
newBox.push(temp);
//newBox.push('<div class="box hide"><a class="img" href="#"><img src="' + data[i].img + '" style="height:' + data[i].height + 'px;" alt="" /></a><span class="title">' + data[i].title + '</span></div>');
idx++;
if (idx == len) {
setPosition(selector, newBox.join(''), op);
}
});
});
};
//需要初始每一次添加元素
if (param.init && param.ajaxServer != '' && param.boxParam != '' && parseInt(param.initBoxNumber) > 0) {
var postPara = {};
//初始化时参数为1
param.pageNumber = 1;
postPara[param.boxParam] = parseInt(param.initBoxNumber);
postPara[param.pageParam] = parseInt(param.pageNumber);
if (param.loadSelector != '') {
$(param.loadSelector).show();
}
$.getJSON(param.ajaxServer, postPara, function(data) {
if (data.length == 0) {
//无数据返回时则显示无数据提示
if (param.noSelector != '') {
if (param.noSelector) {
$(param.noSelector).fadeIn(1000).delay(2000).fadeOut(1000);
}
}
if (param.loadSelector != '') {
$(param.loadSelector).hide();
}
_isnoShow = true;
_SolStatus = 0;
}
else {
appendBox(data, 'init');
}
});
}
//支持滚动加载
var _SolStatus = 0;
if (param.scroll && param.ajaxServer != '' && param.boxParam != '' && parseInt(param.scrollBoxNumber) > 0) {
$(window).scroll(function() {
var scrollh = document.body.scrollHeight;
var clienth = document.documentElement.clientHeight;
var scrollt = document.documentElement.scrollTop + document.body.scrollTop;
if (scrollt + clienth +100>= scrollh && _SolStatus == 0 && _init == 1 && !_isnoShow) {
if ((param.maxPage == 0 || param.pageNumber <= param.maxPage)) {
_SolStatus = 1;
if (param.loadSelector != '') {
$(param.loadSelector).show();
}
var postPara = {};
postPara[param.boxParam] = parseInt(param.scrollBoxNumber);
postPara[param.pageParam] = parseInt(param.pageNumber);
setTimeout(function() {
$.getJSON(param.ajaxServer, postPara, function(data) {
if (data.length == 0) {
//无数据返回时则显示无数据提示
if (param.noSelector != '') {
if (param.noSelector) {
$(param.noSelector).fadeIn(1000).delay(2500).fadeOut(1000);
}
}
if (param.loadSelector != '') {
$(param.loadSelector).hide();
}
_isnoShow = true;
_SolStatus = 0;
}
else {
appendBox(data, 'add');
}
});
}, 100);
}
}
});
}
//支持RESIZE
var _ReStatus;
$(window).wresize(function() {
if (_ReStatus) {
clearTimeout(_ReStatus);
}
_ReStatus = setTimeout(function() { setPosition(selector, param.itemSelector, "resize"); }, 200);
});
};
/**
* 图片头数据加载就绪事件 - 更快获取图片尺寸
* @version 2011.05.27
* @author TangBin
* @see http://www.planeart.cn/?p=1121
* @param {String} 图片路径
* @param {Function} 尺寸就绪
* @param {Function} 加载完毕 (可选)
* @param {Function} 加载错误 (可选)
* @example imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
alert('size ready: width=' + this.width + '; height=' + this.height);
});
*/
var imgReady = (function() {
var list = [], intervalId = null,
// 用来执行队列
tick = function() {
var i = 0;
for (; i < list.length; i++) {
list[i].end ? list.splice(i--, 1) : list[i]();
};
!list.length && stop();
},
// 停止所有定时器队列
stop = function() {
clearInterval(intervalId);
intervalId = null;
};
return function(url, ready, load, error) {
var onready, width, height, newWidth, newHeight,
img = new Image();
img.src = url;
// 如果图片被缓存,则直接返回缓存数据
if (img.complete) {
ready.call(img);
load && load.call(img);
return;
};
width = img.width;
height = img.height;
// 加载错误后的事件
img.onerror = function() {
error && error.call(img);
onready.end = true;
img = img.onload = img.onerror = null;
};
// 图片尺寸就绪
onready = function() {
newWidth = img.width;
newHeight = img.height;
if (newWidth !== width || newHeight !== height ||
// 如果图片已经在其他地方加载可使用面积检测
newWidth * newHeight > 1024
) {
ready.call(img);
onready.end = true;
};
};
onready();
// 完全加载完毕的事件
img.onload = function() {
// onload在定时器时间差范围内可能比onready快
// 这里进行检查并保证onready优先执行
!onready.end && onready();
load && load.call(img);
// IE gif动画会循环执行onload,置空onload即可
img = img.onload = img.onerror = null;
};
// 加入队列中定期执行
if (!onready.end) {
list.push(onready);
// 无论何时只允许出现一个定时器,减少浏览器性能损耗
if (intervalId === null) intervalId = setInterval(tick, 40);
};
};
})();
//判断图片先加载完(网上找来的,masonry使用的这个)
$.fn.imagesLoaded = function(callback) {
var $this = this,
$images = $this.find('img').add($this.filter('img')),
len = $images.length,
blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==',
loaded = [];
function triggerCallback() {
callback.call($this, $images);
}
function imgLoaded(event) {
var img = event.target;
if (img.src !== blank && $.inArray(img, loaded) === -1) {
loaded.push(img);
if (--len <= 0) {
setTimeout(triggerCallback);
$images.unbind('.imagesLoaded', imgLoaded);
}
}
}
// if no images, trigger immediately
if (!len) {
triggerCallback();
}
$images.bind('load.imagesLoaded error.imagesLoaded', imgLoaded).each(function() {
// cached images don't fire load sometimes, so we reset src.
var src = this.src;
// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
// data uri bypasses webkit log warning (thx doug jones)
this.src = blank;
this.src = src;
});
return $this;
};
//修复IE的resize问题(网上找来的)
$.fn.wresize = function(f) {
version = '1.1';
wresize = { fired: false, width: 0 };
function resizeOnce() {
if ($.browser.msie) {
if (!wresize.fired) {
wresize.fired = true;
}
else {
var version = parseInt($.browser.version, 10);
wresize.fired = false;
if (version < 7) {
return false;
}
else if (version == 7) {
//a vertical resize is fired once, an horizontal resize twice
var width = $(window).width();
if (width != wresize.width) {
wresize.width = width;
return false;
}
}
}
}
return true;
}
function handleWResize(e) {
if (resizeOnce()) {
return f.apply(this, [e]);
}
}
this.each(function() {
if (this == window) {
$(this).resize(handleWResize);
}
else {
$(this).resize(f);
}
});
return this;
};
})(jQuery);