CSS исчезает с обратным вызовом JS, чтобы установить отображение CSS при завершении прерывания анимации

Изменить: JSFiddle по запросу: https://jsfiddle.net/5anz0kgt/1/

Редактировать 2: кажется, что прерывание анимации на самом деле связано с порядком элементов... Если новый слой banenr находится поверх старого, анимация будет плавной. Если новый баннер находится внизу, анимация будет прерывистой. Таким образом, возникает новый вопрос, почему и как я могу это исправить?

В настоящее время я заканчиваю небольшой баннер, и у меня проблемы с анимацией.

Изначально у меня были только следующие функции, управляющие видимостью баннера и анимацией (которые работали):

function fadeOut(el){
    el.style.transition = "opacity 0.5s linear 0s";
    el.style.opacity = 0;
}

function fadeIn(el){
    el.style.transition = "opacity 0.5s linear 0s";
    el.style.opacity = 1;
}

Но я быстро заметил, что это (конечно) сделало кнопки на баннерах ненажимаемыми из-за наложения элементов.

Поэтому я решил установить display: none для невидимых слоев баннера. Для затухания я просто добавил

el.style.display = "";

но для затухания мне нужно было убедиться, что анимация CSS завершена, прежде чем я смогу скрыть слой. Поэтому я добавил (любезно предоставлено http://davidwalsh.name/css-animation-callback):

var transitionEvent = whichTransitionEvent(el);
    transitionEvent && el.addEventListener(transitionEvent, function() {
        el.style.display = "none";
    });

до конца функции fadeOut(). Проблема сейчас в том, что переход теперь очень резкий (большую часть времени - кажется, работает небольшое подмножество времени).

Работает только код отображения в fadeIn(), указывая на изменения в fadeOut() как на проблему. Однако, наблюдая в firebug, я вижу, что изменения отображения вступают в игру только после завершения анимации непрозрачности.

Как я могу гарантировать, что мой код отображения не прерывает анимацию, или, альтернативно, как еще я могу решить проблему наложения элементов?


person rscarson    schedule 29.06.2015    source источник
comment
Можете ли вы опубликовать jsfiddle, чтобы мы могли возиться с вашим HTML/JS?   -  person Prusprus    schedule 29.06.2015
comment
jsfiddle.net/5anz0kgt/1 Ну вот!   -  person rscarson    schedule 29.06.2015


Ответы (1)


Итак, я внимательно изучил ваш код. Я создал исправление для проблемы с переходом, установив z-index в функциях fadeOut/fadeIn, чтобы гарантировать, что правильный элемент виден сверху независимо от стека.

Кроме того, есть еще один баг. Цикл анимации продолжается независимо от пользовательского ввода, поэтому взаимодействие пользователя и автоматический цикл борются друг с другом, чтобы обойти это, вы можете использовать clearInterval для остановки функции setInterval (в частности, цикла анимации в этом случае).

Вот jsfiddle, демонстрирующий оба вышеуказанных https://jsfiddle.net/Lmtpw6yq/3/. что я добавил еще одну функцию select_banner, которая вызывается onClick вместо активации_баннера, чтобы можно было прервать цикл анимации:

// stores ID of current animation loop setInterval so can interrupt
var animationTick;

function select_banner(banner_id) {
   if (animationTick) {
       // stop animation loop
       window.clearInterval(animationTick);
    }
    activate_banner(banner_id);
    animation_loop();
}

animationTick устанавливается на идентификатор текущего тика setInterval в функции цикла анимации, вызывая setInterval следующим образом:

function animation_loop() {
    animationTick = setInterval(function(){
        ... 
    }, 3000);
}

Последнее замечание — циклы while. Они работают, но ужасно неэффективны, во-первых, вы многократно используете getElementById для поиска одних и тех же элементов, заставляя ваши js снова и снова пересекать dom без необходимости. Кроме того, ваше условие разрыва циклов while (т.е. поиск несуществующего идентификатора) заставляет js проверять идентификатор буквально каждого узла в документе, что далеко не идеально.

Поскольку количество баннеров не меняется, было бы лучше найти все баннеры один раз и сохранить ссылки на них в массиве в начале, а затем использовать циклы for для перебора массива вместо циклов while.

person Richard Green    schedule 29.06.2015
comment
Добавлен JSFiddle в операцию - person rscarson; 29.06.2015
comment
Большое тебе спасибо! Ты рок-звезда :D - person rscarson; 30.06.2015