От автора: мои недавние статьи о canvas анимации, имитации звездного неба и создании генератора случайных чисел вылились в эксперимент по созданию телевизионных помех… и так вышло, что все эти темы связаны. Как и в статье со звездным небом, в данном уроке будет разбор кода с примерами.
Статические помехи
Первая задача – создать помехи, как в примере выше. С изображением все легко: берем тег canvas с заданными шириной и высотой и заполняем его маленькими прямоугольниками разных оттенков серого. Сам canvas элемент:
1 |
<canvas id="static" width="750" height="500"></canvas> |
Исходные переменные скрипта, который нужно поместить в нижнюю часть страницы:
1 2 3 4 5 |
var canvas = document.getElementById("static"), context = canvas.getContext("2d"), tvHeight = canvas.offsetHeight, tvWidth = canvas.offsetWidth, smallestPixel = 4; |
На это основе можно написать функцию генерации помех:
1 2 3 4 5 6 7 8 9 |
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 технике:
1 2 3 4 5 6 7 8 |
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:
1 |
#static { background: #333; } |
После чего пространство хаотично заполняется прямоугольниками разной ширины и высоты (значения не могут выходить за определенные рамки). Высота и ширина прямоугольника будет также определять его расположение: элемент позиционируется от 0 до значения ширины или высоты поля canvas (меньше разрешения пикселя). С помощью новой функции мы создадим 1 200 прямоугольников. Сперва, я воспользуюсь функцией из статьи про создание генератора случайных чисел:
1 2 3 |
function getRandomInRange(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } |
Остальной код, как в предыдущем примере:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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 также изменилась:
1 2 3 4 5 6 7 8 9 10 11 |
function drawStatic() { for (var i=0; i < maxPixels; i++){ lum = getRandomInRange(40,80); context.fillStyle = "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); } } |
Результат выглядит немного грубее, и, возможно, больше подходит для анимации. В следующей статье мы анимируем эти помехи.
Источник: //thenewcode.com/
Редакция: Команда webformyself.