Когда последний раз вам приходилось копаться в исходниках библиотеки для генерации QR-кодов? Я — на прошлой неделе. Поводом стал типичный кейс: клиенту нужно встроить QR в интерфейс, но с нестандартным дизайном — градиенты, логотипы, анимированные паттерны.
Почему не qrcode.react?
Начну с боли: большинство React-библиотек для QR либо рендерят через canvas (что убивает кастомизацию), либо представляют собой чёрный ящик с ограниченными возможностями стилизации. Популярный qrcode.react хоть и использует SVG, но:
- Не даёт доступа к отдельным модулям QR (позиционные маркеры, тайминг-линии)
- Генерирует монолитный path, где нельзя точечно менять стили
- Имеет скрытые зависимости типа qr.js
Мой эксперимент начался с вопроса: а что если собрать велосипед, но с правильной геометрией руля?
Архитектура кастомного решения
Библиотека строится вокруг трёх ключевых принципов:
- Чистый SVG — никакого canvas для максимальной гибкости
- Нулевые зависимости — даже QR-энкодер написан с нуля
- Компонентный подход — каждый элемент QR-кода доступен для кастомизации
Вот как выглядит базовый пример использования:
<QRCode
value="https://frontend.tools"
modules={({ x, y }) => (
<rect
x={x}
y={y}
width={1}
height={1}
fill={Math.random() > 0.5 ? '#f00' : '#00f'}
/>
)}
/>
Где modules — render-prop для точечного управления отрисовкой каждого модуля QR-кода. Для сравнения, в других библиотеках вам бы пришлось перекрывать элементы через CSS хаки или постобработку SVG.
Под капотом энкодера
Самая интересная часть — реализация алгоритма QR-кодирования. Вот что пришлось учесть:
- Поддержка разных уровней коррекции ошибок (L, M, Q, H)
- Генерация масок с оптимальным penalty score
- Добавление служебной информации (версия, формат)
Особенность моего подхода — разделение логики и представления. Энкодер возвращает чистую матрицу данных, которую затем можно рендерить любым способом:
const matrix = encodeQR('Hello world', { errorCorrection: 'H' });
// matrix = [[0,1,0,1,...], ...]
Это открывает возможности для:
- Анимации через GSAP или Framer Motion
- Кастомных паттернов заливки
- Динамического изменения уровня коррекции
Производительность и ограничения
На практике столкнулся с двумя проблемами:
- Рендер крупных QR-кодов (версия 40) — React начинает тормозить при 2000+ модулях. Решение — виртуализация через react-window.
- Генерация в Web Worker — энкодинг сложных payloads может блокировать UI. Вынес обработку в worker-ы, но это усложнило bundle.
Неожиданно полезным оказался прием с memoization компонентов модулей — это дало +15% к скорости рендера при частых обновлениях.
Когда стоит брать этот подход
Моя библиотека — не замена готовым решениям, а инструмент для специфичных кейсов:
- Нестандартный дизайн QR-кодов
- Интерактивные элементы (hover, click на отдельных модулях)
- Встраивание в сложные SVG-сцены
- Обучение (код энкодера хорошо документирован)
Если же вам нужно просто быстро вставить стандартный QR — возможно, лучше взять проверенную библиотеку. Но когда требования выходят за рамки обычного — приходится писать свой код. И да, это того стоило.
P.S. Демо с живыми примерами кастомизации: qrcode.ttsalpha.com. Критика и пул-реквесты приветствуются — особенно по части оптимизации энкодера.
Источник: https://qrcode.ttsalpha.com