JS30又來啦~!這次處理的是學生時期我們在做簡報時常用的淡入淡出功能,坦白說我同意課程講者說的:這麼做實在看了有點煩躁XD,但我們還是來看一下要如何在JS中實現這樣的功能吧!
HTML
<body>
<div class="site-wrap">
<h1>Slide in on Scroll</h1>
<p> a long paragraph</p>
<img src="http://unsplash.it/400/400" class="align-left slide-in">
<p> a long paragraph </p>
<img src="http://unsplash.it/400/401" class="align-right slide-in">
<p> a long paragraph </p>
<img src="http://unsplash.it/200/500" class="align-left slide-in">
<p> a long paragraph </p>
<p> a long paragraph </p>
<img src="http://unsplash.it/400/400" class="align-right slide-in">
<p> a long paragraph </p>
<p> a long paragraph </p>
</body>
CSS
html {
box-sizing: border-box;
background: #ffc600;
font-family: 'helvetica neue';
font-size: 20px;
font-weight: 200;
}
body {
margin: 0;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
h1 {
margin-top: 0;
}
.site-wrap {
max-width: 700px;
margin: 100px auto;
background: white;
padding: 40px;
text-align: justify;
}
.align-left {
float: left;
margin-right: 20px;
}
.align-right {
float: right;
margin-left: 20px;
}
.slide-in {
opacity: 0;
transition: all .5s;
}
.align-left.slide-in {
transform: translateX(-30%) scale(0.95);
}
.align-right.slide-in {
transform: translateX(30%) scale(0.95);
}
.slide-in.active {
opacity: 1;
transform: translateX(0%) scale(1);
}
Javascript
function debounce(func, wait = 20, immediate = true) {
var timeout;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
// 建立滑動函數
function scroll(e) {
slideImages.forEach(image => {
/*
window.screenY+window.innerHeight會給出目前滑到的位置,可以注意outerHeight & innerHeight的差別,由於我們希望滑到圖片一半時就顯示圖片,於是在後方在減掉圖片一半的高度
*/
const slideInAt = (window.scrollY + window.innerHeight) - image.height / 2
/*
滑過圖片時要讓它恢復原狀,需要找出圖片的底部,offsetTop會找出圖片的頂端與頁面最上方的距離
我們希望找到的是圖片的底部,所以還需要再加上圖片的長度
*/
const imageBottom = image.offsetTop + image.height;
const isHalfShown = slideInAt > image.offsetTop;
const isNotScrollPassed = window.scrollY < imageBottom;
isHalfShown && isNotScrollPassed ? image.classList.add('active') : image.classList.remove('active')
})
}
// 事件監聽
const slideImages = document.querySelectorAll('.slide-in')
window.addEventListener('scroll', debounce(scroll)) function debounce(func, wait = 20, immediate = true) {
var timeout;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
學習重點
- 了解如何運用scrollY、offsetTop找出元素或游標的位置
- 了解innerHeight & outerHeight的差別
- 了解為何使用debounce()->阻止事件無意義的重複執行而影響到效能
- 複習利用JS替元素套用CSS樣式的方法
參考文章