...

четверг, 22 января 2015 г.

Рисуем анимированную сцену с помощью css

Передохнем от верстки всяких пользовательских интерфейсов и просто порисуем на CSS. Рисовать будем такую вот сцену:


Смотреть на jsfiddle.


В статье я попробую описать пошаговое создание этой сцены.


Описанный код работает на webkit браузерах (Chrome, Safari, Opera последних версий). Для работы в других браузерах вместо префиксв -webkit нужно воспользоваться соответствующими префиксами (-moz, -ms, -o).


Создаем сцену и небо











.scene {
position: relative;
width: 800px;
height: 600px;
margin: 50px auto;
overflow: hidden;
background-image: -webkit-linear-gradient(top, #011428, #032a54);
}





с помощью linear-gradient(top, #011428, #032a54) мы заполнили сцену градиентом от темноватого (#011428) до более светлого (#032a54) оттенка синего начиная сверху (top)


Рисуем сугробы. За основу возьмем элипсы которые можно создать из div'ов задав им border-radius: 50%



.ground {
position: absolute;
width: 770px;
height: 200px;
border-radius: 50%;
background-color: #99a;
}



Позиционируем 4 эллипса внизу сцены


























.ground {
width: 400px;
background-color: #f5f5f5;
border-radius: 50%;
width: 770px;
height: 200px;
position: absolute;
bottom: 0;
margin-bottom: -80px;
right: 140px;
background-color: #99a;
}
.ground.back-1 {left: 180px;}
.ground.front {margin-bottom: -124px;left: -27px;}
.ground.front-2 {margin-bottom: -109px;right: -508px;}





Делаем сугробы объемными добавив к классу .ground внутренню тень



box-shadow: 0 0 100px #457eb2 inset;



Рисуем луну и звезды
























.moon {
position: absolute;
width: 60px;
height: 60px;
top: 100px;
left: 100px;
background-color: #ffffaa;
border-radius: 50%;
}

.stars {
position: absolute;
width: 100%;
height: 100%;
}

.star {
position: absolute;
border-radius: 50%;
width: 1px;
height: 1px;
background-color: #ffffff;
}

.star:nth-child(1) {top: 100px;left: 685px;}
.star:nth-child(2) {top: 37px;left: 537px;}
.star:nth-child(3) {top: 150px;left: 350px;}
.star:nth-child(4) {top: 50px;left: 320px;}
.star:nth-child(5) {top: 30px;left: 755px;}
.star:nth-child(6) {top: 70px;left: 483px;}
.star:nth-child(7) {top: 18px;left: 80px;}




Добавляем луне эффект свечения



box-shadow: 0 0 40px #ffffaa;




И звездам тоже:

box-shadow: 0 0 10px 2px white;



Теперь приступаем к дому. Дом будет состоять из крыши, стены, окна и дымохода. Описываем все это версткой:


















.house {
position: absolute;
width: 300px;
height: 365px;
bottom: 50px;
right: 110px;
}



Рисуем стену. Эффект бревенчатого сруба можно получить с помощью повторяющегося градиента:



.house .wall {
width: 100%;
height: 200px;
position: absolute;
bottom: 0;
background-color: #180c00;
background: repeating-linear-gradient(to bottom, #573808 0%,#3a1e12 15%);
}



Делаем окошко. Это будет div с желтым фоном и с коричневой рамкой



.house .window {
position: absolute;
height: 70px;
width: 65px;
background-color: #cccc00;
border: 5px solid #3a1e12;
bottom: 53px;
left: 110px;
box-shadow: 0 0 5px black;
}



Добавляем к нему еще раму и эффект свечения с помощью box-shadow















.house .window .frame:nth-child(1) {
position: absolute;
height: 100%;
left: 50%;
margin-left: -3px;
width: 7px;
background-color: #3a1e12;
}

.house .window .frame:nth-child(2) {
position: absolute;
width: 100%;
top: 30%;
height: 7px;
background-color: #3a1e12;
}

.house .window .light {
width: 100%;
height: 100%;
background-color: #ffff00;
opacity: 0.5;
box-shadow: 0 0 100px yellow;
}




Создаем крышу. Это будет div бордер которого послужит кровлей.



.house .roof .roof-wall {
position: absolute;
width: 280px;
height: 280px;
background-color: #573808;
left: 25px;
top:60px;
border: 5px solid #3a1e12;
box-shadow: 0 0 30px black inset;
}



Для создания эффекта вагонки снова воспользуемся повторяющимся градиентом, который повернем на 45 градусов



background: repeating-linear-gradient(45deg, #573808 0%,#573808 5%,#3a1e12 5%,#3a1e12 5%,#3a1e12 5%,#573808 5%,#3a1e12 6%)



Крыша готова, ставим ее на дом повернув на 45 градусов с помощью transform: rotate(45deg) и отрезав половину с помощью overflow: hidden у контейнера



.house .roof {
width: 340px;
height: 170px;
right: -20px;
position: absolute;
overflow: hidden;
}

.house .roof .roof-wall {
position: absolute;
width: 280px;
height: 280px;
background-color: #573808;
-webkit-transform: rotate(45deg);
left: 25px;
top:60px;
border: 5px solid #3a1e12;
box-shadow: 0 0 30px black inset;
background: repeating-linear-gradient(45deg, #573808 0%,#573808 5%,#3a1e12 5%,#3a1e12 5%,#3a1e12 5%,#573808 5%,#3a1e12 6%);
}



Приделываем трубу, нарисованную с помощью градиента



.house .chimney {
position: absolute;
height: 80px;
width: 30px;
top: 58px;
left: 20px;
background: linear-gradient(right, rgba(42,41,45,1) 0%,rgba(80,84,91,1) 36%,rgba(22,27,33,1) 100%);
}


И добавляем шероховатости бревнам, наложив на них пару повторяющихся коричневых градиентов переходящих в прозрачность














.house .wall .crack {
position: absolute;
width: 100%;
height: 100%;
opacity: 0.5;
background: repeating-linear-gradient(3deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 2%, rgba(0,0,0,0) 2%,#3a1e12 2%,#3a1e12 2%,#573808 2%,#3a1e12 3%);
}

.house .wall .crack:nth-child(2) {
opacity: 0.3;
background: repeating-linear-gradient(-4deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 2%, rgba(0,0,0,0) 2%,#3a1e12 2%,#3a1e12 2%,#573808 2%,#3a1e12 3%);
}



Ну вот, у нас получилась уже вполне миленькая картинка



Настало время оживить нашу статичную картинку анимациями. Для начала сделаем чтобы из дымохода появлялись клубы дыма.

Пока что нарисуем одно облако дыма. Это будет полупрозрачный овал со светлым box-shadow ввокруг и радиальным градиентом.













.smoke-area .smoke {
position: absolute;
width: 30px;
height: 30px;
border-radius: 50%;
box-shadow: 0 0 20px lightgray;
background: radial-gradient(ellipse at center, rgba(206,220,231,1) 33%,rgba(89,106,114,0) 100%);
top: 120px;
left: 20px;
}




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



@-webkit-keyframes smoke-move {
0% {top: 120px; left: 20px}
20% {top: 107px; left: 25px}
30% {top: 95px; left: 35px; opacity: 0.9}
40% {top: 80px; left: 40px; }
50% {top: 65px; left: 50px; }
60% {top: 50px; left: 62px; }
70% {top: 35px; left: 75px; }
80% {top: 25px; left: 90px; }
90% {top: 15px; left: 117px; }
100% {top: 7px; left: 127px; opacity: 0; width: 90px; height: 60px}
}


Теперь назначим только что описанную анимацию к нашему облаку, добавив к классу .smoke свойство



-webkit-animation: smoke-move 2.3s linear infinite



Отлично у нас уже есть рабочий дымоход, но в полноценном виде он должен непрерывно ипускать много клубов дыма, так что добавим еще нескколько штук в верстку.





















Теперь облаков дыма несколько, но пока что толку от этого мало, так как все они движутся одновременно по одной траектории и все это выглядит как одно облако. Описывать новую анимацию для каждого облака слишком топорно и утомительно. Тут хочется какой-то случайности в их движении, например применить что-нибудь типа Math.random() с помощью javascript, но поскольку цель сделать сцену используя только css, прийдется выкручиваться подругому. В нашем случае можно просто заново использовать для каждого элемента уже описанную анимацию smoke-move, но с разным временем проигрывания:


.smoke-area .smoke:nth-child(2) {
-webkit-animation: smoke-move 2.5s linear infinite
}

.smoke-area .smoke:nth-child(3) {
-webkit-animation: smoke-move 2.7s linear infinite
}

.smoke-area .smoke:nth-child(4) {
-webkit-animation: smoke-move 2.2s linear infinite
}

.smoke-area .smoke:nth-child(5) {
-webkit-animation: smoke-move 2.1s linear infinite
}

.smoke-area .smoke:nth-child(6) {
-webkit-animation: smoke-move 2s linear infinite
}

.smoke-area .smoke:nth-child(7) {
-webkit-animation: smoke-move 2.9s linear infinite
}





Теперь клубы дыма движутся по той-же траектории но за различное время что дает видимость их случайного движения:


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


И в качестве изюминки добавим несколько падающих звездочек. Как и раньше начнем с одной, добавим ее как .meteor в div.meteors













.meteors {
position: absolute;
width: 100%;
height: 100%;
}



Описание css начнем с хвоста нашего метеора. Это будет белая линия переходящая в прозрачность.



.meteor {
position: absolute;
top: 50px;
left: 280px;
width: 300px;
height: 1px;
-webkit-transform: rotate(-45deg);
background-image: -webkit-linear-gradient(left, white, rgba(255,255,255,0));
}




Теперь нарисуем звездочку на конце этого хвоста:



.meteor:before {
content: ' ';
position: absolute;
width: 4px;
height: 5px;
background-color: white;
border-radius: 50%;
box-shadow: 0 0 14px 4px white;
margin-top: -2px;
}






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

@-webkit-keyframes meteor {
0% {margin-top: -300px; margin-right: -300px; opacity: 1}
8% {opacity: 0}
10% {margin-top: 300px; margin-left: -600px; opacity: 0}
100% {opacity: 0}
}




Запускаем метеор в полет:

.meteor {top: 100px;left: 480px;-webkit-animation: meteor 10s linear infinite;}






Нужно больше метеоров!













.meteor:nth-child(1) {top: 100px;left: 480px;-webkit-animation: meteor 10s linear infinite;}
.meteor:nth-child(2) {top: 200px;left: 280px;-webkit-animation: meteor 10s linear infinite;}
.meteor:nth-child(3) {top: 250px;left: 790px;-webkit-animation: meteor 9s linear infinite;}





Ну вот, сцена готова!


Recommended article: Chomsky: We Are All – Fill in the Blank.

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий