@schaukel/qr
v0.0.1
Published
Reusable Vue component and canvas API for generating styled QR codes.
Readme
@schaukel/qr
Reusable Vue component and canvas API for generating styled QR codes.
This package is a reusable library version of Anthony Fu's qrcode-toolkit. It extracts the QR code renderer into a component and programmatic API that can be embedded in other Vue apps.
I really wanted to have this, but I couldn't justify the time it would take to extract all the relevant bits from the original, so this was mostly created with Codex 5.5.
Installation
bun add @schaukel/qrVue 3 is a peer dependency.
Vue Component
<script setup lang="ts">
import { QRCodeGenerator } from "@schaukel/qr"
function onGenerated(result) {
console.log(result.dataUrl, result.info)
}
</script>
<template>
<QRCodeGenerator
text="https://qrcode.antfu.me/"
:scale="12"
pixel-style="rounded"
marker-shape="circle"
marker-inner-shape="circle"
@generated="onGenerated"
/>
</template>QRCodeGenerator renders a single <canvas> and accepts every
QRCodeGeneratorOptions field as an optional prop. Vue kebab-case props work
in templates, for example pixel-style maps to pixelStyle.
Events
generated(result: QRCodeRenderResult)- emitted after the QR code is drawn.error(error: unknown)- emitted if rendering fails.
Exposed Methods
Use a template ref to access the component instance:
<script setup lang="ts">
import { QRCodeGenerator } from "@schaukel/qr"
import { ref } from "vue"
const qr = ref<InstanceType<typeof QRCodeGenerator>>()
function download() {
qr.value?.download("qr.png")
}
</script>
<template>
<QRCodeGenerator ref="qr" text="https://example.com" />
<button type="button" @click="download">Download</button>
</template>Available exposed members:
canvas- the underlyingHTMLCanvasElementref.generate()- redraws the QR code and returnsPromise<QRCodeRenderResult>.toDataURL(type?, quality?)- proxiescanvas.toDataURL(...).download(filename?)- downloads the generated QR code as a PNG.
Programmatic API
Use generateQRCode when you already manage the canvas yourself.
import { generateQRCode } from "@schaukel/qr"
const canvas = document.querySelector("canvas")!
const result = await generateQRCode(canvas, {
text: "https://example.com",
scale: 8,
margin: 2,
pixelStyle: "squircle",
markerShape: "octagon",
markerInnerShape: "diamond",
})
console.log(result.dataUrl)generateQRCode(canvas, options?)
function generateQRCode(
canvas: HTMLCanvasElement,
options?: QRCodeGeneratorProps,
): Promise<QRCodeRenderResult>The function draws into the provided canvas, resizes it to the generated QR dimensions, and returns render metadata.
Options
All options are optional. Missing values are filled by
defaultQRCodeGeneratorOptions() and can be normalized with
resolveQRCodeGeneratorOptions(props).
| Option | Type | Default |
| ------------------------------ | -------------------------------------------------------- | -------------- |
| text | string | "" |
| ecc | "L" \| "M" \| "Q" \| "H" | "M" |
| margin | number \| { top, right, bottom, left } | 2 |
| scale | number | 20 |
| lightColor | string | "#ffffff" |
| darkColor | string | "#000000" |
| pixelStyle | PixelStyle | "rounded" |
| markerStyle | PixelStyle \| "auto" | "auto" |
| markerShape | MarkerShape | "square" |
| markerInnerShape | MarkerInnerShape \| "auto" | "auto" |
| markerSub | MarkerShape | "square" |
| markers | QRCodeGeneratorMarkerOptions[] | [] |
| maskPattern | number | -1 |
| minVersion | number | 1 |
| maxVersion | number | 40 |
| boostECC | boolean | false |
| rotate | 0 \| 90 \| 180 \| 270 | 0 |
| invert | boolean | false |
| marginNoise | boolean | false |
| marginNoiseRate | number | 0.5 |
| marginNoiseOpacity | number \| [number, number] | 1 |
| seed | number | random integer |
| marginNoiseSpace | "none" \| "marker" \| "full" \| "minimal" \| "extreme" | "marker" |
| renderPointsType | "all" \| "data" \| "function" \| "guide" \| "marker" | "all" |
| effect | "none" \| "crystalize" \| "liquidify" | "none" |
| effectTiming | "before" \| "after" | "after" |
| effectCrystalizeRadius | number | 8 |
| effectLiquidifyDistortRadius | number | 8 |
| effectLiquidifyRadius | number | 8 |
| effectLiquidifyThreshold | number | 128 |
| backgroundImage | string \| undefined | undefined |
| transformPerspectiveX | number | 0 |
| transformPerspectiveY | number | 0 |
| transformScale | number | 1 |
Style Constants
The package exports the option value lists for building controls:
import {
MarkerInnerShapes,
MarkerShapes,
MarkerSubShapes,
PixelStyles,
} from "@schaukel/qr"PixelStyles:square,rounded,dot,squircle,row,columnMarkerShapes:square,circle,plus,box,octagon,random,tiny-plusMarkerSubShapes:square,circle,box,random,plusMarkerInnerShapes:square,circle,plus,diamond,eye
Types
import type {
MarginObject,
MarkerInnerShape,
MarkerShape,
PixelStyle,
QRCodeGeneratedInfo,
QRCodeGeneratorMarkerOptions,
QRCodeGeneratorOptions,
QRCodeGeneratorProps,
QRCodeRenderResult,
QRCodeWarning,
QRCodeWarningCode,
} from "@schaukel/qr"QRCodeRenderResult contains:
canvas- the canvas that was rendered.dataUrl- PNG data URL for the rendered QR code.info- generated dimensions.options- fully resolved render options.qrcode- the underlyinguqrgeneration result.warnings- scanability and transform warnings.
Development
bun install
bun run play
bun run test
bun run build