
Недавно мне понадобилось реализовать автоматическую генерацию 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';
Создание первого 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. Как следствие — имеет больше возможностей для настройки дизайна и даже анимаций. Но о нем подробнее поговорим уже в следующей статье.
Напишите в комментариях, что думаете насчет такого формата. Хочу время от времени обозревать интересные, но малоизвестные библиотеки, которыми сам пользуюсь.

