|
/* |
|
To check whether the given element in view port by visibility percentage |
|
Tweak the number (20) as you need for the visibility percentage |
|
*/ |
|
function isInViewport(element) { |
|
const rect = element.getBoundingClientRect() |
|
const viewportWidth = |
|
window.innerWidth || document.documentElement.clientWidth |
|
const viewportHeight = |
|
window.innerHeight || document.documentElement.clientHeight |
|
|
|
const visibleWidth = |
|
Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0) |
|
const visibleHeight = |
|
Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0) |
|
|
|
const visibleArea = visibleWidth * visibleHeight |
|
const elementArea = element.offsetWidth * element.offsetHeight |
|
|
|
const visibilityPercentage = (visibleArea / elementArea) * 100 |
|
|
|
return visibilityPercentage >= 20 |
|
} |
|
|
|
|
|
// Adding classname to a tag if its is in viewport |
|
function highlightNavLink() { |
|
const sections = document.querySelectorAll('section') |
|
const navLinks = document.querySelectorAll('.nav-link a') |
|
|
|
// Remove "active" class from all navigation links |
|
navLinks.forEach((link) => { |
|
link.classList.remove('activeLink') |
|
link.classList.add('inactiveLink') |
|
}) |
|
|
|
// Add "active" class to the correct navigation link |
|
sections.forEach((section) => { |
|
const navLink = document.querySelector(`a[href="#${section.id}"]`) |
|
if (navLink && isInViewport(section)) { |
|
navLink.classList.add('activeLink') |
|
} |
|
}) |
|
} |
|
|
|
// Usage |
|
window.addEventListener('scroll', highlightNavLink) |
|
|
|
// Optional you can add debounce as well to prevent continous calls upto 100ms to 200ms |
|
|
|
|
|
function debounce(func, delay) { |
|
let timeoutId |
|
return function () { |
|
const context = this |
|
const args = arguments |
|
clearTimeout(timeoutId) |
|
timeoutId = setTimeout(() => { |
|
func.apply(context, args) |
|
}, delay) |
|
} |
|
} |
|
|
|
|
|
// Debounce the scroll event to prevent continuous calls update the 100 as per your preference |
|
const debouncedHighlightNavLink = debounce(highlightNavLink, 100) |
|
|
|
|
|
// Usage for debounce |
|
window.addEventListener('scroll', debouncedHighlightNavLink) |
|
|
|
|
|
|