Веб-проект: делаем аквариум с разными обитателями
easy

Веб-проект: делаем аквариум с разными обитателями

Собираем аквариум из эмодзи и одной картинки

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

Веб-проект: делаем аквариум с разными обитателями

Логика проекта

Наш веб-проект будет состоять из трёх частей:

  1. HTML-страница, в которой мы будем видеть результат, а по нажатию кнопки добавлять новых обитателей аквариума.
  2. Стили оформления, которые будут отвечать за внешний вид элементов морского дна, рыбок и кнопки.
  3. Скрипт, который оживит наших морских обитателей, чтобы они плавали туда-сюда :-)

Создавать всё это мы будем в такой же последовательности — от страницы к скрипту, чтобы показать, что происходит на каждом из этапов.

Создаём веб-страницу

Поскольку всё будут делать стили и скрипт, веб-страница нужна нам в качестве контейнера для них. Создадим новый HTML-документ, пропишем необходимый минимум элементов, разметим задний, средний и передний план нашего аквариума. Заодно подключим файлы стилей и скрипта — их пока нет, но страница уже будет работать.

<!DOCTYPE html>
<html lang="ru" >
<head>
<meta charset="UTF-8">
<title>Аквариум</title>
<!-- подключаем стили -->
<link rel="stylesheet" href="style.css">

</head>
<body>
	<!-- добавляем элементы -->

	<div>
		<!-- кнопка для добавления рыбки --!>
		<button>Добавить рыбку</button>

		<!-- задний фон --!>
		<div>
			<!-- рыбки -->
			<div></div>
			<!-- кораллы и раковины -->
			<div></div>
		</div>

		<!-- элементы посередине -->
		<div>
			<!-- рыбки -->
			<div></div>
			<!-- растения -->
			<div></div>
		</div>

		<!-- передний план -->
		<div>
			<!-- рыбки -->
			<div></div>
		</div>
	</div>
	<!-- подключаем скрипт -->
	<script src="script.js"></script>

</body>
</html>

Сохраним этот код в файле index.html и откроем в браузере. На нашей странице пока нет ничего, кроме белого фона и кнопки, но мы это сейчас исправим.

Веб-проект: делаем аквариум с разными обитателями

Настраиваем стили

Для начала сделаем нашу кнопку интереснее и красивее. Раскрасим её и рамку, зададим отступы внутри, укажем шрифт и его размер. Ещё добавим немного анимации, которая будет отображаться при наведении мыши: пусть стрелка становится рукой с вытянутым указательным пальцем, а цвет кнопки немного меняется.

/* задаём стиль кнопки */
button {
  /* абсолютное позиционирование */
  position: absolute;
  /* определяем порядок слоёв элементов на странице */
  z-index: 2;
  /* отступы для кнопки */
  margin: 1rem;
  /* размер шрифта текста на кнопке */
  font-size: 1.2rem;
  /* внутренние отступы для текста на кнопке */
  padding: .5rem 1rem;
  /* шрифт для текста на кнопке */
  font-family: sans-serif;
  /* меняем курсор при наведении на кнопку */
  cursor:pointer;
  /* фоновый цвет кнопки с прозрачностью 60% */
  background: #009dff60;
  /* тень для кнопки */
  box-shadow: 0 0 .25rem 0 ;
  /* границу для кнопки */
  border: 4px solid #009dff;
  /* радиус скругления углов кнопки */
  border-radius: 4px;
  /* при наведении на кнопку фоновый цвет меняется на другой с прозрачностью 90% */
  &:hover{
     background: #009dff90;
  }
   /* при нажатии кнопки её размер увеличивается на 10% */
   &:active{
     transform: scale(1.1);
  }
  
}

Теперь нужно добавить изображение морского дна, причём так, чтобы оно занимало всё окно и не имело окантовки. Сгенерируем картинку в Кандинском с пропорциями 3:2 по промту «морское дно с песком и голубой водой, через которую проникают солнечные лучи». Сохраним картинку, укажем её в стилях и растянем на всю страницу:

body {
  /* отступы фоновой картинки */
  margin: 0;
}
.back {
  /* цвет заднего фона */
  background: #009dff30;
  /* размер элементов фона */
  font-size: 2rem;
  /* картинка заднего фона */
  background-image: url("sea_bottom.png");

    /* картинка полностью заполняет задний план без изменения пропорций */
    background-size: cover;
}
Веб-проект: делаем аквариум с разными обитателями

Теперь пропишем стили для элементов на заднем фоне, в середине и на переднем плане: определим размеры, а фон сделаем более голубым. Дополним стиль body:

.coral {
/* отступы снизу */
bottom: -4rem;
/* отступы слева */
left: -3rem;
/* абсолютное позиционирование */
position: absolute;
/* размер шрифта */
font-size: 12rem;
/* запрет на перенос на новую строку */
white-space: nowrap;
/* расстояние между символами */
letter-spacing: 2rem;
}
.back .coral {
/* отступы слева */
left: 2rem;
/* отступы снизу */
bottom: -5rem;
/* размер шрифта */
font-size: 17rem;
/* запрет на перенос на новую строку */
white-space: nowrap;
/* расстояние между символами */
letter-spacing: 5rem;
}

