Здравствуйте, уважаемые читатели сайта Sumlab.ru!
В этой статье будет показано, как можно с помощью JavaScript создать веб-приложение, которое будет работать в браузере и имитировать движения рыб. Говоря проще, будет создан простой аквариум. В дальнейшем его можно будет установить на заставку в браузере или разместить на вашем сайте, чтобы он развлекал посетителей.
Конечный результат можно посмотреть здесь. Ссылки на исходный код будут указаны в конце статьи.
А теперь пройдёмся по порядку по всем этапам создания этого приложения.
Подготавливаем основу для рисования
Рисовать наш аквариум будем с помощью технологии canvas, которая доступна в html5, поэтому нам потребуется подготовить соответствующий html-документ. Обязательно в нём следует указать <!DOCTYPE html> и тег <canvas></canvas>. В нашем случае простой пример такой страницы будет выглядеть так:
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Aquarium</title>
<link href="./style.css" rel="stylesheet">
<script defer src="./app.js"></script>
</head>
<body>
<canvas></canvas>
</body>
</html>
Объявляем стартовые значения
Теперь переходим к созданию js-кода. Он будет написан в файле ./app.js, который ранее мы подключили на html-странице и который лежит в общей для нашего проекта директории. В этом файле мы сперва объявим основные константы, с которыми будем работать дальше.
// получаем ссылку на элемент canvas по его селектору
const canvas = document.querySelector('canvas');
// получаем контекст для рисования
const ctx = canvas.getContext('2d');
// получаем ширину и высоту доступного окна
const width = canvas.width = window.innerWidth;
const height = canvas.height = window.innerHeight;
// указываем количество рыб
const COUNT_FISH = 50;
// создаём пустой массив, где будут храниться объекты всех рыб
const allFish = [];
Создаём служебную функцию
Также нам потребуется создать служебную функцию, которая будет возвращать случайное число в заданном диапазоне.
function random(min, max, withZero = true) {
// генерируем случайное число
let num = Math.floor(Math.random() * (max - min)) + min;
// проверяем значение withZero. Если он true, то сразу возвращаем число num,
// даже если там ноль
if(withZero){
return num;
}
// если значение withZero равно false, то запускаем цикл while до тех пор,
// пока в num не будет значение отличное от нуля. После этого возвращаем его
while(num === 0){
num = Math.floor(Math.random() * (max - min)) + min;
}
return num;
};
Функция random имеет три входных параметра: min - минимальное число; max - максимальное число; withZero - флаг, который указывает возвращать ноль или нет, если он попадает в заданный диапазон от min до max.
Создаём класс Fish
Переходим к одной из самых важных частей, созданию общего класса Fish. На основе этого класса мы будем генерировать объекты всех наших рыб.
В конструкторе класса происходит базовая инициализация объекта. Поэтому нам нужно заполнить полученными и сгенерированными значениями следующие свойств:
- this.x - положение объекта на оси x;
- this.y - положение объекта на оси y;
- this.velX - скорость перемещения по оси x;
- this.velY - скорость перемещения по оси y;
- this.img_fish - создаём пустое изображение для текущего объекта;
- this.fish - генерируем случайное название для текущей рыбы в диапазоне от fish1 до fish8 (понадобится для отображения разных видов рыб).
class Fish {
constructor(x, y, velX, velY) {
this.x = x;
this.y = y;
this.velX = velX;
this.velY = velY;
this.img_fish = new Image();
this.fish = `fish${random(1, 8)}`;
}
}
Добавляем в класс Fish метод draw. Он необходим для отрисовки изображения рыбы по текущим координатам x, y для вызываемого объекта. Само изображение рыбы будет меняться в зависимости от скорости движения velX (положительная или отрицательная). Если скорость движения рыбы меньше нуля, значит перемещение объекта происходит в левую сторону от текущего положения, а следовательно подключаем левостороннее изображение. В противном случае подключаем правостороннее изображение.
draw() {
if(this.velX < 0){
// подключаем левостороннее изображение
this.img_fish.src = `./img/${this.fish}-l.png`;
}else{
// подключаем правосторонее изображение
this.img_fish.src = `./img/${this.fish}-r.png`;
}
ctx.drawImage(this.img_fish, this.x, this.y);
}
На этом этапе мы уже настроили инициализацию объекта и его отображение. Теперь нам необходимо реализовать перемещение (движение) объекта. Для этого создадим метод update, который будет сдвигать объект по оси координат, в зависимости от значения скорости. А когда объект будет достигать какой-то границы, то знак скорости будет меняться на противоположный, и объект начнёт двигаться в обратную сторону.
update() {
// если объект достиг правой границы, то меняем его скорость
// в this.velX на противоположную
if ((this.x + this.img_fish.width) >= width) {
this.velX = -(this.velX);
}
// если объект достиг левой границы, то меняем его скорость
// в this.velX на противоположную
if (this.x <= 0) {
this.velX = -(this.velX);
}
// если объект достиг нижней границы, то меняем его скорость
// в this.velY на противоположную
if ((this.y + this.img_fish.height) >= height) {
this.velY = -(this.velY);
}
// если объект достиг верхней границы, то меняем его скорость
// в this.velY на противоположную
if (this.y <= 0) {
this.velY = -(this.velY);
}
// когда определились с направлением движения, то меняем текущее положение объекта
this.x += this.velX;
this.y += this.velY;
}
Генерируем всех рыб
С созданием класса Fish на этом закончили. Теперь на его основе нужно создать всех наших рыб и заполнить ими массив allFish.
while (allFish.length < COUNT_FISH) {
const fish = new Fish(
random(0 + 100, width - 100),
random(0 + 100, height - 100),
random(-3, 3, false),
random(-1, 1, false),
);
allFish.push(fish);
}
При создании экземпляра класса в его конструктор мы передаём следующие значения:
- стартовое положение объекта рыбы по оси x. Чтобы рыба не создалась на краю области для рисования, делаем смещение на 100 пикселей от левой и правой границы;
- стартовое положение объекта рыбы по оси y. Также делаем смещение на 100 пикселей по краям;
- скорость перемещения объекта по оси x. От и до. Третий параметр указываем как false, чтобы исключить нулевую скорость;
- скорость перемещения объекта по оси y. От и до. Третий параметр указываем как false, чтобы исключить нулевую скорость.
Когда получили готовый объект, добавляем его в конец массива allFish с помощью метода push.
Запускаем цикл
В завершении нам осталось создать функцию, которая будет повторяться циклически с помощью метода requestAnimationFrame, который предназначен для запуска анимации.
function loop() {
// создаём фоновое изображение
img_fon = new Image();
img_fon.src = `./img/fon.jpg`;
// заполняем контекст фоновым изображением
ctx.fillStyle = ctx.createPattern(img_fon, "repeat");
ctx.fillRect(0, 0, width, height);
// перебираем в цикле все объекты рыб. Для каждого запускаем методы draw и update, которые отрисовывают его и сдвигают.
for (const fish of allFish) {
fish.draw();
fish.update();
}
// передаём запуск функции методу
requestAnimationFrame(loop);
}
loop();
На этом создание аквариума на JavaScript можно считать завершённым. Ниже прикладываю скриншот с полученным результатом. Здесь же вы можете ознакомиться с живым примером, а здесь посмотреть на весь код в репозитории на GitHub.
Аквариум на JavaScript
А на этом всё! Всем спасибо за внимание.
Если вам понравилась статья, тогда не забывайте делиться ею в социальных сетях и писать ваши комментарии.
Добавить комментарий:
Комментарии: