[前端小項(xiàng)目] 滾動(dòng)動(dòng)畫 Scroll Animation (50projects50days)
??前言
- 這個(gè)小項(xiàng)目源于github項(xiàng)目:?50 projects 50 days, 這個(gè)項(xiàng)目包含了50個(gè)小型前端項(xiàng)目,適合學(xué)習(xí)了Html+Css+JavaScript但是還沒(méi)有學(xué)習(xí)框架的前端新手作為練習(xí)。
- 這里是原項(xiàng)目的代碼實(shí)現(xiàn)??Scroll Animation Code.
- 這里是原項(xiàng)目的呈現(xiàn)效果??Scroll Animation Live Demo.
?????分析

布局
水平居中的實(shí)現(xiàn)較為簡(jiǎn)單,可以使用margin:0 auto;,也可以使用flex布局:
#container{
display:flex;
flex-direction:column;
align-items:center;
}
綁定滾動(dòng)事件
- 滾動(dòng)事件可以考慮節(jié)流,但是這里內(nèi)容比較簡(jiǎn)單,就不使用節(jié)流了(主要是不會(huì)??),原項(xiàng)目的代碼也沒(méi)有用節(jié)流。
- 滾動(dòng)事件可以用事件監(jiān)聽(tīng)
addEventListener()綁定到window對(duì)象上(也可以就綁定到document上)。 - 觸發(fā)滾動(dòng)事件后,執(zhí)行對(duì)應(yīng)的函數(shù)——判斷哪些卡片是顯示的,哪些是不顯示的(在窗口外部的)。
判斷是否顯示卡片
- 獲取卡片元素,使用
querySelectorAll(),得到一個(gè)靜態(tài)的NodeList(偽數(shù)組)。 - 使用
forEach()方法,對(duì)每一個(gè)卡片判斷是否顯示。 - 顯示原則:當(dāng)卡片的頂部到達(dá)視圖窗口的頂部的距離小于視圖窗口的高度時(shí),說(shuō)明卡片到達(dá)視圖窗口了,便可以顯示出來(lái)。
- 此處用到了
getBoundingClientRect()方法和Window.innerHeight屬性,后者返回視圖窗口的高度。 - 關(guān)于
getBoundingClientRect(),MDN Web Docs是這樣解釋的:
Element.getBoundingClientRect()方法返回一個(gè) DOMRect 對(duì)象,其提供了元素的大小及其相對(duì)于視口的位置。
語(yǔ)法
getBoundingClientRect()
參數(shù)
無(wú)。
返回值
返回值是一個(gè) DOMRect 對(duì)象,是包含整個(gè)元素的最小矩形(包括 padding 和 border-width)。該對(duì)象使用 left、top、right、bottom、x、y、width 和 height 這幾個(gè)以像素為單位的只讀屬性描述整個(gè)矩形的位置和大小。除了 width 和 height 以外的屬性是相對(duì)于視圖窗口的左上角來(lái)計(jì)算的。

- 在原GitHub項(xiàng)目給出的代碼中,其判斷條件是卡片使用
getBoundingClientRect()方法后,獲取top值,然后再和Window.innerHeight的\(\frac{4}{5}\)做比較,此處的\(\frac{4}{5}\)應(yīng)該是優(yōu)化參數(shù),影響不大。
?????代碼實(shí)現(xiàn)
Html
點(diǎn)擊查看代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>scroll-animation</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- 提示語(yǔ)句 -->
<h1>Scroll to See the Animation</h1>
<!-- 卡片列表 -->
<div id="list">
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
<div class="box">
<p>content</p>
</div>
</div>
</body>
<script src="script.js"></script>
</html>
Css
點(diǎn)擊查看代碼
*{
box-sizing: border-box;
}
body{
min-height: 100vh;
background-color: #efedd6;
display: flex;
flex-direction: column;
align-items: center;
overflow-x: hidden;
}
#list{
/* 卡片居中排列 */
display: flex;
flex-direction: column;
align-items: center;
}
#list .box{
/* 卡片通用樣式 */
width: 320px;
height: 200px;
background-color:#4682b4;
display: flex;
align-items: center;
justify-content: center;
border-radius: 1rem;
box-shadow: 2px 4px 5px rgb(0 0 0 / 30%);
margin: 10px 0;
transition: transform ease 0.4s;
}
/* 偶數(shù)盒子不顯示時(shí),向右邊偏移 */
#list .box:nth-of-type(2n){
transform: translateX(400%);
}
/* 奇數(shù)盒子不顯示時(shí),向左邊偏移 */
#list .box:nth-of-type(2n+1){
transform: translateX(-400%);
}
#list .box p{
color: #fff;
font-size: 32px;
font-weight: bold;
}
/* 添加上.show類的盒子取消平移量,回到中間 */
#list .box.show{
transform: translateX(0%);
}
JavaScript
點(diǎn)擊查看代碼
window.onload = function(){
//獲取盒子元素
const boxes = document.querySelectorAll('.box');
//判斷所有盒子中,有哪些盒子是要顯示出來(lái)的
function check(){
//forEach()方法是一種數(shù)組迭代方法
boxes.forEach(box=>{
//對(duì)每一個(gè)卡片判斷是否顯示出來(lái)
//這里使用了getBoundingClientRect()方法和window.innerHeight屬性
if(box.getBoundingClientRect().top <= window.innerHeight*4/5){
box.classList.add('show');
}else{
box.classList.remove('show');
}
});
}
//綁定滾動(dòng)事件
document.addEventListener('scroll',check);
//頁(yè)面加載完,先判斷當(dāng)前視口內(nèi)有哪些卡片是要顯示的
check();
}
??知識(shí)點(diǎn)清單
- 數(shù)組迭代方法:
forEach()。 - 獲取當(dāng)前卡片在窗口的相對(duì)位置時(shí),可以使用
getBoundingClientRect()方法和window.innerHeight屬性進(jìn)行計(jì)算、判斷。 - 使用Css選擇器的過(guò)程中,要注意空格的存在,比如
.box .show(中間有空格)表示帶有.box的元素的子元素中帶有.show的元素;而.box.show(中間無(wú)空格)則選擇到了同時(shí)帶有.box和.show這兩個(gè)類的元素。
??參考文章
[1]Element.getBoundingClientRect()
[2]Window.innerHeight
[3]CSS選擇器參考手冊(cè)

浙公網(wǎng)安備 33010602011771號(hào)