JavaScript 練習 - 瀑布流相簿

Demo

JavaScript 練習 - 瀑布流相簿 - Demo

Introduction 介紹

瀑布流是一種常見的版面配置,在滑鼠滾輪向下滾動時,頁面便會不斷的加載,讓新的內容產生出來並附加在網頁的最底端。這種特別的互動方式可以讓使用者在瀏覽內容時,不必再像以往一樣一直不斷的在網頁上點擊下一頁,可以讓使用者瀏覽起來更為輕鬆。像是 Pinterest,就是使用這種瀏覽方式。這個練習就是實現一個瀑布流相簿。

  • 瀑布流的圖片定位
  • 瀑布流的圖片排序
  • 瀑布流的圖片加載功能

功能

HTML、CSS 結構

HTML 結構比較單純,一個區塊內包含一張圖片元素。此外,由於待會我們要按照圖片寬高來調整圖片位置,所以整個頁面使用相對定位。

1
2
3
4
5
6
7
<div id="main">
<div class="box">
<div class="pic">
<img src="./img/1.jpg" alt="" />
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#main {
position: relative;

.box {
padding: 15px 0 0 15px;
float: left;

.pic {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 0 5px #ccc;

img {
height: auto;
}
}
}
}

瀑布流的圖片定位

頁面加載的時候就要呼叫一個取得整個頁面裡圖片區塊的函數,這個函數傳入兩個參數,父元素及要傳入的圖片區塊,取得所有父元素底下 class 為 box 的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
window.onload = function() {
waterfall("main", "box");
};

function waterfall(parent,box){
var allParent = document.getElementById(parent);
var allBox = getByClass(allParent,box);
}

function(parent,clsName){
var boxArr = [];
allElements = parent.getElementsByTagName('*')
for(var i =0;i<allElements.length;i++){
if(allElements[i].className===clsName){
boxArr.push(allElements[i]);
}
}
return boxArr;
}

計算頁面顯示的列數,是利用頁面寬度除以圖片區塊的寬度。先使用 offsetWidth取得其中單一圖片區塊的寬度即可,再取得瀏覽器頁面寬度並相除,就會取得呈現載每一列的圖片數量。這裡也要使用每一張圖片的寬度乘以每一列呈現數量,獲得最外層父元素的寬度。

1
2
3
4
5
function waterfall(parent, box) {
var allBoxW = allBox[0].offsetWidth;
var col = Math.floor(document.documentElement.clientWidth / allBoxW);
allParent.style.cssText = "width:" + allBoxW * col + "px;margin:0 auto";
}

瀑布流的圖片排序

接下來要依序使圖片出現在另一張圖片的底部,先取得第一行裡行高最小的圖片,使用 apply(),改變 this 的指向,找出 heightArr 中最矮的圖片,讓第二列從這張圖片開始排列。同時也要取得這張最矮圖片的索引位置。最後因為加入圖片之後,最小高度的圖片不是原來那張了,是原來圖片與新增圖片的高度,這樣才不會一直新增在同一張底下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function waterfall(parent, box) {
var heightArr[];
for (var i =0;i<allBox.length;i++){
if(i<col){
heightArr.push(allBox[i].offsetHeight);
}else{
var minHeight=Math.min.apply(null,heightArr);
var index = getMinHeightIndex(heightArr,minHeight);
allBox[i].style.position = "absolute";
allBox[i].style.top=minHeight+"px";
allBox[i].style.left=allBox[index].offsetLeft+"px";
heightArr[index]+=allBox[i].offsetHeight;
}
}
}

function getMinHeightIndex(arr,val){
for (var i in arr){
if(arr[i]===val){
return i; }
}
}

瀑布流的圖片加載

最後一個是實現無限圖片加載,當滾動側邊的時候加載圖片。這裡要檢測是否具備滾動加載數據的條件。首先要取得最後一個圖片區塊頂部與頁面頂部的距離加上該圖片一半的高度(a)。也取得已經滾動出頁面外的距離加銀幕高度(b)。如果 a>b,則具備加載數據的條件

1
2
3
4
5
6
7
8
9
10
function checkScrollSilde() {
var allParent = document.getElementById("main");
var allBox = getByClass(allParent, "Box");
var lastBoxHeight =
allBox[allBox.length - 1].offsetTop +
Math.floor(allBox[allBox.length - 1].offsetHeight / 2);
var scrollTop =
document.body.scrollTop || document.documentElement.clientHeight;
return lastBoxHeight < scrollTop + height ? true : false;
}

最後將數據渲染到頁面尾端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
window.onload = function() {
waterfall("main", "box");
var dataInt = {
data: [
{ src: "1.jpg" },
{ src: "2.jpg" },
{ src: "3.jpg" },
{ src: "4.jpg" },
{ src: "5.jpg" },
{ src: "6.jpg" },
{ src: "7.jpg" },
{ src: "8.jpg" },
{ src: "9.jpg" },
{ src: "10.jpg" },
{ src: "11.jpg" },
{ src: "12.jpg" },
{ src: "13.jpg" },
{ src: "14.jpg" },
{ src: "15.jpg" },
{ src: "16.jpg" },
{ src: "17.jpg" },
{ src: "18.jpg" },
{ src: "19.jpg" },
{ src: "20.jpg" }
]
};
window.onscroll = function() {
if (checkScrollSlide) {
//把數據渲染到頁面尾端
var allParent = document.getElementById("main");
for (var i = 0; i < dataInt.data.length; i++) {
var allBox = document.createElement("div");
allBox.className = "box";
allParent.appendChild(allBox);
var allPic = document.createElement("div");
allPic.className = "pic";
allBox.appendChild(allPic);
var allImg = document.createElement("img");
allImg.src = "img/" + dataInt.data[i].src;
allPic.appendChild(allImg);
}
waterfall("main", "box");
}
checkScrollSlide();
};
};

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2020 CYC'S BLOG All Rights Reserved.

UV : | PV :