Вступительные титры из Star Wars на JS+CSS3

в 14:14, , рубрики: css, css3 transform, Интересное, метки: ,

Здравствуй Хабрахабр.

Вдохновленный недавно законченым курсом «Learn Jquery in 30 days» и статьей про генерацию изображения в виде кода матрицы, решил прокачать свой js до уровня чуть выше плинтуса, попробовать заработать инвайт и сделать что-нибудь интересное, что-то что можно показать, не сгорая от желания провалится под землю, такому искушенному сообществу как хабр.

Итак, подопытным были выбраны вступительные титры любмого мной цикла «Звездные Войны». В процессе гуляния интернетами, в поисках чьих-нибудь наработок ничего сначала найдено не было. Ну и хорошо, а то затея закончилась бы еще даже не начавшись.

Для создания анимации были выбраны Jquery(что не удивительно, ввиду предпосылок для всей этой затеи) и замечательные CSS3 свойства transform3d. Выбраны они были несмотря на долгое, безрезультатное битье челом в поисковую строку гугла в поисках костылей для кроссбраузерности. Добится идентичной работы в разных браузерах, даже в рамках одного движка(webkit) так и не удалось. Chrome наотрез отказывается показывать титры у нижнего края экрана, и они волшебным образом появляются только на середине анимации, в то время же как Safari исправно все показывает. Firefox заметно подтормаживает, но анимацию тоже отображает правильно.

Оговорюсь сразу, ни времени ни желания подгонять под различные разрешения у меня не было. Поэтому рассчитывалось все под мой рабочий монитор 1600x900. Если что-то где-то не там выскочит, не обессудьте.

Начнем с html-разметки

<!DOCTYPE html>
<html>
<head>
    <title>Star Wars Opening Crawl</title>
    <link rel="stylesheet" href="style.css" type="text/css">
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
    <script type="text/javascript">
	JS…
    </script>
</head>
<body>
    <h3 id="intro">A long time ago, in a galaxy far,<br /> far away...</h3>
	<audio id="music" preload="auto" autobuffer controls>		
	         <source src="http://dl.dropbox.com/u/16979719/sw_music.ogg">
	</audio>
<img src="starwars-logo.png" width="100%"/>
<div id="crawl">
    <div id="text">
	Тут текст титров…
    </div>
</div>
<div id="theend">THE END</div>
<div id="bg"></div>  //заранее подтянем фон, чтобы не мигал при смене
</body>
</html>

Ничего особенного…

JS

function startIntro(){
            $('#intro').fadeOut(1000);
            setTimeout(function (){
                $('body').css('background', 'url(background.png)')  // сменяем фон
				var music = document.getElementById('music')
					if(music.canPlayType) // проверка поддержки audio. Делается дабы Safari не останавливал JS на ошибке
						music.play()
                $('#logodiv').fadeIn(500);
                setTimeout(startCrawl, 1000);
            }, 1500)
        }

        function startCrawl(){
            $('#logodiv').hide("scale",{}, 15000); //без JQuery UI работать не будет			
            setTimeout(function(){
				$('#text').show()
				var now = 800;
				var translateY = setInterval(
					function(){ // хотелось бы использовать стандартный animation, но с transform он не дружит.
						if($.browser.mozilla) var prefix = '-moz-'
										else  var prefix = '-webkit-'		
						$('#text').css( prefix + 'transform','rotateX(55deg) translateY('+now+'px) translateZ(300px)');
						now = now - 2;
						if(now == -1800){  // титры уже далеко уехали, пора бы и заканчивать 
							clearInterval(translateY);
							$('#text').fadeOut(2000)
							$('#theend').delay(2000).fadeIn(2000);
						}
					}, 50);					
            }, 9000)
        }
		
        $(function(){
            setTimeout(function(){
                $('#intro').fadeIn(1000); //появление Long time ago...
            }, 500)
            setTimeout(startIntro, 6000);
        })

Весь JS это обычный набор таймеров, приправленный банальнейшими jquery-методами. Как я говорил раньше, на светлый путь познания JS я только вступил, поэтому за говнокод просьба не пинать.

Так как голый JQuery не умеет работать со свойством scale, то для анимации уменьшения картинки был подключен JQuery UI, который позволяет использовать scale в эффектах.

CSS
Здесь интересна только небольшая часть.

#crawl
{
    width: 1000px;
    margin: auto;
	-webkit-perspective: 800px;
	-webkit-perspective-origin: center 350px;	
	-moz-perspective: 800px;
	-moz-perspective-origin: center 350px;
}

#text 
{
    display: none;
	margin: auto;
    width: 600px;
	text-align: justify;
	-webkit-transform: rotateX(55deg) translateY(800px) translateZ(300px);
	-webkit-backface-visibility: visible;
	-moz-transform: rotateX(55deg) translateY(800px) translateZ(300px);
	-moz-backface-visibility: visible;		
}

Значения свойства (-префикс-)transform были найдены методом научного тыка анализа.
rotateX указывает на наклон элемента относительно оси Х (проще говоря относительно горизонтальной плоскости монитора), translateY определяет смещение по оси Y, translateZ как можно догадаться определяет смещение относительно оси Z.

perspective определяет глубину переспективы, perpective-origin указывает на позицию наблюдателя относительно нашего текста. Эти свойства указываются для родительського элемента узлов с которыми мы работаем.

Рабочий пример

В процессе гугления материалов наткнулся на реализацию титров на чистом css без js. Тут

Очень хочется услышать советы по поводу гармонизации всего этого хазяйства, улучшению кода, полезных костылей и прочего.

PS Отдельно хочется написать о работе Safari с элементом audio. Я, честно говоря, на некоторе время завис, наблюдая в консоли:

«TypeError: 'undefined' is not a function (evaluating 'document.getElementsTagName('audio')')».

Поблуждав между спецификацией элемента audio и гуглом — выснил, что Safari не поддерживает audio без установленного в системе QuickTime. Вот вам и standalone-приложение.

Автор: zein

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js