При наводе на блок останавливать функцию в которой есть setTimeout, а при выходе мышки из блока, заново запускать функцию
Есть блок, в котором есть 5 блоков и 5 картинок. В каждом блоке есть анимация (линия прогресса) которая заполняется до 100%. Сразу активный блок - первый. Когда у первого блока заполняется шкала прогресса, активный блок становится второй и меняется картинка, а так же запускается шкала прогресса у второго блока. После второго блока, по такой же технологии запускается третий блок, потом четвертый и потом пятый, а после пятого снова первый и так по кругу. Шкала прогресса сделана через анимацию CSS, а активность блоков и смена картинок через JS (функция активности). Но так же нужно, чтобы при новоде на блок, функция активности останавливалась и активный становился тот блок, на который я навел мышкой, а так же запускалась другая анимация CSS (шкала прогресса доходила до 100% и все, не нужно чтобы на другой блок переходило), но когда мышь уберу с этого блока, нужно чтобы заново началась та функция активности и аниамация CSS с первого блока. Очень надеюсь что все понятно написал, но если нет, то задавайте вопросы, на все отвечу. И да, код JS не очень хороший, но я еще только учусь и пишу как умею
const imgHover = () => {
const productImg = document.querySelectorAll('.product-img'); //блоки с картинкой
const productImg1 = document.querySelector('.product-img_1');
const productImg2 = document.querySelector('.product-img_2');
const productImg3 = document.querySelector('.product-img_3');
const productImg4 = document.querySelector('.product-img_4');
const productImg5 = document.querySelector('.product-img_5');
const itemNum = document.querySelectorAll('.product__list_item'); // все блоки под одним классом
const productListItemTextProgressGrad = document.querySelectorAll('.product__list_item_text_progress_grad'); // шкала прогресса
const itemNum1 = document.querySelector('.item-num-1'); //блоки на которые нужно наводить по отдельности
const itemNum2 = document.querySelector('.item-num-2');
const itemNum3 = document.querySelector('.item-num-3');
const itemNum4 = document.querySelector('.item-num-4');
const itemNum5 = document.querySelector('.item-num-5');
//функция которая делает активнсть блоков при наводе на них и убирает прошлую анимацию и подставляет новую
function prov(one, two, three) {
productListItemTextProgressGrad.forEach((item, ind) => {
item.style.animation = "none";
if(ind == one) {
item.style.animation = "product_progress_one ease-out 25s";
}
});
itemNum.forEach(item => {
item.classList.remove('active');
})
productImg.forEach(el => {
el.classList.remove('active');
})
two.classList.add('active');
three.classList.add('active');
}
// функция которая запускает автоматически смену активности при заполнении шкалы
const framesImg = () => {
productListItemTextProgressGrad.forEach((item, ind) => {
item.style.animation = "product_progress ease-out 25s";
});
itemNum5.classList.remove('active');
itemNum1.classList.add('active');
productImg5.classList.remove('active');
productImg1.classList.add('active');
setInterval(() => {
itemNum5.classList.remove('active');
itemNum1.classList.add('active');
productImg5.classList.remove('active');
productImg1.classList.add('active');
}, 25000);
setTimeout(() => {
itemNum1.classList.remove('active');
itemNum2.classList.add('active');
productImg1.classList.remove('active');
productImg2.classList.add('active');
setInterval(() => {
itemNum1.classList.remove('active');
itemNum2.classList.add('active');
productImg1.classList.remove('active');
productImg2.classList.add('active');
}, 25000);
}, 5000);
setTimeout(() => {
itemNum2.classList.remove('active');
itemNum3.classList.add('active');
productImg2.classList.remove('active');
productImg3.classList.add('active');
setInterval(() => {
itemNum2.classList.remove('active');
itemNum3.classList.add('active');
productImg2.classList.remove('active');
productImg3.classList.add('active');
}, 25000);
}, 10000);
setTimeout(() => {
itemNum3.classList.remove('active');
itemNum4.classList.add('active');
productImg3.classList.remove('active');
productImg4.classList.add('active');
setInterval(() => {
itemNum3.classList.remove('active');
itemNum4.classList.add('active');
productImg3.classList.remove('active');
productImg4.classList.add('active');
}, 25000);
}, 15000);
setTimeout(() => {
itemNum4.classList.remove('active');
itemNum5.classList.add('active');
productImg4.classList.remove('active');
productImg5.classList.add('active');
setInterval(() => {
itemNum4.classList.remove('active');
itemNum5.classList.add('active');
productImg4.classList.remove('active');
productImg5.classList.add('active');
}, 25000);
}, 20000);
}
framesImg();
// наведение на каждый блок
itemNum.forEach(elem => {
elem.addEventListener('mouseover', (e) => {
if(e.target.classList.contains('product__list_item_one')) {
prov(0, productImg1, itemNum1);
} else if (e.target.classList.contains('product__list_item_two')) {
prov(1, productImg2, itemNum2);
} else if (e.target.classList.contains('product__list_item_three')) {
prov(2, productImg3, itemNum3);
} else if (e.target.classList.contains('product__list_item_four')) {
prov(3, productImg4, itemNum4);
} else if (e.target.classList.contains('product__list_item_five')) {
prov(4, productImg5, itemNum5);
}
});
});
}
imgHover()
.product__list {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.product__list_wrapper {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.product__list_wrapper-hidden {
position: relative;
display: none;
}
.product__list_column-1 {
max-width: 581px;
}
.product__list_column-2 {
margin-left: 100px;
max-width: 500px;
}
.product__list_column-text-2 {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
max-width: 467px;
}
.product__list_column--img {
width: 500px;
height: 872px;
margin-top: -200px;
background-size: cover;
background-position: center;
overflow: hidden;
}
.product__list-subtitle::before {
content: "";
display: inline-block;
vertical-align: middle;
width: 30px;
height: 1px;
background-color: #342F3F;
margin-right: 10px;
}
.product__list-title {
margin: 0 0 0 -5px;
max-width: 598px;
}
.product__list_item {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
opacity: .4 !important;
transition: 0.5s;
}
.product__list_item_text_progress {
height: 2px;
max-width: 570px;
width: 100%;
background: #484848;
}
.product__list_item_text_progress_grad {
background: #FAD4E7;
height: 100%;
z-index: 99;
width: 0%;
}
.product__list_item_text_progress_grad_one {
animation: product_progress ease-out 25s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.product__list_item_text_progress_grad_two {
animation: product_progress ease-out 25s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-delay: 5s;
}
.product__list_item_text_progress_grad_three {
animation: product_progress ease-out 25s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-delay: 10s;
}
.product__list_item_text_progress_grad_four {
animation: product_progress ease-out 25s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-delay: 15s;
}
.product__list_item_text_progress_grad_five {
animation: product_progress ease-out 25s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-delay: 20s;
}
@keyframes product_progress {
0% {
width: 0;
}
20% {
width: 100%;
}
20.00000001% {
width: 0%;
}
100% {
width: 0%;
}
}
@keyframes product_progress_one {
0% {
width: 0;
}
100% {
width: 100%;
}
}
.product-img {
display:none;
transition: 1s;
}
.active.product-img {
display:block;
transition: 1s;
}
.active.product__list_item {
opacity: 1 !important;
-webkit-transition: opacity 0.8s linear;
transition: opacity 0.8s linear;
color: #FAD4E7;
transition: 0.5s;
}
.active.product__list_item>div>.product__list_item-number{
color: #FAD4E7;
transition: 0.5s;
}
.product__list_item-num {
line-height: 7px;
width: 85px;
margin-right: 20px;
}
.product__list_item-number {
margin-top: -46px;
}
.product__list_item-num img {
max-width: initial;
}
.product__list_item-text {
max-width: 475px;
}
<section class="product__list padding_top_130 padding_bottom_150 padding_top_78_1440">
<div class="container container_two">
<div class="product__list_wrapper">
<div class="product__list_column product__list_column-1">
<p class="product__list-subtitle padding_bottom_10 p2_black">мы работаем с вами, а не для вас</p>
<h2 class="product__list-title padding_title_60 h2_black">Направления работы</h2>
<div class="product__list_item item-num-1 _anim-items padding_bottom_40 active product__list_item_one">
<div class="product__list_item-num product__list_item_one">
<p class="p7 product__list_item-number product__list_item_one">01.</p>
</div>
<div class="product__list_item-text product__list_item_one">
<p class="h3_black_300 padding_bottom_20 width_103 width_480_768 product__list_item_one">Создание сайтов</p>
<p class="p3_black padding_bottom_20 width_103 product__list_item_one">Разработка удобных для посетителя, элегантных и доступных для поиска сайтов, их сопровождение — это то, что вы получите при работе с нами.</p>
<!-- <progress class="progress" value="0" max="100">
<span class="percent">0</span>%
</progress> -->
<div class='product__list_item_text_progress product__list_item_one'><div class='product__list_item_text_progress_grad product__list_item_text_progress_grad_one product__list_item_one'></div></div>
</div>
</div>
<div class="product__list_item item-num-2 _anim-items padding_bottom_40 product__list_item_two">
<div class="product__list_item-num product__list_item_two">
<p class="p7 product__list_item-number product__list_item_two">02.</p>
</div>
<div class="product__list_item-text product__list_item_two">
<p class="h3_black_300 padding_bottom_20 width_103 width_480_768 product__list_item_two">Cоздание и SEO-продвижение сайтов</p>
<p class="p3_black padding_bottom_20 width_103 product__list_item_two">Умеем планировать разумную маркетинговую компанию, которая соответствует вашему бюджету при этом достигает максимальной эффективности.</p>
<!-- <progress class="progress" value="0" max="100">
<span class="percent">0</span>%
</progress> -->
<div class='product__list_item_text_progress product__list_item_two'><div class='product__list_item_text_progress_grad product__list_item_text_progress_grad_two product__list_item_two'></div></div>
</div>
</div>
<div class="product__list_item item-num-3 _anim-items padding_bottom_40 product__list_item_three">
<div class="product__list_item-num product__list_item_three">
<p class="p7 product__list_item-number product__list_item_three">03.</p>
</div>
<div class="product__list_item-text product__list_item_three">
<p class="h3_black_300 padding_bottom_20 width_103 width_480_768 product__list_item_three">SMM-маркетинг</p>
<p class="p3_black padding_bottom_20 width_103 product__list_item_three">Быстрый способ привлечения це левых посетителей на сайт. Заказывая контекстную рекламу у нас, вы платите за результат – лояльных посетителей.</p>
<!-- <progress class="progress" value="0" max="100">
<span class="percent">0</span>%
</progress> -->
<div class='product__list_item_text_progress product__list_item_three'><div class='product__list_item_text_progress_grad product__list_item_text_progress_grad_three product__list_item_three'></div></div>
</div>
</div>
<div class="product__list_item item-num-4 _anim-items padding_bottom_40 product__list_item_four">
<div class="product__list_item-num product__list_item_four">
<p class="p7 product__list_item-number product__list_item_four">04.</p>
</div>
<div class="product__list_item-text margin_10_1440 product__list_item_four">
<p class="h3_black_300 padding_bottom_20 width_103 width_480_768 product__list_item_four">Контекстная и таргетированная реклама</p>
<p class="p3_black padding_bottom_20 width_103 width_103_500 product__list_item_four">Контекстная реклама нацелена на максимальное привлечение клиентов к вашему бизнесу или продукту. Она привлекает лояльных потребителей.</p>
<!-- <progress class="progress" value="0" max="100">
<span class="percent">0</span>%
</progress> -->
<div class='product__list_item_text_progress product__list_item_four'><div class='product__list_item_text_progress_grad product__list_item_text_progress_grad_four product__list_item_four'></div></div>
</div>
</div>
<div class="product__list_item item-num-5 _anim-items padding_bottom_40 product__list_item_five">
<div class="product__list_item-num product__list_item_five">
<p class="p7 product__list_item-number product__list_item_five">05.</p>
</div>
<div class="product__list_item-text product__list_item_five">
<p class="h3_black_300 padding_bottom_20 width_103 width_480_768 product__list_item_five">Дизайн</p>
<p class="p3_black padding_bottom_20 width_103 product__list_item_five">Предлагаем широкий спектр услуг, от web-дизайна до графического дизайна каталогов и брошюр, которые помогут вам создать корпоративный имидж.</p>
<!-- <progress class="progress" value="0" max="100">
<span class="percent">0</span>%
</progress> -->
<div class='product__list_item_text_progress product__list_item_five'><div class='product__list_item_text_progress_grad product__list_item_text_progress_grad_five product__list_item_five'></div></div>
</div>
</div>
</div>
<div class="product__list_column-2">
<div class="product__list_column--img margin_bottom_40">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/assets/img/jpg/img-hover1.jpg" alt="img" class="product-img product-img_1 active">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/assets/img/jpg/img-hover2.jpg" alt="img" class="product-img product-img_2">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/assets/img/jpg/img-hover3.jpg" alt="img" class="product-img product-img_3">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/assets/img/jpg/img-hover4.jpg" alt="img" class="product-img product-img_4">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/assets/img/jpg/img-hover5.jpg" alt="img" class="product-img product-img_5">
</div>
<div class="product__list_wrapper list_wrapper-hidden">
<div class="grad-line"></div>
<div class="product__list_column-text-2">
<p class="h3_black_300 padding_bottom_20">Мы работаем с вами, а не для вас!</p>
<p class="col-text-2 padding_bottom_10 p3_black padding_18_1440">Агентство интернет-рекламы полного цикла – так можно охарактеризовать работу нашей компании. Действительно, в реалиях 20-х годов нового тысячелетия об успехе онлайн можно говорить только при условии, что рычаги влияния применяются комплексно и системно. Как раз поэтому предполагается многовекторная работа
</p>
<p class="col-text-2 padding_bottom_10 p3_black padding_30_1440">Агентство интернет-маркетинга «Веб Фокус» – это воплощение проекта в жизнь с четким пониманием особенностей того или иного бизнеса. Считаем этот момент ключевым, ведь без учета сезонности, среднего чека и других нюансов раскрутка превращается в сумбурный набор движений, от которых толку немного.
</p>
<p class="col-text-2 padding_bottom_10 p3_black">Только точечные удары по аудитории, которые заставляют офисный телефон буквально разрываться от звонков! О Вас не знают? Исправим! Хотите увеличить продажи или улучшить репутацию? Будет сделано! Больше, чем среднестатистическое агентство разработки сайтов!
</p>
</div>
</div>
</div>
</div>
<div class="product__list_wrapper-hidden gradient">
<div class="grad_line-text--wrapper">
<div class="product__list_wrapper-text">
<div class="grad-line"></div>
<div class="product__list_column-text-2">
<p class="h3_black_300 padding_bottom_20 padding_bottom_21_500">Мы работаем с вами, а не для вас!</p>
<p class="col-text-2 col-text-2--p padding_bottom_10 p3_black">Агентство интернет-рекламы полного цикла – так можно охарактеризовать работу нашей компании. Действительно, в реалиях 20-х годов нового тысячелетия об успехе онлайн можно говорить только при условии, что рычаги влияния применяются комплексно и системно. Как раз поэтому предполагается многовекторная работа</p>
<p class="col-text-2 padding_bottom_10 p3_black">Агентство интернет-маркетинга «Веб Фокус» – это воплощение проекта в жизнь с четким пониманием особенностей того или иного бизнеса. Считаем этот момент ключевым, ведь без учета сезонности, среднего чека и других нюансов раскрутка превращается в сумбурный набор движений, от которых толку немного.</p>
<p class="col-text-2 padding_bottom_10 p3_black">Только точечные удары по аудитории, которые заставляют офисный телефон буквально разрываться от звонков! О Вас не знают? Исправим! Хотите увеличить продажи или улучшить репутацию? Будет сделано! Больше, чем среднестатистическое агентство разработки сайтов! </p>
</div>
</div>
</div>
</div>
</div>
</section>
Ответы (2 шт):
Все оказалось куда проще. При наведении на блок, я очищал все setTimeout, а так же проверял сработали ли уже setTimeout, и если да, то значит были созданы уже setInterval, а значит очищал их тоже. А когда мышь убирал с блока, то снова запускал эту функцию
Да, код кривой, его можно оптимизировать, но в данный момент мне нужен был просто рабочий код, а писать сразу красиво я еще не умею:(
Вот код который получился:
const imgHover = () => {
const productImg = document.querySelectorAll('.product-img');
const productImg1 = document.querySelector('.product-img_1');
const productImg2 = document.querySelector('.product-img_2');
const productImg3 = document.querySelector('.product-img_3');
const productImg4 = document.querySelector('.product-img_4');
const productImg5 = document.querySelector('.product-img_5');
const itemNum = document.querySelectorAll('.product__list_item');
const productListItemTextProgressGrad = document.querySelectorAll('.product__list_item_text_progress_grad');
const productListItemTextProgressGradOne = document.querySelector('.product__list_item_text_progress_grad_one');
const productListItemTextProgressGradTwo = document.querySelector('.product__list_item_text_progress_grad_two');
const productListItemTextProgressGradThree = document.querySelector('.product__list_item_text_progress_grad_three');
const productListItemTextProgressGradFour = document.querySelector('.product__list_item_text_progress_grad_four');
const productListItemTextProgressGradFive = document.querySelector('.product__list_item_text_progress_grad_five');
const itemNum1 = document.querySelector('.item-num-1');
const itemNum2 = document.querySelector('.item-num-2');
const itemNum3 = document.querySelector('.item-num-3');
const itemNum4 = document.querySelector('.item-num-4');
const itemNum5 = document.querySelector('.item-num-5');
function prov(one, two, three, four) {
productListItemTextProgressGrad.forEach(item => {
item.style.animation = 'none';
});
itemNum.forEach(item => {
item.classList.remove('active')
});
productImg.forEach(item => {
item.classList.remove('active')
});
four.style.animation = "product_progress_one ease-out 5s forwards";
itemNum.forEach(item => {
item.classList.remove('active');
})
productImg.forEach(el => {
el.classList.remove('active');
})
two.classList.add('active');
three.classList.add('active');
}
const framesImg = () => {
timerOne = setTimeout(() => {
productListItemTextProgressGradOne.style.animation = 'product_progress linear 25s infinite'
itemNum5.classList.remove('active');
itemNum1.classList.add('active');
productImg5.classList.remove('active');
productImg1.classList.add('active');
itemNum1.classList.add('one');
intervalOne = setInterval(() => {
productListItemTextProgressGradOne.style.animation = 'product_progress linear 25s infinite'
itemNum5.classList.remove('active');
itemNum1.classList.add('active');
productImg5.classList.remove('active');
productImg1.classList.add('active');
}, 25000);
}, 0);
timerTwo = setTimeout(() => {
productListItemTextProgressGradTwo.style.animation = 'product_progress linear 25s infinite'
itemNum1.classList.remove('active');
itemNum2.classList.add('active');
productImg1.classList.remove('active');
productImg2.classList.add('active');
itemNum2.classList.add('two');
intervalTwo = setInterval(() => {
productListItemTextProgressGradTwo.style.animation = 'product_progress linear 25s infinite'
itemNum1.classList.remove('active');
itemNum2.classList.add('active');
productImg1.classList.remove('active');
productImg2.classList.add('active');
}, 25000);
}, 5000);
timerThree = setTimeout(() => {
productListItemTextProgressGradThree.style.animation = 'product_progress linear 25s infinite'
itemNum2.classList.remove('active');
itemNum3.classList.add('active');
productImg2.classList.remove('active');
productImg3.classList.add('active');
itemNum3.classList.add('three');
intervalThree = setInterval(() => {
itemNum3.classList.add('three');
productListItemTextProgressGradThree.style.animation = 'product_progress linear 25s infinite'
itemNum2.classList.remove('active');
itemNum3.classList.add('active');
productImg2.classList.remove('active');
productImg3.classList.add('active');
}, 25000);
}, 10000);
timerFour = setTimeout(() => {
productListItemTextProgressGradFour.style.animation = 'product_progress linear 25s infinite'
itemNum3.classList.remove('active');
itemNum4.classList.add('active');
productImg3.classList.remove('active');
productImg4.classList.add('active');
itemNum4.classList.add('four');
intervalFour = setInterval(() => {
itemNum4.classList.add('four');
productListItemTextProgressGradFour.style.animation = 'product_progress linear 25s infinite'
itemNum3.classList.remove('active');
itemNum4.classList.add('active');
productImg3.classList.remove('active');
productImg4.classList.add('active');
}, 25000);
}, 15000);
timerFive = setTimeout(() => {
productListItemTextProgressGradFive.style.animation = 'product_progress linear 25s infinite'
itemNum4.classList.remove('active');
itemNum5.classList.add('active');
productImg4.classList.remove('active');
productImg5.classList.add('active');
itemNum5.classList.add('five');
intervalFive = setInterval(() => {
itemNum5.classList.add('five');
productListItemTextProgressGradFive.style.animation = 'product_progress linear 25s infinite'
itemNum4.classList.remove('active');
itemNum5.classList.add('active');
productImg4.classList.remove('active');
productImg5.classList.add('active');
}, 25000);
}, 20000);
}
framesImg();
itemNum.forEach(elem => {
elem.addEventListener('mouseover', (e) => {
if (itemNum1.classList.contains('one')) {
clearInterval(intervalOne);
}
if (itemNum2.classList.contains('two')) {
clearInterval(intervalTwo);
}
if (itemNum3.classList.contains('three')) {
clearInterval(intervalThree);
}
if (itemNum4.classList.contains('four')) {
clearInterval(intervalFour);
}
if (itemNum5.classList.contains('five')) {
clearInterval(intervalFive);
}
clearTimeout(timerOne);
clearTimeout(timerTwo);
clearTimeout(timerThree);
clearTimeout(timerFour);
clearTimeout(timerFive);
if(e.target.classList.contains('product__list_item_one')) {
prov(0, productImg1, itemNum1, productListItemTextProgressGradOne);
} else if (e.target.classList.contains('product__list_item_two')) {
prov(1, productImg2, itemNum2, productListItemTextProgressGradTwo);
} else if (e.target.classList.contains('product__list_item_three')) {
prov(2, productImg3, itemNum3, productListItemTextProgressGradThree);
} else if (e.target.classList.contains('product__list_item_four')) {
prov(3, productImg4, itemNum4, productListItemTextProgressGradFour);
} else if (e.target.classList.contains('product__list_item_five')) {
prov(4, productImg5, itemNum5, productListItemTextProgressGradFive);
}
});
elem.addEventListener('mouseout', (e) => {
productListItemTextProgressGrad.forEach(item => {
item.style.animation = 'none';
});
itemNum.forEach(item => {
item.classList.remove('active')
});
productImg.forEach(item => {
item.classList.remove('active')
});
framesImg();
});
});
}
const productList = document.querySelector('.product__list');
let box = productList.getBoundingClientRect();
let isRun = false;
window.addEventListener('scroll', () => {
if (window.pageYOffset >= box.top - document.documentElement.clientHeight + 250 && !isRun) {
imgHover()
isRun = true;
}
});