图片类网站经常用到瀑布流的形式来排列自己的图片,例如pinterest, 花瓣网。有很多开源的jQuery框架可以实现瀑布流,但是比较复杂。这篇文章主要讲诉图片类瀑布流的布局组织的算法,用纯js实现。
HTML
略
JS
//main.js
(function () {
var COLS = 5;
var ITEMWIDTH = 236;
var GUTTERWIDTH = 15;
var columnHeights;
var button = document.getElementsByTagName("button")[0];
// Number of columns is 5, and init heights array of columns.
function resetHeights() {
columnHeights = [];
for (var i = 0; i < COLS; i++) {
columnHeights.push(0);
}
}
// main function to load images
function loadImages() {
var imageArr = getImages();
var html = "";
for (var i = 0; i < imageArr.length; i++) {
var _div = '<div class="item">';
var _img = '<img src="' + imageArr[i] + '">';
_div += _img + "</div>";
html += _div;
}
var container = document.getElementsByClassName("container")[0];
container.innerHTML = html;
console.log(html);
// after images loaded.
setTimeout(placeItems, 1000);
}
// get images source array.
function getImages() {
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
var imageArr = [];
var baseUri = "http://myst729.github.io/Waterfall/img/";
for (var i = 0; i < arr.length; i++) {
var img_src = baseUri + arr[i] + ".jpg";
imageArr.push(img_src);
}
return imageArr;
}
// get left of the item
function getItemLeft(key) {
var left = 0;
// COLS
left = (key % COLS) * (ITEMWIDTH + GUTTERWIDTH);
return left;
}
//
function placeItems() {
resetHeights();
var items = document.getElementsByClassName("item");
for (var index in items) {
columnIndex = getMinKey(columnHeights);
columnHeight = columnHeights[columnIndex];
items[index].style.left = getItemLeft(columnIndex) + "px";
items[index].style.top = columnHeight + "px";
columnHeights[columnIndex] =
columnHeight + GUTTERWIDTH + items[index].offsetHeight;
console.log(columnHeights);
}
}
// get minimal value index of an array.
function getMinKey(arr) {
var key = 0;
var min = arr[0];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
key = i;
}
}
return key;
}
button.addEventListener("click", loadImages);
})();
要点
-
项目item的定位
- item的定位: position: absolute;
- item父级元素contianer的定位:position: relative;
-
假设一定宽度内的列数为固定值5
-
item的放置方式
- 对于第一行,top值为0;
- 对于以后的行,每次新增的item,自动补在高度最小的列,并记录下该列为第几列columnIndex;
- 根据columnIndex可以计算出item的left,根据columnIndex对应的列高可以计算出item的top。
-
列高度columnHeights是一个有5个元素的数组。
简化
本文关注主要问题,即布局问题,简化(省略)了以下关注点
- 计算一定宽度内可放置的列数
- 调整浏览器窗口大小时,item重新布局
- 鼠标向下滚动事件
- ajax