Подсветить ссылки меню в зависимости от скролла страницы (по заголовкам в тексте)
Есть код JavaScrpt, который отвечает за боковое меню страницы. Он считывает все h2,h3 теги на странице и копирует их в div class="articles_tags_list_content", оборачивает в тег a, и делает плавный скролл по клику от тега a к соответствующему заголовку. Подскажите как добавлять class="active" к ссылкам в меню (при скролле страницы), в зависимости от того какая часть текста сейчас отображается на экране. Я нашла пример на jQuery, но хочу добиться результата на чистом JavaScrpt. Вот пример того, как должно работать:
jQuery(window).scroll(function() {
var $sections = $('section');
$sections.each(function(i, el) {
var top = $(el).offset().top - 100;
var bottom = top + $(el).height();
var scroll = $(window).scrollTop();
var id = $(el).attr('id');
if (scroll > top && scroll < bottom) {
$('a.active').removeClass('active');
$('a[href="#' + id + '"]').addClass('active');
}
})
});
$("nav").on("click", "a", function(event) {
// исключаем стандартную реакцию браузера
event.preventDefault();
// получем идентификатор блока из атрибута href
var id = $(this).attr('href'),
// находим высоту, на которой расположен блок
top = $(id).offset().top;
// анимируем переход к блоку, время: 800 мс
$('body,html').animate({
scrollTop: top
}, 800);
});
section {
font: bold 24px/700px Helvetica, arial, sans-serif;
height: 700px;
text-align: center;
color: #ededed;
text-transform: uppercase;
}
section#block1 {
background: #F05222;
}
section#block2 {
background: #7CBA01;
}
section#block3 {
background: #00A6F0;
}
section#block4 {
background: #FFB901;
}
nav {
position: fixed;
right: 20px;
top: 20px;
padding: 10px;
border-radius: 5px;
background: #ededed;
}
a {
display: block;
}
a.active {
color: #f95;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<nav>
<a href="#block1"> Block 1 </a>
<a href="#block2"> Block 2 </a>
<a href="#block3" class=""> Block3 </a>
<a href="#block4"> Block 4 </a>
</nav>
<div>
<section id="block1" class="nav">block 1</section>
<section id="block2" class="nav">block 2</section>
<section id="block3" class="nav">block 3</section>
<section id="block4" class="nav">block 4</section>
<div>
Вот мой код JavaScrpt, в котором я хочу добиться нужного результата:
let tags = document.querySelectorAll('h2,h3')
let nav = document.querySelector('.articles_tags_list_content')
for (let tag of tags) {
let a = document.createElement('a')
a.href = '#'
a.innerHTML = tag.innerHTML
nav.append(a)
a.addEventListener('click', e => {
e.preventDefault()
tag.scrollIntoView({
behavior: 'smooth'
})
})
}
.articles_tags_list_content {
padding: 30px 30px 30px 35px;
background-color: #F2F2F2;
border-radius: 20px;
position: relative;
margin-top: 50px;
height: max-content;
position: fixed;
right: 0;
}
.articles_tags_list_content a {
display: block;
}
<div class="articles_tags_list_content">
</div>
<div>
No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the
No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the
hands of the head of the CS department. No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The
access to this dashboard is usually in the hands of the head of the CS department. hands of the head of the CS department. No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer
service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the hands of the head of the CS department.
<h2>Заголовок 1</h2>
No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the
No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the
hands of the head of the CS department. No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The
access to this dashboard is usually in the hands of the head of the CS department. hands of the head of the CS department. No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer
service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the hands of the head of the CS department.
<h3>Заголовок 2</h3>
No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the
No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the
hands of the head of the CS department. No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The
access to this dashboard is usually in the hands of the head of the CS department. hands of the head of the CS department. No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer
service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the hands of the head of the CS department.
<h2>Заголовок 3</h2>
No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The access to this dashboard is usually in the
hands of the head of the CS department. No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get reports about the customer’s feedback. The
access to this dashboard is usually in the hands of the head of the CS department. No business can thrive without providing exceptional customer services to its clientele. It is why many turn towards the customer service supervisor dashboard to get
reports about the customer’s feedback. The access to this dashboard is usually in the hands of the head of the CS department.
</div>
Ответы (1 шт):
Автор решения: Andrey Semykin
→ Ссылка
Ну вот как-то так (только не забудьте класс active добавить в CSS):
let tags = document.querySelectorAll('h2,h3')
let nav = document.querySelector('.articles_tags_list_content');
for (let tag of tags) {
let a = document.createElement('a')
a.href = '#'
a.innerHTML = tag.innerHTML
nav.append(a)
a.addEventListener('click', e => {
e.preventDefault()
tag.scrollIntoView({
behavior: 'smooth'
})
})
}
window.addEventListener('scroll', onScroll);
function onScroll(){
let refs = nav.querySelectorAll('a');
const windowPosition = { //координаты окна
top: window.pageYOffset,
bottom: window.pageYOffset + document.documentElement.clientHeight
};
const tagPosition = []; // координаты заголовков
for (let tag of tags) {
tagPosition.push({
top: window.pageYOffset + tag.getBoundingClientRect().top,
bottom: window.pageYOffset + tag.getBoundingClientRect().bottom
});
}
for (let i=0; i<tags.length; i++) {
if (tagPosition[i].top < windowPosition.bottom &&
(i<tags.length-1 ? tagPosition[i+1].top > windowPosition.top + 20 : true)){
// 20 - просто для примера, значение надо менять в зависимости от величины шрифта
refs[i].classList.add('active');
} else{
refs[i].classList.remove('active');
}
}
}