I'm fairly new to programming and I'm working on a project,
HTML
<div >
<span><h2 >Text1</h2></span>
<span
><h2 >Text2</h2></span
>
<span
><h2 >Text3</h2></span
>
<span
><h2 >text4</h2></span
>
<span><h2 >text5</h2></span>
<span><h2 >text6</h2></span>
<span><h2 >text7</h2></span>
<span><h2 >text8</h2></span>
<span><h2 >text9</h2></span>
</div>
JavaScript
// Check if is in viewport & animate
const headers2 = document.querySelector(".twoH");
function elementInViewportTWO() {
let bounding = headers2.getBoundingClientRect();
if (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.right <=
(window.innerWidth || document.documentElement.clientWidth) &&
bounding.bottom <=
(window.innerHeight || document.documentElement.clientHeight)
) {
headers2.style.opacity = 1;
} else {
headers2.style.opacity = 0.6;
}
}
setInterval(elementInViewportTWO, 10);
My questions is, how to apply this effect, given an array of 9 headings without reusing so much code, how do I make my function work with an array of elements? (My code highlights text when a certain element is in a viewport)
CodePudding user response:
Select them all with document.querySelectorAll
and loop through them each time.
// Check if is in viewport & animate
const headers = document.querySelectorAll(".animatedHeader");
function elementsInViewport() {
headers.forEach(header=>{
let bounding = header.getBoundingClientRect();
if (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.right <=
(window.innerWidth || document.documentElement.clientWidth) &&
bounding.bottom <=
(window.innerHeight || document.documentElement.clientHeight)
) {
header.style.opacity = 1;
} else {
header.style.opacity = 0.6;
}
})
}
setInterval(elementsInViewport, 10);
<div >
<span><h2 >Text1</h2></span>
<span
><h2 >Text2</h2></span
>
<span
><h2 >Text3</h2></span
>
<span
><h2 >text4</h2></span
>
<span><h2 >text5</h2></span>
<span><h2 >text6</h2></span>
<span><h2 >text7</h2></span>
<span><h2 >text8</h2></span>
<span><h2 >text9</h2></span>
</div>
CodePudding user response:
The function you've provided evaluates the dimensions of each .animatedHeader
element every 10 milliseconds. This will make your CPU work very hard and has a high chance of hurting your site's peformance. And because of setInterval
it will keep on running even if you're not interacting with the site and nothing changes.
Instead, consider using the Intersection Observer API which is specifically designed to detect if elements are within a viewport whilst keeping the performance high.
const headers = document.querySelectorAll('.animatedHeader');
const intersectionCallback = entries => {
for (const { isIntersecting, target } of entries) {
if (isIntersecting) {
target.style.opacity = 1;
} else {
target.style.opacity = 0.6;
}
}
};
const observer = new IntersectionObserver(intersectionCallback);
for (const header of headers) {
observer.observe(header);
}