ASCII анимация с помощью спрайта, элемента canvas и JavaScript

В данном уроке мы сделаем эффектное преобразование спрайта в анимированную ASCII картинку (то есть в изображение, нарисованное с помощью символов). Для реализации задуманного нам понадобится элемент canavas и несколько строк кода на JavaScript.

Шаг 1. Разметка HTML

Для создания эффекта нам понадобится следующая структура:

<!— Источник изображения для конвертации —> <img src=»/lessons/les1534/img/sprite.png» id=»sprite»/> <div id=»container»> <!— ASCII часть будет выводиться в ниже представленный тег pre —> <pre id=»ascii»></pre> </div>

Изображение содержит исходный спрайт. Весь функционал будет реализован в коде JavaScript, а результат конвертации будет выводиться в элемент ascii.

 

Шаг 2. Создаем временные элемент canvas 

window.onload = function(){ //Переменные для обработки спрайта var sprite = document.getElementById(«sprite»); var W = sprite.width; var H = sprite.height; //Элемент canvas для обработки спрайтов var tcanvas = document.createElement(«canvas»); tcanvas.width = W; tcanvas.height = H; //Размеры элемента canvas такие же, как и у исходного спрайта var tc = tcanvas.getContext(«2d»); //Выводим изображение в элемент canvas tc.drawImage(sprite, 0, 0, W, H); sprite.parentNode.insertBefore(tcanvas, sprite); //одновременно выводятся элемент canvas и исходное изображение }

Скрипт создает элемент canavas и выводит в него и сходный спрайт.

Шаг2. Преобразуем спрайт в серый вариант и готовим ASCII данные

window.onload = function(){ //Внутренние переменные var r, g, b, gray; //Переменные для обработки спрайта var sprite = document.getElementById(«sprite»); var W = sprite.width; var H = sprite.height; //Элемент canvas для обработки спрайтов var tcanvas = document.createElement(«canvas»); tcanvas.width = W; tcanvas.height = H; //Размеры элемента canvas такие же, как и у исходного спрайта var tc = tcanvas.getContext(«2d»); //Выводим изображение в элемент canvas tc.drawImage(sprite, 0, 0, W, H); //Получаем данные о пикселях var pixels = tc.getImageData(0, 0, W, H); var colordata = pixels.data; //Каждый пиксель дает 4 целых числа -> r, g, b, a //Поэтому длина массива colordata будет W*H*4 for(var i = 0; i < colordata.length; i = i+4) { r = colordata[i]; g = colordata[i+1]; b = colordata[i+2]; //Конвертируем цвет в серую шкалу gray = r*0.2126 + g*0.7152 + b*0.0722; //Переписываем массив colordata полученными данными //colordata[i] = colordata[i+1] = colordata[i+2] = gray; } //Выводим серое изображение tc.putImageData(pixels, 0, 0); //Вы можете увидеть серое изображение спрайта //с помощью вставки элемента canvas в структуру DOM sprite.parentNode.insertBefore(tcanvas, sprite); //одновременно выводятся элемент canvas и исходное изображение }

Теперь на основании серого варианта спрайта готовим текст для ASCII картинки. Готовим массив, в котором строчки символов соответствуют строчкам пикселей. На основании значения интенсивности серого цвета выбирается символ. Полученные строки добавляются в структуру DOM.

window.onload = function(){ //Внутренние переменные var r, g, b, gray; var character, line = «»; //Переменные для обработки спрайта var sprite = document.getElementById(«sprite»); var W = sprite.width; var H = sprite.height; //Элемент canvas для обработки спрайтов var tcanvas = document.createElement(«canvas»); tcanvas.width = W; tcanvas.height = H; //Размеры элемента canvas такие же, как и у исходного спрайта var tc = tcanvas.getContext(«2d»); //Выводим изображение в элемент canvas tc.drawImage(sprite, 0, 0, W, H); //Получаем данные о пикселях var pixels = tc.getImageData(0, 0, W, H); var colordata = pixels.data; //Каждый пиксель дает 4 целых числа -> r, g, b, a //Поэтому длина массива colordata будет W*H*4 var ascii = document.getElementById(«ascii»); for(var i = 0; i < colordata.length; i = i+4) { r = colordata[i]; g = colordata[i+1]; b = colordata[i+2]; //Конвертируем цвет в серую шкалу gray = r*0.2126 + g*0.7152 + b*0.0722; //Переписываем массив colordata полученными данными //colordata[i] = colordata[i+1] = colordata[i+2] = gray; //Текст для ascii картинки. //Темные цвета = символы подобные «W», «@» //Светлые цвета = «`», «.» if(gray > 250) character = » «; //Почти белый else if(gray > 230) character = «`»; else if(gray > 200) character = «:»; else if(gray > 175) character = «*»; else if(gray > 150) character = «+»; else if(gray > 125) character = «#»; else if(gray > 50) character = «W»; else character = «@»; //Почти черный //Новые строки и вставка в DOM if(i != 0 && (i/4)%W == 0) //если указатель достиг конца строки { ascii.appendChild(document.createTextNode(line)); //Новая строка ascii.appendChild(document.createElement(«br»)); //Очищаем строку для следующего набора пикселей line = «»; } line += character; } //Выводим серое изображение tc.putImageData(pixels, 0, 0); //Вы можете увидет серое изображение спрайта //с помощью вставки элемента canvas в структуру DOM sprite.parentNode.insertBefore(tcanvas, sprite); //одновременно выводятся элемент canvas и исходное изображение }

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

#ascii { font-family: monospace; font-size: 11px; line-height: 70%; } #sprite { display: none; }

Также отключаем в скрипте вывод элемента canvas.

 

Шаг 5. Анимация

Анимация осуществляется за счет изменения значения левого поля. Полученное изображение смещается и в контейнере с соответствующими свойствами последовательно сменяются кадры.

Контейнер имеет следующие свойства.

#container { overflow: hidden; display: inline-block; }

А в скрипте будут производиться расчеты и установка значений. Для смены кадров используется таймер.

window.onload = function(){ //Внутренние переменные var r, g, b, gray; var character, line = «»; //Переменные для обработки спрайта var sprite = document.getElementById(«sprite»); var W = sprite.width; var H = sprite.height; //Элемент canvas для обработки спрайтов var tcanvas = document.createElement(«canvas»); tcanvas.width = W; tcanvas.height = H; //Размеры элемента canvas такие же, как и у исходного спрайта var tc = tcanvas.getContext(«2d»); //Заполняем элемент canvas белым сплошным полем перед работой с png tc.fillStyle = «white»; tc.fillRect(0, 0, W, H); //Выводим изображение в элемент canvas tc.drawImage(sprite, 0, 0, W, H); //Получаем данные о пикселях var pixels = tc.getImageData(0, 0, W, H); var colordata = pixels.data; //Каждый пиксель дает 4 целых числа -> r, g, b, a //Поэтому длина массива colordata будет W*H*4 var ascii = document.getElementById(«ascii»); for(var i = 0; i < colordata.length; i = i+4) { r = colordata[i]; g = colordata[i+1]; b = colordata[i+2]; //Конвертируем цвет в серую шкалу gray = r*0.2126 + g*0.7152 + b*0.0722; //Переписываем массив colordata полученными данными //colordata[i] = colordata[i+1] = colordata[i+2] = gray; //Текст для ascii картинки. //Темные цвета = символы подобные «W», «@» //Светлые цвета = «`», «.» if(gray > 250) character = » «; //Почти белый else if(gray > 230) character = «`»; else if(gray > 200) character = «:»; else if(gray > 175) character = «*»; else if(gray > 150) character = «+»; else if(gray > 125) character = «#»; else if(gray > 50) character = «W»; else character = «@»; //Почти черный //Новые строки и вставка в DOM if(i != 0 && (i/4)%W == 0) //если указатель достиг конца строки { ascii.appendChild(document.createTextNode(line)); //Новая строка ascii.appendChild(document.createElement(«br»)); //Очищаем строку для следующего набора пикселей line = «»; } line += character; } //Выводим серое изображение //tc.putImageData(pixels, 0, 0); //Вы можете увидет серое изображение спрайта //с помощью вставки элемента canvas в структуру DOM //sprite.parentNode.insertBefore(tcanvas, sprite); //одновременно выводятся элемент canvas и исходное изображение //Анимация var frames = 10; //Спрайт имеет 10 кадров var container = document.getElementById(«container»); //Ширина контейнера должна быть равна только одному кадру var frame_width = parseInt(window.getComputedStyle(container).width)/frames; //window.getComputedStyle поддерживается в Chrome, FF, Opera и IE9+ //Значение ширины имеет «px» в конце, поэтому parseInt используется для удаления суффикса container.style.width = frame_width+»px»; //Будем изменять margin-left элемента ascii для смещения. ascii.style.marginLeft = «0»; setInterval(loop, 1000/10); function loop() { var current_ml = parseFloat(ascii.style.marginLeft); //Если ascii достиг последнего кадра (9-го в нашем случае) //Значение поля нужно установить в 0 //frame_width * (10-1) * -1(так как мы используем отрицательное значение поля) if(current_ml == frame_width*(frames-1)*-1) ascii.style.marginLeft = «0»; else ascii.style.marginLeft = (current_ml — frame_width) + «px»; } }

 

Готово!

Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/qvzUUKScQKs/lessons.php

Источник: lred.ru

Оцените статью
новости для мужчин