работа с DOM js анимация
моих знаний основ на js не достаточно , чтобы реализовать следующее: на странице есть несколько раскрывающихся блоков и нужно добавить небольшую анимацию переворота стрлки на 180 градусов , сейчас я реализовал это так : я добавил обработчик событий на блок в котором есть та самая анимированная стрелка и с помощью метода toggle при клике добавляю и удаляю класс в котором пописан стиль rotate(180 deg) , работает , но только для первого блока (обращался к ним по общему классу) вопрос: как задействовать все эти элемента но чтобы они анимировались все только при клике , писать функцию для каждого точно не вариант , так что я пришел спросить как такое реализуется
Ответы (3 шт):
Это решается самым обычным циклом...
let arrow = document.querySelectorAll('.arrow');
for( let i = 0; i < arrow.length; i++ ) {
arrow[i].addEventListener('click', function() {
this.classList.toggle('rotate');
});
}
.arrow {
display: inline-block;
color: red;
font-size: 100px;
line-height: 100px;
transition: 0.5s;
cursor: pointer;
}
.arrow:hover {
color: #800;
}
.arrow.rotate {
transform: rotate(180deg);
}
<div class="arrow">▼</div>
<div class="arrow">▼</div>
<div class="arrow">▼</div>
<div class="arrow">▼</div>
// Выбираем все стрелки в пределах .block
const arrows = document.querySelectorAll('.block .arrow');
// Перебираем все стрелки и вызываем при клике обработчик
arrows.forEach(arrow => arrow.onclick = arrowClickHandle);
// Обработчик
function arrowClickHandle() {
// Выбираем родительский .block
const block = this.closest('.block');
// Выбираем блок .content
const content = block.querySelector('.content');
// Проверяем есть ли активный класс у элемента
const isActive = block.classList.contains('active');
// Переключаем класс
block.classList.toggle('active');
// Анимируем появление/исчезновение блока
gsap.fromTo(content, {
height: isActive ? content.scrollHeight : 0
},{
duration: 0.5,
height: isActive ? 0 : content.scrollHeight
});
}
.block {
margin-bottom: 20px;
font-family: Arial;
}
.arrow {
display: inline-block;
color: #2ecc71;
font-size: 30px;
line-height: 30px;
user-select: none;
transition: transform 0.5s, color 0.5s;
cursor: pointer;
transform: rotate(-90deg);
}
.content {
width: 50%;
height: 0;
overflow: hidden;
}
.block.active .arrow {
transform: rotate(0deg);
color: #e74c3c;
}
.block.active .content {
height: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js"></script>
<div class="block">
<div class="arrow">▼</div>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda quos, tempore in harum. Officiis nisi aliquam nemo consequuntur, illo, quidem quos eaque vitae velit ratione repellat reprehenderit officia asperiores in.
</div>
</div>
<div class="block active">
<div class="arrow">▼</div>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda quos, tempore in harum. Officiis nisi aliquam nemo consequuntur, illo, quidem quos eaque vitae velit ratione repellat reprehenderit officia asperiores in.
</div>
</div>
<div class="block">
<div class="arrow">▼</div>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda quos, tempore in harum. Officiis nisi aliquam nemo consequuntur, illo, quidem quos eaque vitae velit ratione repellat reprehenderit officia asperiores in.
</div>
</div>
Для решения вашей задачи JavaScript не требуется вообще! Всё можно сделать нативным HTML/CSS:
details {
position: relative;
margin-bottom: 0.5rem;
min-height: 1rem;
max-height: 3rem;
transition: min-height 0.15s linear, max-height 0.5s linear;
will-change: max-height;
overflow: hidden;
}
details summary {
display: inline-block;
padding-left: 1.5em;
transition: color 0.12s;
}
details summary span {
border-bottom: 1px currentColor dotted;
}
details summary::before {
content: "";
left: 0;
top: 1px;
position: absolute;
background: url("data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjM0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIzNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNOC41OSAxNi4zNGw0LjU4LTQuNTktNC41OC00LjU5TDEwIDUuNzVsNiA2LTYgNnoiLz48L3N2Zz4=") no-repeat 50% 50%/1em 1em;
width: 1em;
height: 1em;
transition: transform 0.1s linear;
}
details summary:hover {
color: #d06c6c;
}
details summary ~ * {
padding-left: 1.5em;
opacity: 0;
transition: opacity 0.15s linear;
}
details[open] {
min-height: 2em;
max-height: 20em;
}
details[open] summary {
color: #d06c6c;
}
details[open] summary ~ * {
opacity: 1;
}
details[open] summary:before {
transform: rotate(90deg);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/godlike.css/3.7.2/godlike.min.css" rel="stylesheet">
<details>
<summary tabindex="1"><span>Кликни на меня!</span></summary>
<p>Я открываюсь нативно без JavaScript и библиотек для анимаций!</p>
</details>
<details>
<summary tabindex="2"><span>В меня можно поместить картинку!</span></summary>
<p><img src="//picsum.photos/100/100/?random" alt="Картинка"></p>
</details>
<details>
<summary tabindex="3"><span>И моя разметка семантически верная для поисковиков!</span></summary>
<p><b>Lorem Ipsum</b> is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever <i>since the 1500s</i>, when an unknown printer took a galley of type and scrambled it to make a type...</p>
</details>
Более того, используя семантически верные теги мы можем улучшить видимость нашей вёрстки для поисковиков.
Также описанные предыдущими ораторами подходы полностью императивны, но в современной разработке хорошим тоном является использование декларативного подхода.