.middle {
/* цвет фона */
background: #009dff30;
/* размер шрифта */
font-size: 4rem;
}

.front {
/* цвет фона */
background: #009dff30;
/* размер шрифта */
font-size: 6rem;
}

.layer {
/* ширина 100% */
width: 100%;
/* высота 100% */
height: 100%;
/* абсолютное позиционирование */
position: absolute;
/* скрывать содержимое, если оно выходит за пределы */
overflow: hidden;
}

.fish {
/* анимация длительностью 17 секунд с линейным типом и бесконечным повтором */
animation: example 17s linear infinite;
/* абсолютное позиционирование */
position: absolute;
}

Зададим стили будущей анимации:

// задаём ключевые кадры
@keyframes example {
// что будет на первом кадре
0% {
// разворачиваем рыбку
left: 0;
transform: scaleX(-1);
}
// в середине анимации
50% {
// в середине она доплыла до края аквариума
left: 100%;
transform: scaleX(-1);
}
51% {
// после разворачиваем рыбу
transform: scaleX(1);
}
// и в конце
100% {
// и отправляем её в обратное плавание
left: 0;
}
}

Дополним веб-страницу

Добавим недостающие элементы на нашу страницу: кораллы, раковины и растения.

<div>
<!-- кнопка для добавления рыбки -->
<button v-on:click="addFish">Добавить рыбку</button>

<!-- задний фон -->
<div class="layer back">
<!-- рыбки -->
<div v-for="fish in back" class="fish" :style="fish.style">{{fish.fish}}</div>
<!-- кораллы и раковины -->
<div class="coral">🪸🎍🐚🪸🎍🐚🪸🎍🐚🪸🎍</div>
</div>

<!-- элементы посередине -->
<div class="layer middle">
<!-- рыбки -->
<div v-for="fish in middle" class="fish" :style="fish.style">{{fish.fish}}</div>
<!-- растения -->
<div class="coral">🌿🌱🌿🌱🌿🌱🌿🌱🌿</div>
</div>

<!-- передний план -->
<div class="layer front">
<!-- рыбки -->
<div v-for="fish in front" class="fish" :style="fish.style">{{fish.fish}}</div>
</div>
</div>
Веб-проект: делаем аквариум с разными обитателями

Вместо рыбок у нас пока плавает код, но мы исправим это на следующем шаге. 

Пишем скрипт

За выбор рыбок и анимацию у нас будет отвечать такой скрипт:

// используем Vue для программирования поведения и появления рыбок
new Vue({
	// создаём новое vue-приложение
	el: "#app",
	data: {
		// массив с рыбками
		fish: ["🐟", "🐠", "🐡", "🪼", "🐙", '🦑', '🐬', '🐳', '🐋', '🦑', '🦈', '🧜‍♀️', '🧜'],
		// устанавливаем, какие рыбки будут двигаться на разных планах и с какой скоростью
front: [{ 'fish': '🐠', 'style': { top: '10%', animationDuration: '30s' } }],
		middle: [{ 'fish': '🐡', 'style': { top: '47%', animationDuration: '25s' } }],
		back: [{ 'fish': '🐟', 'style': { top: '14%', animationDuration: '35s' } }],
		layers: ["front", "middle", "back"] 
	},


	// задаём методы приложения
methods: {
	// функция добавления новой рыбки
		addFish: function (event) {
			// выбираем случайным образом рыбку и план для неё
			const icon = Math.floor(Math.random() * this.fish.length);
			const layer = Math.floor(Math.random() * 3);
			// создаём новую рыбку с выбранными параметрами
			const object = {
				fish: this.fish[icon],
				style: {
				// задаём размер и скорость движения рыбы
				fontSize: Math.floor(Math.random() * 10 + 2) + "rem",
				top: Math.floor(Math.random() * 100) + "%", animationDuration: Math.floor(Math.random() * 30 + 10) + "s" } 
			};

			// добавляем рыбку на нужный слой
this.layers[layer] === "front" && this.front.push(object);
			this.layers[layer] === "middle" && this.middle.push(object);
			this.layers[layer] === "back" && this.back.push(object);
		}	 
	} 
});

Получилось! Теперь в нашем аквариуме плавают рыбки:

Веб-проект: делаем аквариум с разными обитателями

<!DOCTYPE html>
<html lang="ru" >
<head>
	<meta charset="UTF-8">
	<title>Аквариум</title>
	<!-- подключаем стили -->
	<link rel="stylesheet" href="./style.css">

