Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   CSS3 анимация (transition) (https://javascript.ru/forum/events/39270-css3-animaciya-transition.html)

Magneto 23.06.2013 13:38

CSS3 анимация (transition)
 
Я хочу добавить в приложение немного анимации, анимацию решил реализовывать при помощи css3. И у меня возникли проблемы с этим.

Сначала я опишу алгоритм работы анимации:
Есть некая кнопка по которой при клике плавно выезжает менюшка. При этом менюшка динамическая, она каждый раз заново генерируется и вставляется в DOM

Вот простой код, который по логике уже должен работать:
<html>
<head>
	<style type="text/css">
		.menu {
			width: 0px;
			height: 20px;
			text-align: center;
			color: #fff;
			background-color: green;
		}

		.animate {
			width: 400px;
			transition: width 2s;
		}
	</style>
</head>
<body>
	<script type="text/javascript">

		div = document.createElement('div');
		div.innerHTML = 'Dynamic Menu'
		div.className = 'menu';

		document.body.appendChild( div );

		div.className += ' animate';

	</script>
</body>
</html>

, но если запустить код то никакой анимации не произойдет, хотя она и прописана в стилях - transition: width 2s;

Проблема в том что современные браузеры оптимизируют работу с DOM, и они стараются произвести максимум работы с элементом перед вставкой его в DOM. Поэтому если посмотреть в код на строки 25 и 27 становится ясно что они выполняются не в той последовательности как записаны. Тоесть браузер сначала добавляет класс animate в котором описана анимация а после вставляет элемент в страницу и естественно никакой анимации не происходит.

Чтоб проверить это нужно вынести добавление класса animate в асинхронную функцию, например вот так:
setTimeout( function () {
	div.className += ' animate';
}, 10 );

<html>
<head>
	<style type="text/css">
		.menu {
			width: 0px;
			height: 20px;
			text-align: center;
			color: #fff;
			background-color: green;
		}

		.animate {
			width: 400px;
			transition: width 2s;
		}
	</style>
</head>
<body>
	<script type="text/javascript">

		div = document.createElement('div');
		div.innerHTML = 'Dynamic Menu'
		div.className = 'menu';

		document.body.appendChild( div );

		setTimeout( function () {
			div.className += ' animate';
		}, 10 );

	</script>
</body>
</html>

, ну вот все работает.

Но так как предполагается достаточно много анимированных элементов, то совсем не хочется иметь великое множество setTimeout в проекте.

Ну и вопрос: как установить класс новосозданному элементу, гарантированно после вставки этого элемента в DOM? ( Не используя setTimeout, setInterval и пр. )

melky 23.06.2013 14:21

Ты почти отгадал, в чём соль :)

http://javascript.ru/forum/css-html-...eflow-bug.html

можно просто вызвать forced отрисовку.

я это делал так :

window.scrollBy(0, 0);


ну или можно подождать отрисовки и тогда применять стиль - это делается с помощью requestAnimationFrame, который вызывает callback перед отрисовкой. Двойной вызов rAF сделает бочку.

Удачи!) переходы (transitions) вообще такая муть .... зря с ними связываться только :)

Deff 23.06.2013 15:05

Вариант:
<html>
<head>
	<style type="text/css">
		.menu {
			width: 0px;
			height: 20px;
			text-align: center;
			color: #fff;
			background-color: green;
		}

		.animate {
			width: 400px;
			transition: width 2s;
		}

	</style>
</head>
<body>

	<script type="text/javascript">
		div = document.createElement('div');
function btnClk(){
		div.innerHTML = 'Dynamic Menu'
		div.className = 'menu';
		document.body.appendChild( div );

}
function btnClk2(){
		div.className=div.className.replace(/ ?animate/i,'')+' animate';

}
	</script>
<input type=button value=Клик onmousedown="btnClk()" onmouseup="btnClk2()">
</body>
</html>

Magneto 23.06.2013 17:37

Цитата:

Сообщение от melky
можно просто вызвать forced отрисовку.

Спасибо, я остановил свой выбор на:
div.offsetTop

, это работает в: Chrome 27, Firefox 21, Opera 12.15 и IE 10.

Цитата:

Сообщение от Deff
Вариант: ...

Спасибо, хороший вариант, но мне он не подошел.
Я пишу на Backbone.js и Chaplin.js, и там событие которое вызывает меню кастомное да и вообще там все так "православно" )). Ну и есть более легкий способ, см. выше.

maxycws 19.12.2014 11:39

Сделал перевод статьи по анимациям для начинающих. От и до расписано что для чего. Живые примеры тут же в тексте. Можно копировать и вставлять сразу к себе на сайт.

http://devdocs.ru/verstka/css3-anima...for-beginners/


Часовой пояс GMT +3, время: 09:38.