
Недавно мне понадобилось реализовать автоматическую генерацию QR для личного проекта. Идея простая: пользователь нажимает на кнопку «Пригласить друга», а небольшая функция на JavaScript закидывает в буфер обмена реферальную ссылку.
Все было бы хорошо, но нужно было добавить попап с QR-кодом, который при сканировании перекидывает по ранее полученной ссылке. И так как писать собственное решение было сомнительной идеей, пришлось использовать библиотеку — QRious. В этой статье расскажу, как с ней работать.
Почему не QRickit
QRious генерирует QR-коды прямо в браузере, без использования внешнего API. Хорошо это или плохо — вопрос с подвохом. Например, есть старые добрые Google Chart API и QRickit. Наверное, кто-то сочтет такой подход удобнее, но для меня автономность и скорость генерации важнее. Поэтому предпочитаю решения вроде QRious.

Начало работы с QRious
Установка
Библиотеку QRious можно подключить несколькими способами: через CDN и npm.
Способ через CDN:
<script src="https://cdn.jsdelivr.net/npm/qrious/dist/qrious.min.js"></script>
Способ через npm:
npm install qrious
import QRious from 'qrious';

30+ бесплатных курсов на IT-темы в Академии Selectel
Для начинающих и опытных специалистов.
Создание первого QR-кода
QRious работает с канвасами, поэтому в коде HTML-страницы нужно добавить блок, в который будет грузиться сам QR-код:
<canvas id="qrcode"></canvas>
Затем в JavaScript нужно инициализировать объект QRious и задать необходимые параметры:
const qr = new QRious({
element: document.getElementById('qrcode'),
value: 'https://habr.com/ru/users/marmash/', // данные для кодирования
size: 200 // размер изображения в пикселях
});
Теперь на странице появится QR-код, который при сканировании откроет указанный URL.

Напомню, что в качестве данных для кодирования может выступать не только ссылка, но и текст, контактные данные и тому подобное.
Расширенная генерация кодов
Приятная фича — наличие модификаций QR-кодов. В момент инициализации объекта QRious можно задать не только размер canvas, но и цвет кода, цвет бэкграунда и уровень коррекции ошибок (L, M, Q, H).
Честно говоря, я даже не знал, что из себя представляет последняя опция. Но если коротко, то уровень коррекции ошибок определяет, какая доля информации в коде может быть восстановлена при повреждении или частичном затуманивании. Чем выше уровень, тем больше данных может быть восстановлено, но при этом увеличивается размер QR-кода, так как добавляется больше избыточной информации.
Разные уровни коррекции ошибок:

Вернемся к параметрам инициализации. Пояснения в комментариях к коду.
const qr = new QRious({
element: document.getElementById('qrcode'),
value: 'https://habr.com/ru/users/marmash/',
size: 250,
background: 'red',
foreground: 'blue',
level: 'H'
});
Разукрашенный QR-код:

Еще можно вместо «однозначных цветов» использовать палитру RGBa, HEX, к сожалению, не поддерживается QRious.

Кастомизация через Canvas
Сегодня сложно найти интерфейс без скруглений. Мне нужно было, чтобы элементы QR-кода были скруглены, как и все остальные блоки. Не нравилось только одно: на этапе инициализации объема QRious задать скругления нельзя.
Зато можно переопределить или подстроить процесс рисования каждого квадрата QR-кода. Вместо стандартного fillRect, использовать arc и fill для рисования закругленных прямоугольников. QRious как раз позволяет получить матрицу данных (modules) — массив, где каждый элемент — это 0 или 1, открытый или закрытый модуль (квадрат) соответственно.
const qr = new QRious({ value: 'https://habr.com/ru/users/marmash/' });
const modules = qr._o.modules; // массив данных о модулях
Обратите внимание: использование приватных свойств (_o) не рекомендуется, так как они могут измениться в будущих версиях.
Дальше можно, изменяя свойства отдельных модулей, отрисовать QR-код с закруглениями.
const size = 200; // размер canvas
const ctx = document.getElementById('qrcode').getContext('2d');
const qr = new QRious({ value: 'https://habr.com/ru/users/marmash/', size: size });
const modules = qr._o.modules;
const moduleCount = modules.length;
const cellSize = size / moduleCount;
const radius = 3; // радиус скругления
// Очистка канваса
ctx.clearRect(0, 0, size, size);
// Рисуем модули с закругленными углами
for (let r = 0; r < moduleCount; r++) {
for (let c = 0; c < moduleCount; c++) {
if (modules[r][c]) {
const x = c * cellSize;
const y = r * cellSize;
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + cellSize - radius, y);
ctx.quadraticCurveTo(x + cellSize, y, x + cellSize, y + radius);
ctx.lineTo(x + cellSize, y + cellSize - radius);
ctx.quadraticCurveTo(x + cellSize, y + cellSize, x + cellSize - radius, y + cellSize);
ctx.lineTo(x + radius, y + cellSize);
ctx.quadraticCurveTo(x, y + cellSize, x, y + cellSize - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
ctx.fillStyle = '#000'; // цвет блока
ctx.fill();
}
}
}
Но с новыми версиями QRious такое, увы, не пройдет. Свойство _o и метод modules были сделаны приватными или изменены, и напрямую получить матрицу стало сложнее или невозможно без модификации библиотеки. Поэтому для подобной кастомизации вам нужно либо использовать версию v4.0.2, либо альтернативное решение.
Подключение QRious v4.0.2:
<script src="https://cdn.jsdelivr.net/npm/qrious@4.0.2/dist/qrious.min.js">
Альтернативные решения
Сам по себе QRious очень простой инструмент без излишеств. Единственное, чего не хватает, — простой настройки геометрии кодов.
Если вы ищете альтернативных решений, обратите внимание на qrcode.js, QRCode-generator, kjua или EasyQRCodeJS. В сущности они все похожи, но EasyQRCodeJS поддерживает не только Canvas, но и SVG. Как следствие — имеет больше возможностей для настройки дизайна и даже анимаций. Но о нем подробнее поговорим уже в следующей статье.
Напишите в комментариях, что думаете насчет такого формата. Хочу время от времени обозревать интересные, но малоизвестные библиотеки, которыми сам пользуюсь.