</head>
	<body>
	<!-- добавляем элементы -->
	<div id="app">
		<!-- кнопка для добавления рыбки -->
		<button v-on:click="addFish">Добавить рыбку</button>
		<!-- задний фон -->
		<div class="layer back">
			<!-- рыбки -->
			<div v-for="fish in back" class="fish" :style="fish.style">{{fish.fish}}</div>
			<!-- кораллы и раковины -->
			<div class="coral">🪸🎍🐚🪸🎍🐚🪸🎍🐚🪸🎍</div>
		</div>
		
		<!-- элементы посередине -->
		<div class="layer middle">
			<!-- рыбки -->
			<div v-for="fish in middle" class="fish" :style="fish.style">{{fish.fish}}</div>
			<!-- растения -->
			<div class="coral">🌿🌱🌿🌱🌿🌱🌿🌱🌿</div>
		</div>

		<!-- передний план -->
		<div class="layer front">
		<!-- рыбки -->
			<div v-for="fish in front" class="fish" :style="fish.style">{{fish.fish}}</div>
		</div>
		
	</div>
	<!-- подключаем скрипты -->
	<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js'></script><script src="./script.js"></script>

	</body>
	</html>

body {
  /* отступы фоновой картинки */
  margin: 0;
}

.coral {
/* отступы снизу */
bottom: -4rem;
/* отступы слева */
left: -3rem;
/* абсолютное позиционирование */
position: absolute;
/* размер шрифта */
font-size: 12rem;
/* запрет на перенос на новую строку */
white-space: nowrap;
/* расстояние между символами */
letter-spacing: 2rem;
}

.back {
  /* цвет заднего фона */
  background: #009dff30;
  /* размер элементов фона */
  font-size: 2rem;
  /* картинка заднего фона */
  background-image: url("sea_bottom.png");

    /* картинка полностью заполняет задний план без изменения пропорций */
    background-size: cover;
}
.back .coral {
/* отступы слева */
left: 2rem;
/* отступы снизу */
bottom: -5rem;
/* размер шрифта */
font-size: 17rem;
/* запрет на перенос на новую строку */
white-space: nowrap;
/* расстояние между символами */
letter-spacing: 5rem;
}

.middle {
/* цвет фона */
background: #009dff30;
/* размер шрифта */
font-size: 4rem;
}

.front {
/* цвет фона */
background: #009dff30;
/* размер шрифта */
font-size: 6rem;
}

.layer {
/* ширина 100% */
width: 100%;
/* высота 100% */
height: 100%;
/* абсолютное позиционирование */
position: absolute;
/* скрывать содержимое, если оно выходит за пределы */
overflow: hidden;
}

.fish {
/* анимация длительностью 17 секунд с линейным типом и бесконечным повтором */
animation: example 17s linear infinite;
/* абсолютное позиционирование */
position: absolute;
}

// задаём ключевые кадры
@keyframes example {
// что будет на первом кадре
0% {
// разворачиваем рыбку
left: 0;
transform: scaleX(-1);
}
// в середине анимации
50% {
// в середине она доплыла до края аквариума
left: 100%;
transform: scaleX(-1);
}
51% {
// после разворачиваем рыбу
transform: scaleX(1);
}
// и в конце
100% {
// и отправляем её в обратное плавание
left: 0;
}
}

// используем Vue для программирования поведения и появления рыбок
new Vue({
	// создаём новое vue-приложение
	el: "#app",
	data: {
		// массив с рыбками
		fish: ["🐟", "🐠", "🐡", "🪼", "🐙", '🦑', '🐬', '🐳', '🐋', '🦑', '🦈', '🧜‍♀️', '🧜'],
		// устанавливаем, какие рыбки будут двигаться на разных планах и с какой скоростью
front: [{ 'fish': '🐠', 'style': { top: '10%', animationDuration: '30s' } }],
		middle: [{ 'fish': '🐡', 'style': { top: '47%', animationDuration: '25s' } }],
		back: [{ 'fish': '🐟', 'style': { top: '14%', animationDuration: '35s' } }],
		layers: ["front", "middle", "back"] 
	},


	// задаём методы приложения
methods: {
	// функция добавления новой рыбки
		addFish: function (event) {
			// выбираем случайным образом рыбку и план для неё
			const icon = Math.floor(Math.random() * this.fish.length);
			const layer = Math.floor(Math.random() * 3);
			// создаём новую рыбку с выбранными параметрами
			const object = {
				fish: this.fish[icon],
				style: {
				// задаём размер и скорость движения рыбы
				fontSize: Math.floor(Math.random() * 10 + 2) + "rem",
				top: Math.floor(Math.random() * 100) + "%", animationDuration: Math.floor(Math.random() * 30 + 10) + "s" } 
			};

			// добавляем рыбу на нужный слой
this.layers[layer] === "front" && this.front.push(object);
			this.layers[layer] === "middle" && this.middle.push(object);
			this.layers[layer] === "back" && this.back.push(object);
		}	 
	} 
});

Обложка:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Мария Дронова

Соцсети:

Юлия Зубарева

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