Как реализовать «поочередное» выполнение кода?

Доброго времени суток уважаемый хабражители. Сам я кодер неопытный и столкнулся со следующей проблемой: хочу выполнить анимацию (transition прописал в css), но природа современных движков рендеринга (многозадачные, выполняя одну строку уже работают над другой… или как правильно сказать) не позволяет мне это сделать.

Пример:
$('.nextMonthArrow').click(function() {
	createCalendar(1, "nextMonth"); // 60ms на создание
	var content = $('.calendarBody').html();
	$('.calendarBody').html('<div id="calendarTransform">'+content+'</div>');
	setTimeout(function(){$('#calendarTransform').css({'margin-left': -step, 'width': step*2})}, 1);
});


Буквально случайный образом я решил использовать setTimeout и оказалось работает даже при одной милисекунде. Но если убрать таймаут то анимации нет. Насколько я понимаю браузер еще не успел прочитать css transition но margin из js уже обработал (.js подключен намного позже .css). Почему спасает setTimeout? Какие есть еще варианты?

Нет — я не хочу использовать $.animate();
Есть ли у кого нибудь сниппет кроссбраузерной обработки Transition Event?
  • Вопрос задан
  • 4534 просмотра
Решения вопроса 1
Выше было правильно сказано, попробую дополнить.

Вы создаете ДОМ(calenderTrasform) и присваиваете margin-left / width в одном и том же event tick. И грубо говоря, ваш новый html приходит в live DOM уже с margin-left / width — то есть, браузер не фиксирует эти изменения, поэтому и не вызывается transition. А используя setTimeout, вы переносите присваивание margin-left / width в следующий тик в event loop — и после того, как ваша функция «клик» отработает, браузер между делом «познакомится» с новыми нодами в доме, и когда функция по таймеру изменит margin-left, браузер это зафиксирует и запустит transition. И таймер в данном случае является оптимальным решением — a без нужно браузер заставить пересчитать стили:
// ...
$('.calendarBody').html('<div id="calendarTransform">'+content+'</div>');
var $transform = $('#calendarTransform'),
       styles  = getComputedStyle($transform[0]);
styles['margin-left'];
styles['width'];

$transform.css({'margin-left': -step, 'width': step*2})}, 1);


Также это относится к удалению «display:none» — присваивание всех других стилей в том же тике, не будет расценено браузером как изменения.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
deleted-mifki
@deleted-mifki
Потому что вы пытаетесь анимировать только что созданный элемент, а с таймаутом это происходит уже на следующей итерации цикла обработки событий. Ну и, кстати, использовать таймер таким способом (там можно даже 0 написать, видимо) — вполне нормальный подход.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы