Генерація перешкод в HTML5 Canvas

308

Від автора: мої недавні статті про canvas анімації, імітації зоряного неба і створення генератора випадкових чисел вилилися в експеримент по створенню телевізійних перешкод… і так вийшло, що всі ці теми пов’язані. Як і в статті з зоряним небом, в даному уроці буде розбір коду з прикладами.

Статичні перешкоди

Перша задача – створити перешкоди, як у прикладі вище. З зображенням все легко: беремо тег canvas з визначеними висотою та шириною і заповнюємо його маленькими прямокутниками різних відтінків сірого. Сам елемент canvas:

Вихідні змінні скрипта, який потрібно помістити у нижню частину сторінки:

var canvas = document.getElementById(“static”),
context = canvas.getContext(“2d”),
tvHeight = canvas.offsetHeight,
tvWidth = canvas.offsetWidth,
smallestPixel = 4;

На це основі можна написати функцію генерації перешкод:

function drawStatic() {
for (var v=0; v < tvHeight; v += smallestPixel){
for (var h=0; h < tvWidth; h += smallestPixel){
lum = Math.floor( Math.random() * 50 );
context.fillStyle = “hsl(0, 0%,” + lum + “%)”;
context.fillRect(h,v, smallestPixel, smallestPixel);
}
}
}

У функції є два циклу for, один в іншому. Перший цикл працює вертикально. Як инкремента виступає змінна smallestPixel. Внутрішній цикл працює горизонтально і заповнює всі ряди квадратиками HSL кольору. Ряди заповнюються послідовно.

Щоб затемнити пікселі перешкод, зменшите значення lum. Щоб зробити їх тонше, зменшите значення smallestPixel. Перешкоди можна перетворити на прямокутники, задавши різні значення ширини та висоти пікселя, або ж змінюючи значення smallestPixel.

Як розтягнути canvas на весь екран

Щоб canvas заповнював всю сторінку, ми вдамося до старої й перевіреної CSS техніці:

body, html {
margin: 0; height:100%;
}
#static {
position:absolute;
width:100%;
height:100%;
}

Оптимізація часу відтворення

Якщо canvas становить 800 пікселів в ширину і 400 у висоту, а кожен піксель розміром 4х4, то у рядку виходить 200 пікселів, а всього промалювати необхідно 20 000 квадратиків. JS цілком може впоратися з цим завданням, але можуть виникнути труднощі при відображенні прямокутників (30 разів на секунду). Якщо ми захочемо анімувати всі елементи, нам потрібно зменшити їх кількість.

Для вирішення даної проблеми можна зменшити висоту і ширину canvas або збільшити розмір пікселя. Також можна малювати більш великі фігури, так їх знадобиться набагато менше. Зробити колір екрану за замовчуванням можна за допомогою властивості background:

#static { background: #333; }

Після чого простір хаотично заповнюється прямокутників різної ширини і висоти (значення не можуть виходити за певні рамки). Висота і ширина прямокутника буде також визначати його розташування: елемент позиціонується від 0 до значення ширини або висоти поля canvas (менше дозволу пікселя). За допомогою нової функції ми створимо 1 200 прямокутників. Спершу, я скористаюся з функцією статті про створення генератора випадкових чисел:

function getRandomInRange(min, max) {
return Math.floor(Math.random() * (max – min + 1)) + min;
}

Решті код, як в попередньому прикладі:

var canvas = document.getElementById(“static”),
context = canvas.getContext(“2d”),
tvHeight = canvas.offsetHeight,
tvWidth = canvas.offsetWidth,
staticWidth = 0,
staticHeight = 0,
smallestWidth = 8,
largestWidth = 32,
smallestHeight = 4,
largestHeight = 8,
maxPixels = 1200,
horizontalPosition = 0,
verticalPosition = 0;

Функція drawStatic також змінилася:

function drawStatic() {
for (var i=0; i < maxPixels; i++){
lum = getRandomInRange(40,80);
context.fillStyle = ” # hsla-color hsla(0, 0%,” + lum + “%, 0.8)”;
staticWidth = getRandomInRange(smallestWidth, largestWidth);
staticHeight = getRandomInRange(smallestHeight, largestHeight);
horizontalPosition = getRandomInRange(0, tvWidth – staticWidth);
verticalPosition = getRandomInRange(0, tvHeight – staticHeight);
context.fillRect(horizontalPosition,verticalPosition, staticWidth, staticHeight);
}
}

Результат виглядає трохи грубіше, і, можливо, більше підходить для анімації. У наступній статті ми анимируем ці перешкоди.