Я пытаюсь создать маленькое крутое микро-взаимодействие, но у меня небольшая проблема.
document.querySelector('button').onclick = function(){
const
items = document.querySelector('nav').children
if (items[0].getBoundingClientRect().top >= document.querySelector('nav').getBoundingClientRect().bottom){
// start showing elements, starting from the left side
for (let i = 0; i < items.length; i++){
setTimeout(function(){
items[i].style.transform = 'translateY(0)'
}, i * 200)
}
} else {
// start hiding elements, starting from the right side
for (let i = 0; i < items.length; i++){
setTimeout(function(){
items[i].style.transform = 'translateY(100%)'
}, (items.length-1 - i) * 200)
}
}
}
button {
width: 100px;
height: 50px;
}
nav {
width: 50vw;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
background: red;
}
nav > a {
width: 100%;
height: 50px;
transition: .5s transform;
transform: translateY(100%);
opacity: 0.5;
background: lime;
}
<button>Toggle</button>
<nav>
<a href=''></a>
<a href=''></a>
<a href=''></a>
<a href=''></a>
</nav>
Если вы включите слишком быстро последовательность, некоторые элементы будут в конечном итоге отображаться, тогда как другие в конечном итоге будут скрыты.
Это связано с тем, что существуют ожидающие setTimeouts
, которые еще должны быть выполнены при выпуске нового набора setTimeouts
.
Очевидно, что есть способы обойти эту проблему, например, не отменить порядоканимации, ожидая, пока анимация полностью не закончится, прежде чем разрешить обратное, и так далее, но я бы предпочел не идти на такие компромиссы.
Я пытался использовать и переключать глобальное логическое значение в if
else
блоков, а затем с помощью дополнительного оператора if/else
в блоке setTimeout
, но это не сработало.
Я также пытался установить задержки transition
на лету перед применением нового transform
значений, вместо того, чтобы полагаться на setTimeout
, который не работал.
Есть ли простой способ отменить или игнорировать любые ожидающие setTimeouts
из старше цикла?