Skip to content

Repository files navigation

@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/qr

Vue 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 underlying HTMLCanvasElement ref.
  • generate() - redraws the QR code and returns Promise<QRCodeRenderResult>.
  • toDataURL(type?, quality?) - proxies canvas.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, column
  • MarkerShapes: square, circle, plus, box, octagon, random, tiny-plus
  • MarkerSubShapes: square, circle, box, random, plus
  • MarkerInnerShapes: 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 underlying uqr generation result.
  • warnings - scanability and transform warnings.

Development

bun install
bun run play
bun run test
bun run build

About

Reusable Vue component and canvas API for generating styled QR codes.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages