Саморисующийся штрих-код

Не все штрих-коды в итоге печатаются, некоторые просто отображаются в браузере. Есть два основных способа их получения:

Для обоих методов существует множество библиотек и фреймворков, но здесь мы предлагаем реализацию клиентского рендеринга без фреймворков с помощью саморисующегося автономного SVG-файла.

Да, встроив Javascript-код в SVG-файл, можно заставить его рисовать себя.

Этот метод широко используется для SVG-анимации, но не для штрих-кодов. Исправим это! В итоге получится единый саморисующийся автономный SVG-файл для QR-кодов, как на примере ниже:

Вот код, использованный для отображения:

<object data="qr.min.svg?data=hello, world" type="image/svg+xml" width="200" height="200">
</object>

Файл qr.min.svg весит всего около 17 КБ и содержит всё необходимое для рисования QR-кодов. Интересно? Сделаем это пошагово!

Простой SVG-файл

Вот очень простой SVG-файл, который мы будем использовать как шаблон:

<?xml version="1.0" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
	<g id="qrcode">
			<line x1="0" y1="0" x2="200" y2="200" width="1" stroke="red"/>
			<line x1="0" y1="200" x2="200" y2="0" width="1" stroke="red"/>
	</g>
</svg>

А вот как это выглядит:

Изображение состоит из двух красных линий, заданных элементами <line> в коде SVG. Теперь изменим файл, добавив Javascript для программной генерации линий:

<?xml version="1.0" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
	<g id="qrcode"/>
	
	<script type="application/javascript">//<![CDATA[

			function line(el, x1, y1, x2, y2, width, color) {
				const nl = document.createElementNS("http://www.w3.org/2000/svg","line");
				nl.setAttribute("x1", x1);
				nl.setAttribute("y1", y1);
				nl.setAttribute("x2", x2);
				nl.setAttribute("y2", y2);
				nl.setAttribute("width", width);
				nl.setAttribute("stroke", color)
				el.appendChild(nl);
			}

			const elem = document.getElementById("qrcode");
			line(elem, 0, 0, 200, 200, 1, "red");
			line(elem, 0, 200, 200, 0, 1, "red");

	//]]>
	</script>
</svg>

Код стал гораздо длиннее, но хотя результат выглядит так же:

со скриптами можно делать гораздо больше. Например, если заменить последние три строки на:

const elem = document.getElementById("qrcode");
for (let i = -200; i < 200; i += 10) {
	line(elem, 0, 0 + i, 200, 200 + i, 1, "red");
	line(elem, 0, 200 + i, 200, 0 + i, 1, "red");
}

получится сетка из линий, нарисованная самим SVG-файлом:

Теперь сделаем это немного более интерактивным…

Разбор входных параметров

Изображение с сеткой выше отображается в HTML так:

<object data="qr-3.svg" type="image/svg+xml" width="200" height="200"></object>

Обратите внимание: атрибут data указывает на созданный нами SVG-файл. Но, как и с любым другим HTML-ресурсом, после имени файла можно передать параметры:

<object data="qr-3.svg?color=green" type="image/svg+xml" width="200" height="200"></object>

Здесь мы передали параметр color со значением green. Теперь прочитаем его внутри SVG-файла. Понадобится такой код:

const params = new URLSearchParams(window.location.search);
const color = params.get("color");

Первая строка считывает все параметры, переданные SVG-файлу, а вторая извлекает параметр color.

Теперь заменим последний сниппет, рисующий сетку, на:

const params = new URLSearchParams(window.location.search);
const color = params.get("color");
const elem = document.getElementById("qrcode");
for (let i = -200; i < 200; i += 10) {
	line(elem, 0, 0 + i, 200, 200 + i, 1, color);
	line(elem, 0, 200 + i, 200, 0 + i, 1, color);
}

и вызовем так:

<object data="qr-4.svg?color=orange" type="image/svg+xml" width="200" height="200"></object>

результат:

Итак, мы можем считывать входные параметры и рисовать произвольные фигуры с помощью Javascript прямо в SVG-файле без каких-либо зависимостей. Теперь мы готовы нарисовать QR-код!

Рисование QR-кода

Не будем изобретать велосипед и просто используем существующую библиотеку Javascript для рисования QR-кодов от Kazuhiko Arase.

Понадобится функция для рисования закрашенных прямоугольников:

function rect(el, x, y, width, height, color) {
	const rc = document.createElementNS("http://www.w3.org/2000/svg", "rect");
	rc.setAttribute("x", x);
	rc.setAttribute("y", y);
	rc.setAttribute("width", width);
	rc.setAttribute("height", height);
	rc.setAttribute("fill", color)
	el.appendChild(rc);
}

Основной код рисования выглядит так:

const elem = document.getElementById("qrcode");
const width = 200, height = 200;

const params = new URLSearchParams(window.location.search);
const data = params.get("data");

const cl = QRErrorCorrectLevel.H;
const qr = new QRCodeModel(_getTypeNumber(data, cl), cl);
qr.addData(data);
qr.make();

const count = qr.getModuleCount();
const cw = Math.floor(width / count);
const ch = Math.floor(height / count);

for (let row = 0; row < count; row++) {
	for (let col = 0; col < count; col++) {
		if (qr.isDark(row, col)) {
			rect(elem, col * cw, row * ch, cw, ch, "black");
		}
	}
}

Много кода, но на самом деле всё просто: читаем содержимое штрих-кода из параметра, создаём генератор QR-кода из библиотеки и проходим по всем ячейкам, проверяя, нужно ли их закрашивать.

Реальный Javascript-код содержит дополнительную проверку ошибок. Его можно посмотреть здесь: qr.svg, или минифицированную версию: qr.min.svg.

Вот несколько примеров использования этого SVG-файла:

// Точка доступа Wi-Fi
// WIFI:S:$SSID;P:$PASSWORD;;
<object data="qr.min.svg?data=WIFI:S:My Network;P:My Password;;" type="image/svg+xml" width="200" height="200"></object>

// Номер телефона
// tel:+NNNNNNNNNNNN
<object data="qr.min.svg?data=tel:+1234567890" type="image/svg+xml" width="200" height="200"></object>

// Координаты на карте
// geo:+XXX,-YYY
<object data="qr.min.svg?data=geo:48.858222,2.2945" type="image/svg+xml" width="200" height="200"></object>

То есть всё, что угодно можно представить в виде QR-кода с помощью этого SVG-файла с нужным параметром. Никаких библиотек, фреймворков, обслуживания — просто один SVG-файл, рисующий себя. Кстати, печать тоже поддерживается.

Ограничения

Очевидное ограничение — для работы метода в браузере должен быть включён Javascript. Здесь вы сами решаете, нужно ли резервное решение, но если браузер не поддерживает скрипты, на месте QR-кода будет просто пустое место. Никаких ошибок, никаких некорректных данных. Если код не главное на странице, можно оставить как есть.

Другое ограничение — SVG-файлу нужен браузер для работы. При открытии в просмотрщике, загрузке в векторный редактор или любое другое приложение он ничего не покажет. Без браузера скрипт не выполняется, и содержимое не рисуется.

Наконец, как вы, вероятно, уже заметили, для отображения SVG-файла нужен тег <object>, а не <img>. Проблема в том, что браузеры не выполняют скрипты внутри SVG-файлов, загруженных как изображения, поэтому при загрузке через <img> будет пустое место. Вот почему нужен <object>.

Можно ли использовать этот SVG?

Конечно, вы можете использовать файл как есть или вносить нужные изменения. Пожалуйста, сохраняйте исходные авторские права из уважения к чужой работе. Вот ссылки ещё раз: qr.svg, qr.min.svg.

Тот же подход используется в нашем бесплатном онлайн-генераторе QR-кодов.

Больше Информации о Barcode

Инсталляция

Основы

Штрих-коды EAN

Штрих-коды UPC

Штрих-коды NDC

QR Коды

Другие Штрих-коды

Экспорт

Автоматизация

Другое