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

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

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

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

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

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

.scene { position: relative; width: 800 px; height: 600 px; margin: 50 px auto; overflow: hidden; background-image: -webkit-linear-gradient (top, #011428, #032a54); } с помощью linear-gradient (top, #011428, #032a54) мы заполнили сцену градиентом от темноватого (#011428) до более светлого (#032a54) оттенка синего начиная сверху (top)f7369677347749c39aa8174c2fece5a9.png

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

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

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

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

fb9ae26d943e494d9b48ac59bb1f57f4.png

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

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

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

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

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

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

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

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

box-shadow: 0 0 40 px #ffffaa; И звездам тоже: box-shadow: 0 0 10 px 2 px white; 7f9a13aa89ce456ab33acc8eec0e16b3.png

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

.house { position: absolute; width: 300 px; height: 365 px; bottom: 50 px; right: 110 px; } Рисуем стену. Эффект бревенчатого сруба можно получить с помощью повторяющегося градиента:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.house .chimney { position: absolute; height: 80 px; width: 30 px; top: 58 px; left: 20 px; 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%); } Ну вот, у нас получилась уже вполне миленькая картинка

e8b5129452394a0f921f02a70e901581.png

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

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

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

@-webkit-keyframes smoke-move { 0% {top: 120 px; left: 20 px} 20% {top: 107 px; left: 25 px} 30% {top: 95 px; left: 35 px; opacity: 0.9} 40% {top: 80 px; left: 40 px; } 50% {top: 65 px; left: 50 px; } 60% {top: 50 px; left: 62 px; } 70% {top: 35 px; left: 75 px; } 80% {top: 25 px; left: 90 px; } 90% {top: 15 px; left: 117 px; } 100% {top: 7 px; left: 127 px; opacity: 0; width: 90 px; height: 60 px} } Теперь назначим только что описанную анимацию к нашему облаку, добавив к классу .smoke свойство

-webkit-animation: smoke-move 2.3s linear infinite e0df1376293042b4b5925616e21eb188.gif

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

Теперь облаков дыма несколько, но пока что толку от этого мало, так как все они движутся одновременно по одной траектории и все это выглядит как одно облако. Описывать новую анимацию для каждого облака слишком топорно и утомительно. Тут хочется какой-то случайности в их движении, например применить что-нибудь типа 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 } Теперь клубы дыма движутся по той-же траектории, но за различное время что дает видимость их случайного движения: 6a5be29067fb42988749c85196224986.gif

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

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

.meteors { position: absolute; width: 100%; height: 100%; } Описание css начнем с хвоста нашего метеора. Это будет белая линия переходящая в прозрачность.

.meteor { position: absolute; top: 50 px; left: 280 px; width: 300 px; height: 1 px; -webkit-transform: rotate (-45deg); background-image: -webkit-linear-gradient (left, white, rgba (255,255,255,0)); } fe4ad1131ba8484b94701fb1813aa7c9.pngТеперь нарисуем звездочку на конце этого хвоста:

.meteor: before { content: ' '; position: absolute; width: 4 px; height: 5 px; background-color: white; border-radius: 50%; box-shadow: 0 0 14 px 4 px white; margin-top: -2 px; } 96b26b0eb2534e348e363eebea795192.pngОпишем анимацию для метеора, будем его двигать меняя отступы создавая эффект полета под наклоном 45 градусов. Метеор будет падать и постепенно исчезать. @-webkit-keyframes meteor { 0% {margin-top: -300 px; margin-right: -300 px; opacity: 1} 8% {opacity: 0} 10% {margin-top: 300 px; margin-left: -600 px; opacity: 0} 100% {opacity: 0} } Запускаем метеор в полет: .meteor {top: 100 px; left: 480 px;-webkit-animation: meteor 10s linear infinite;} 79a8bd84f07d479493e8c9e77adb3b3b.gifНужно больше метеоров!

.meteor: nth-child (1) {top: 100 px; left: 480 px;-webkit-animation: meteor 10s linear infinite;} .meteor: nth-child (2) {top: 200 px; left: 280 px;-webkit-animation: meteor 10s linear infinite;} .meteor: nth-child (3) {top: 250 px; left: 790 px;-webkit-animation: meteor 9s linear infinite;} d5ea6060c4c946e98b2e25e5008971bf.gifНу вот, сцена готова!

© Habrahabr.ru