В последнее время я все больше замечаю, что сайты уже не представляют собой страницу в браузере, полную квадратов. Все больше и больше дизайнеров рисуют на макетах страниц элементы с причудливой формой, которые могли бы стать настоящей головной болью верстальщика, если бы не JavaScript Canvas.
В этом уроке мы научим вас создавать и анимировать фигуры с эффектом желе. Вы сможете создать желеобразную форму и оживить ее в соответствии с вашими потребностями без особых усилий. В частности, в первой части мы увидим, как добиться следующего результата:
Математический рассчет такого эффекта не простое занятие, поэтому мы попытались сгруппировать код, необходимый для создания и анимации желеобразных форм в простую для использования библиотеку.
В то же время мы были вдохновлены работой Тома Чиоволони и игрой «The Floor is Jelly», поэтому мы специально начали с реализации желеобразной физики.
Результат вылился в библиотеку, которую мы назвали jelly.js, в которую мы добавили все, что нужно, чтобы получить желеобразую форму. Давайте посмотрим, как ее использовать!
Создание фигур с помощью SVG
Мы решили создавать фигуры с помощью SVG, потому что это самый простой способ: мы можем создавать нужные нам формы в векторном редакторе (например, Inkscape или Illustrator) и вставлять их непосредственно в наш HTML-документ или даже импортировать их из JavaScript. Создадим вот такую простую форму в векторном редакторе:
Затем включим соответствующий SVG-код непосредственно в HTML:
<!-- SVG в форме пятиугольника -->
<!-- Обратите внимание на свойство `display: none`: мы не хотим показывать SVG,
нам нужно получить путь с помощью JavaScript -->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="400" style="display: none">
<path id="pentagon-path" d="m200 97.218 108.07 78.524-41.28 127.04h-133.58l-41.281-127.04z"/>
</svg>
Настройка HTML разметки
Нам также потребуется canvas, чтобы нарисовать фигуру и другие элементы с целью перемещения буквы «S» относительно средней точки формы.
<div class="jelly-container">
<!-- Холст для рисования желеобразного Пентагона) -->
<canvas class="jelly-canvas"></canvas>
<!-- Текст в центре тяжести фигуры -->
<div class="centroid-container">
<div class="centroid-text">S</div>
</div>
</div>
Немного CSS
Для этого примера нам нужно совсем CSS стилей:
/* Основные стили */
html, body {
margin: 0;
}
body {
background-color: #D98327;
overflow: hidden;
}
/* Стили для желе */
.jelly-container {
position: relative;
display: inline-block;
left: 50%;
margin-left: -200px;
}
.jelly-container, .jelly-canvas {
width: 400px;
height: 400px;
}
/* Важно спозиционировать `.centroid-container` в верхнем левом углу.
Так `.centroid-text` будет расположен в центре (с JavaScript) */
.centroid-container {
position: absolute;
left: 0;
top: 0;
transform: translate(-50%, -50%);
pointer-events: none;
}
.centroid-text {
font-size: 100px;
color: white;
}
Давайте сделаем желе
Наконец, мы подошли к самой интересной части! Давайте нарисуем наш пятиугольник на canvas и анимируем его. Не беспокойтесь, - это будет очень просто с помощью нашей библиотеки.
Нам просто нужно несколько строк кода, чтобы нарисовать наш пятиугольник и заставить его пенять форму, если мы переместим мышь к краям фигуры:
/* Опции настройки */
var options = {
paths: '#pentagon-path', // Форма, которую мы хотим нарисовать
pointsNumber: 10, // Количество точек
maxDistance: 70, // Максимальное расстояние между точками
color: '#5C1523',
centroid: '.centroid-text' // Элемент для перемещения относительно центра тяжести
// debug: true // Раскомментируйте эту строку, чтобы увидеть точки
};
/* Инициализация */
var jelly = new Jelly('.jelly-canvas', options);
Обратите внимание, что конструктор нашей библиотеки (jelly.js) получает элемент canvas и набор опций. Мы также можем предоставить массив опций или набор параметров для каждой фигуры, которую мы хотим рисовать. Подробное описание доступных опций вы можете проверить на Github репозитории.
Можно было бы оставить так и ничего не менять, но у нашей библиотеки еще есть огромный потенциал. Итак, давайте посмотрим, что мы еще можем сделать.
Внедрение желеобразного перетаскивания
Чтобы проиллюстрировать немного больше возможностей, которые у нас есть (и для удовольствия), давайте посмотрим, как мы можем поколебать наш пятиугольник, когда мы перетаскиваем его по экрану. Для этого нам нужно знать, когда указатель мыши находится внутри формы, чтобы перетащить ее только в этом случае. Взгляните на следующий код:
/* Проверяем элемент (фигуру) при наведении курсора и обновляем указатель */
var container = document.querySelector('.jelly-container');
var hoverIndex = -1;
function checkHover() {
// Функция `getHoverIndex` вернет индекс формы,
на которую наводится курсор, или -1
hoverIndex = jelly.getHoverIndex();
container.style.cursor = hoverIndex === -1 ? 'default' : 'pointer';
window.requestAnimationFrame(checkHover);
}
window.requestAnimationFrame(checkHover);
Давайте посмотрим, как мы можем реализовать базовую логику перетаскивания. Пожалуйста, ознакомьтесь с комментариями, чтобы разобраться в происходящем и обратите особое внимание на функцию shake:
/* Перетаскивание */
var startX, startY, dx, dy, endX = 0, endY = 0, x = 0, y = 0, lastX = 0, lastY = 0;
var down = false;
// Это будет максимальное расстояние для встряхивания
var shakeLimit = 5;
container.addEventListener('mousedown', function (e) {
if (hoverIndex >= 0) {
startX = e.clientX;
startY = e.clientY;
down = true;
}
});
document.addEventListener('mousemove', function (e) {
if (down) {
x = e.clientX - startX;
y = e.clientY - startY;
container.style.transform = 'translate(' + (endX + x) + 'px, ' + (endY + y) + 'px)';
dx = x - lastX;
dy = y - lastY;
if (dx > shakeLimit || dx < - shakeLimit) dx = dx < 0 ? - shakeLimit : shakeLimit;
if (dy > shakeLimit || dy < - shakeLimit) dy = dy < 0 ? - shakeLimit : shakeLimit;
// Функция `shake` будет «перемещать» половину точек (поочередно) на заданное расстояние
jelly.shake({x: - dx, y: - dy});
lastX = x;
lastY = y;
}
});
function mouseUp() {
if (down) {
down = false;
endX += x;
endY += y;
}
}
document.addEventListener('mouseup', mouseUp);
document.addEventListener('mouseout', function (e) {
if (e.target.nodeName == 'HTML') {
mouseUp();
}
});
Все современные браузеры поддерживают canvas, но jelly.js использует промисы, поэтому вам потребуется полиполк для браузеров, которые не поддерживает промисы.
Производительность эффекта варьируется в зависимости от браузеров и операционных систем. Это связано с интенсивной работой процессора в каждом анимационном кадре, поэтому не злоупотребляйте использованием этих эффектов на сайте.
Заключение
Мы создали поистине желеобразный пятиугольник без особых усилий. Наша форма также изменяет курсор при наведении и реагирует на перетаскивание! Результат вы можете увидеть здесь или скачать и протестировать локально.
Это не единственное, что мы можем сделать. Во второй части нашего урока мы построим удивительный слайдер, где все будет одно сплошное желе. В общих чертах мы узнаем, как:
- Нарисовать больше желе-форм и текст!
- Использовать изображения внутри фигур, а не только сплошные цвета.
- Анимировать фигуры, чтобы показать их или плавно скрыть.
- Менять форму желе.
- Сделать весь слайдер адаптивным.