Переходы CSS не работают при назначении JavaScript

У меня возникает серьезная головная боль, пытающаяся применить переходы CSS3 к слайд-шоу через JavaScript.

В основном JavaScript получает все слайды в слайд-шоу и применяет классы CSS к правильным элементам, чтобы придать приятный анимированный эффект, если поддержка CSS3 не поддерживается, он будет применять стили без перехода.

Теперь моя "маленькая" проблема. Все работает, как и ожидалось, все слайды получают правильные стили, код работает без ошибок (пока). Но указанные переходы не работают, даже если правильные стили применяются. Кроме того, стили и переходы работают, когда я сам применяю их через инспектора.

Поскольку я не мог найти логическое объяснение, я подумал, что кто-то здесь может ответить на него, пожалуйста, пожалуйста?

Я собрал небольшой пример того, что код сейчас: http://g2f.nl/38rvma Или используйте JSfiddle (без изображений): http://jsfiddle.net/5RgGV/1/

Ответ 1

Чтобы сделать работу transition, должно произойти три вещи.

  • элемент должен иметь явное определение свойства, в этом случае: opacity: 0;
  • элемент должен иметь определенный переход: transition: opacity 2s;
  • необходимо установить новое свойство: opacity: 1

Если вы назначаете 1 и 2 динамически, как и в вашем примере, должна быть задержка до 3, чтобы браузер мог обработать запрос. Причина, по которой он работает, когда вы отлаживаете это, заключается в том, что вы создаете эту задержку, пройдя через нее, предоставляя время браузера для обработки. Дайте задержку для назначения .target-fadein:

window.setTimeout( function() { slides[targetIndex].className += " target-fadein"; }, 100 ); 

Или поместите .target-fadein-begin в свой HTML напрямую, чтобы он разобрался с загрузкой и будет готов к переходу.

Добавление transition к элементу не является тем, что запускает анимацию, изменяя свойство.

Демо: http://jsfiddle.net/ThinkingStiff/QNnnQ/

HTML:

<div id="fade1" class="fadeable">fade 1 - works</div>
<div id="fade2">fade 2 - doesn't work</div>
<div id="fade3">fade 3 - works</div>

CSS:

.fadeable {
    opacity: 0;
}

.fade-in {
    opacity: 1;
    transition:             opacity 2s;
        -moz-transition:    opacity 2s;
        -ms-transition:     opacity 2s;
        -o-transition:      opacity 2s;
        -webkit-transition: opacity 2s;
}

Script:

//works
document.getElementById( 'fade1' ).className += ' fade-in';

//doesn't work
document.getElementById( 'fade2' ).className = 'fadeable';
document.getElementById( 'fade2' ).className += ' fade-in';

//works
document.getElementById( 'fade3' ).className = 'fadeable';
window.setTimeout( function() {

    document.getElementById( 'fade3' ).className += ' fade-in';

}, 100);

Ответ 3

Обманите механизм компоновки!

function finalizeAndCleanUp (event) {
    if (event.propertyName == 'opacity') {
        this.style.opacity = '0'
        this.removeEventListener('transitionend', finalizeAndCleanUp)
    }
}
element.style.transition = 'opacity 1s'
element.style.opacity = '0'
element.addEventListener('transitionend', finalizeAndCleanUp)
// next line important but there no need to store the value
element.offsetHeight
element.style.opacity = '1'

Как уже упоминалось, transition работает путем интерполяции из состояния A в состояние B. Если ваш script вносит изменения в одну и ту же функцию, механизм компоновки не может отделяться от состояния A и начинается B. Если вы не дадите ему намек.

Поскольку нет официального способа сделать намек, вы должны полагаться на побочные эффекты некоторых функций. В этом случае .offsetHeight getter, который неявно заставляет механизм компоновки останавливаться, оценивать и вычислять все установленные свойства и возвращать значение. Как правило, этого следует избегать при оценке производительности, но в нашем случае это именно то, что необходимо: консолидация состояния.

Код очистки добавлен для полноты.

Ответ 4

Некоторые люди спрашивают, почему происходит задержка. Стандарт хочет разрешить сразу несколько переходов, известных как событие изменения стиля (например, элемент замирает в то же время, когда он вращается в представлении). К сожалению, он не определяет явный способ группировки переходов, которые вы хотите совершить одновременно. Вместо этого он позволяет браузерам произвольно выбирать, какие переходы происходят одновременно с тем, насколько они выходят друг от друга. Большинство браузеров, похоже, используют свою частоту обновления, чтобы определить это время.

Вот стандарт, если вы хотите получить более подробную информацию: http://dev.w3.org/csswg/css-transitions/#starting