- PVSM.RU - https://www.pvsm.ru -

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

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

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

Смотреть на jsfiddle. [1]

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

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

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

		<div class="scene"></div>
        

		.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)

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

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

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

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

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

	<div class="ground back-1"></div>
	<div class="ground back-2"></div>
	<div class="ground front"></div>
	<div class="ground front-2"></div>
         

.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;}

	

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

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

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

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

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

		<div class="moon"></div>
		<div class="stars">
			<div class="star"></div>
			<div class="star"></div>
			<div class="star"></div>
			<div class="star"></div>
			<div class="star"></div>
			<div class="star"></div>
			<div class="star"></div>
		</div>
       

.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;}

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

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

	box-shadow: 0 0 40px #ffffaa;
        

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

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

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

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

		<div class="house">
			<div class="chimney"></div>
			<div class="roof">
				<div class="roof-wall"></div>
			</div>
			<div class="wall"></div>
			<div class="window"></div>
		</div>

		.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%);
		}
	

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

Делаем окошко. Это будет 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;
		}
	

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

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

		<div class="window">
			<div class="frame"></div>
			<div class="frame"></div>
			<div class="light"></div>
		</div>

		.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;
		}
	

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

Создаем крышу. Это будет 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;
	}
	

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

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

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

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

Крыша готова, ставим ее на дом повернув на 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%);
		}
	

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

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

		.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%);
		}
	

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

		<div class="wall">
			<div class="crack"></div>
			<div class="crack"></div>
		</div>

		.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%);
		}
	

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

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

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

		<div class="smoke-area">
			<div class="smoke"></div>
		</div>

		.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;
		}
	

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

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

		@-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
	

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

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

	<div class="smoke-area">
		<div class="smoke"></div>
		<div class="smoke"></div>
		<div class="smoke"></div>
		<div class="smoke"></div>
		<div class="smoke"></div>
		<div class="smoke"></div>
		<div class="smoke"></div>
		<div class="smoke"></div>
	</div>

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

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

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

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

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

		<div class="meteors">
			<div class="meteor"></div>
		</div>

	.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));
	}
	

Рисуем анимированную сцену с помощью css - 18
Теперь нарисуем звездочку на конце этого хвоста:

		.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;
		}
	

Рисуем анимированную сцену с помощью css - 19
Опишем анимацию для метеора, будем его двигать меняя отступы создавая эффект полета под наклоном 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;}
	

Рисуем анимированную сцену с помощью css - 20
Нужно больше метеоров!

		<div class="meteors">
			<div class="meteor"></div>
			<div class="meteor"></div>
			<div class="meteor"></div>
		</div>	

	.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;}

Рисуем анимированную сцену с помощью css - 21
Ну вот, сцена готова!

Автор: alexclimber

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/80281

Ссылки в тексте:

[1] Смотреть на jsfiddle.: http://jsfiddle.net/AlexanderN/onjsw3kv/2/

[2] взаимно простые числа.: https://ru.wikipedia.org/wiki/%D0%92%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%BE_%D0%BF%D1%80%D0%BE%D1%81%D1%82%D1%8B%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%B0

[3] Источник: http://habrahabr.ru/post/247731/