[英]How to trigger a JavaScript function only when the user scrolls the page
[英]Trigger a function when the user scrolls the element into the viewport – Vanilla JavaScript
我寫了一個動畫條形圖的函數。 當前,此操作是在頁面加載時觸發的,但是我只希望在到達該元素時觸發它–否則用戶將看不到動畫。 我想通過香草JavaScript實現這一目標,這可能嗎?
這是我的標記:
<div class="section">
section
</div>
<div class="section">
section
</div>
<div class="section">
section
</div>
<div class="section">
section
<ul class="skills__list">
<li class="skills__list-item">
<div class="bar">
<span>HTML</span>
<div class="bar__inner" data-percent="90%"></div>
</div>
</li>
<li class="skills__list-item">
<div class="bar">
<span>css</span>
<div class="bar__inner" data-percent="80%"></div>
</div>
</li>
<li class="skills__list-item">
<div class="bar">
<span>Javascript</span>
<div class="bar__inner" data-percent="60%"></div>
</div>
</li>
<li class="skills__list-item">
<div class="bar">
<span>UI design</span>
<div class="bar__inner" data-percent="70%"></div>
</div>
</li>
<li class="skills__list-item">
<div class="bar">
<span>sketch</span>
<div class="bar__inner" data-percent="50%"></div>
</div>
</li>
<li class="skills__list-item">
<div class="bar">
<span>Photoshop</span>
<div class="bar__inner" data-percent="80%"></div>
</div>
</li>
<li class="skills__list-item">
<div class="bar">
<span>Illustrator</span>
<div class="bar__inner" data-percent="90%"></div>
</div>
</li>
</ul>
</div>
這是Scss:
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.section {
padding: 20px;
font-size: 30px;
font-family: sans-serif;
text-transform: uppercase;
height: 400px;
&:nth-child(1){
background-color: #ddd;
}
&:nth-child(2){
background-color: #aaa;
}
&:nth-child(3){
background-color: #bbb;
}
&:nth-child(4){
background-color: #000;
}
}
.skills__list-item {
& + .skills__list-item {
margin-top: 20px;
}
}
// bar chart styles
.bar {
position: relative;
width: 100%;
height: 28px;
overflow: hidden;
background-color: blue;
span {
position: absolute;
z-index: 9;
display: flex;
align-items: center;
height: 100%;
padding: 10px;
color: #fff;
background-color: red;
}
&__inner {
display: flex;
justify-content: flex-end;
width: 0;
height: 100%;
background-color: green;
transform-origin: 0 100%;
transition: width 0.6s linear;
&::after {
content: attr(data-percent);
align-self: center;
padding-right: 20px;
color: #fff;
}
}
}
這是JavaScript:
const bars = document.querySelectorAll('.bar__inner');
Array.from(bars).forEach((bar, index) => {
setTimeout(() => {
const eachBar = bar;
eachBar.style.width = bar.dataset.percent;
}, index * 400);
});
這是一個工作示例Codepen 。
您可以關注Gomakethings.com網站上非常有用的提示 。
它表明您可以使用getBoundingClientRect()
方法實現您的目標:
// Get the an HTML element
var element = document.querySelector('<a selector>');
// Get its bounding client rectangle
var bounding = element.getBoundingClientRect();
使用它來構建一個函數,該函數通過檢索邊界框來檢查元素是否在視口客戶端中(好的,可以改進代碼,這只是一個演示):
function isInViewPort(element) {
// Get the bounding client rectangle position in the viewport
var bounding = element.getBoundingClientRect();
// Checking part. Here the code checks if it's *fully* visible
// Edit this part if you just want a partial visibility
if (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight)
) {
console.log('In the viewport! :)');
return true;
} else {
console.log('Not in the viewport. :(');
return false;
}
}
最后,在scroll
事件上添加事件偵聽器 ,以調用上述函數:
window.addEventListener('scroll', function (event) {
if (isInViewport(theElementToWatch)) {
// update the element display
}
}, false);
根據MDN頁面顯示的瀏覽器兼容性,Chrome和Firefox(> = 3.5)完全支持getBoundingClientRect()
)。 最常用的瀏覽器完全支持此處提供的解決方案(某些移動版本不知道)。
根據我可以使用...網站提供的信息,至少從給定版本開始,移動瀏覽器(Chrome,Firefox等)完全支持該方法。
最后,您可以記住一個仍在實驗中的解決方案,該解決方案旨在替代使用getBoundingClientRect()
Observer API getBoundingClientRect()
方法(請參見Tom M的答案)。 與MDN相關的頁面說明了原因:
過去實現交叉檢測涉及事件處理程序,並循環調用
Element.getBoundingClientRect()
類的方法來為每個受影響的元素建立所需的信息。 由於所有這些代碼都在主線程上運行,因此即使其中一個也會導致性能問題。 當網站加載了這些測試時,事情可能會變得很丑陋。
您可以為此使用IntersectionObserver
API。
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
console.log(entry.target);
// your callback here
})
});
observer.observe(document.querySelector('.skills__list-item'));
請注意瀏覽器支持 ,例如IE,Safari和Opera Mini不支持它。
如果要支持IE7 +,則可以使用W3C提供的polyfill 。
資源
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.