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

Напишите в комментариях, что думаете насчет такого формата. Хочу время от времени обозревать интересные, но малоизвестные библиотеки, которыми сам пользуюсь.

Комментарии (0)