Интерактивный текст на HTML5
Очень необычно и красиво сделанный интерактивный типографический эффект с использованием canvas. Будем создавать динамические баннеры, для оживления сайта. Работать будет по разному и не во всех браузерах.
HTML
Структура html очень проста, так как всю работу будем делать в jаvascript с canvas:
<canvas id="banner"></canvas>
JS
Всё будет реализовано на jаvascript, но прежде всего мы должны проверить, использует ли наш пользователь современный браузер, который поддерживает элемент canvas.
Если canvas не поддерживается, то нужно придумать, как сделать для такого случая статическое изображение. Для проверки используем Modernizr - http://www.modernizr.com/
Переменные
Начнем с определения нескольких переменных:
//Слова для написания на баннере
var keyword = "PCVECTOR",
canvas, context,
bgCanvas, bgContext,
density = 13,
particles = [],
colour = '#fff0a4',
mouse = {
x: 0,
y: 0
},
isDrawing = false,
canvasW, canvasH;
Опишу немножко что тут написано:- keyword - это слово, которое будем выводить на экран в нашем баннере.
- canvas - переменная, которая будет содержать элемент html canvas. Значение будет присвоено позже.
- context - то, что позволяет нам нарисовать и написать на canvas.
- density - переменная плотности, содержащая количество пикселей (и горизонтально и вертикально), которое будет между каждой частицей баннера.
- particles - массив частиц, который будет хранить все частицы и их настройки.
- colour - цвет, который будет иметь каждая частица.
- isDrawing - позволяет определить, находится ли курсор над баннером.
- canvasW, canvasH - ширина и высота холста соответственно.
Установка баннера
Первым шагом будет вызов функции reload (перезагрузка), которую также будет использовать для изменения размеров окна:
this.initialize = function(canvas_id) {
reload(canvas_id);
window.onresize = function(event) {
reload(canvas_id);
}
};
В функции reload мы инициализируем canvas и context и устанавливаем соответствующие размеры. Затем мы вызываем prepare, setupParticles и draw функции.
var reload = function(canvas_id) {
canvas = document.getElementById(canvas_id);
if (!window.HTMLCanvasElement) return false;
context = canvas.getContext('2d');
canvasW = window.innerWidth;
canvasH = 300;
canvas.width = canvasW;
canvas.height = canvasH;
bgCanvas = document.createElement('canvas');
bgContext = bgCanvas.getContext('2d');
bgCanvas.width = canvasW;
bgCanvas.height = canvasH;
prepare();
setupParticles();
draw();
};
Первое, что следует отметить, то что функция принимает строковую (string) переменную, которая должна соответствовать ID элемента в HTML. В нашем случае мы передали бы "canvas-banner".Как вы можете заметить, и фон холста и основной холст имеют один и тот же установленный размер.
Фон холста
Итак, фон холста - тут мы будем печатать текст, или изображения.
var prepare = function() {
//Выбираем шрифт, и размер, какой хотим.
bgContext.font = "300px 'Jockey One'";
//Заполняем текст keyword на холсте.
bgContext.fillText(keyword, (canvasW / 2) - (Math.round(bgContext.measureText(keyword).width / 2)), 260);
};
Команда filltext принимает три параметра: первый - текст для записи, второй и третий - координаты по X и Y.Далее мы создадим наши частицы. Они будут вскоре выведены на основном холсте(canvas), но пока, мы только сохраним их в нашем массиве частиц:
var setupParticles = function() {
particles = [];
//Объявляем наши локальные переменные
var imageData, image_Data,
pixel,
width = 0,
i = 0,
slide = false;
//Получаем данные изображения - от (0,0) до краев хоста
imageData = bgContext.getImageData(0, 0, canvasW, canvasH);
image_Data = imageData.data;
for (var height = 0; height < canvasH; height += density) {
++i;
slide = ((i % 2) == 0);
width = 0;
if (slide == true) {
width += 6;
}
//Выполнение итераций горизонтально по данным изображения.
for (width; width < canvasW; width += density) {
//Определение местоположения пикселя согласно нашей текущей итерации.
pixel = image_Data[((width + (height * canvasW)) * 4) - 1];
//Pixel has been drawn on.
if (pixel == 255) {
//Добавление координат и цвета нашему массиву частицы.
particles.push({
colour: colour,
x: width,
y: height
});
}
}
}
};
Пробежимся теперь по этому блоку кода:Действительно, всё, что мы делаем, является цикличным выполнением по каждому n-ому пикселю, где n - это density - плотность, указанная при старте.
getImageData принимает четыре значения, X и Y верхнего левого угла, так же как для нижнего правого. В нашем случае мы передали два нуля (самое верхнее левое) и ширина и высота холста, которые являются координатами самого нижнего правого угла. Всё это возвращает очень большой список, содержащий данные цвета каждого отдельного пикселя на холсте. Почему мы умножаем на 4? Потому что в переделах этого списка, каждый пиксель представлен четырьмя значениями: красным, зеленым, синим и альфа-значением.
И наконец, мы положили X и Y координаты в простой словарь, который будем теперь использовать, чтобы нарисовать наш баннер.
Рисование баннера
Здесь, мы наконец всё объединяем вместе. С нашим списком X и Y позиций, сохраненных в массиве частиц, мы можем нарисовать баннер.
var draw = function() {
context.clearRect(0, 0, canvasW, canvasH);
var dx, dy, sqrDist,
scale = 1;
for (var i = 0, len = particles.length; i < len; ++i) {
...
context.beginPath();
context.moveTo(x, y - height / 2);
context.lineTo(x + width / 2, y - height / 4);
context.lineTo(x + width / 2, y + height / 4);
context.lineTo(x, y + height / 2);
context.lineTo(x - width / 2, y + height / 4);
context.lineTo(x - width / 2, y - height / 4);
context.lineTo(x, y - height / 2);
context.closePath();
context.fill();
}
};
Мы циклично проходим через каждую из частиц, сохраненную ранее, чтобы выбрать цвет и нарисовать форму по точкам (x,y).Со всем этим у нас теперь есть простой статический баннер... теперь придадим ему интерактивности.
Добавление интерактивности
Первой "плюшкой", которую будем делать, станет путь пользовательского курсора при наведении на баннер.
var mouse = {x:0, y:0, o: false};
mouse - переменная, будет обновлена двумя функциями, одна отслеживающая перемещения и другая, отслеживание того, покинул ли курсор элемент canvas.var MouseMove = function(e) {
mouse.x = e.offsetX || (e.layerX - canvas.offsetLeft);
mouse.y = e.offsetY || (e.layerY - canvas.offsetTop);
if (!isDrawing) {
isDrawing = true;
drawTimeout = setTimeout(function() {
draw();
isDrawing = false;
}, 60);
}
};
var MouseOut = function(e) {
isDrawing = false;
clearTimeout(drawTimeout);
draw();
};
Чтобы заставить их работать, мы так же должны прикрепить события jаvascript к нашему элементу canvas. Они сразу вернутся в нашу функция reload.canvas.addEventListener('mousemove', MouseMove, false);
canvas.addEventListener('mouseout', MouseOut, false);
Теперь, когда мы можем отследить мышь(курсор), мы должны немного изменить нашу функцию draw, основываясь на том, как мы хотим взаимодействовать с мышью....
var p = particles[i];
dx = p.x - mouse.x;
dy = p.y - mouse.y;
// расстояние от мыши до частицы
sqrDist = Math.sqrt(dx * dx + dy * dy);
(isDrawing) ? scale = Math.max(Math.min(3 - (sqrDist / 10), 10), 1): scale = 1;
var width = density / scale - 4,
height = density,
x = p.x,
y = p.y;
context.fillStyle = p.colour;
...
Выше, мы вычисляем расстояние между текущей частицей и мышью и обновляем переменную scale масштаба.Добавление цвета
У нас уже есть аккуратный рабочий баннер, добавим ка ему немного цвета. К счастью, мы уже большую часть работы выполнили, и только изменим две строчки.
//Переменная для хранения каждого из цветов, которые будем использовать.
var colors = ['#fff0a4', '#ffe98f', '#ffcf52', '#fbad1d', '#c48d1c'];
...
//Создавая частицы, мы присваиваем цвет из этого списка.
color: colors[Math.floor(Math.random() * colors.length)],
Вот мы наконец и сделали это! Уникальный, генерируемый и красочный баннер. Посмотрите Демо, там несколько примеров использования данного метода.Удачи.