Appearance
@carrot/qr-vue ​
tsvue
Canvas-based QR code renderer with a Vue 3 component. Supports multiple render styles, custom finder patterns, centre cutouts, and retina-aware rendering.
Installation ​
ts
import { CarrotQr } from '@carrot/qr-vue';
// or framework-agnostic:
import { renderToCanvas } from '@carrot/qr-vue';Peer dependency: vue ^3.5.30. Runtime dependency: @carrot/qr.
Architecture ​
Renderer ​
The core renderer (render.ts) is framework-agnostic - it takes a canvas, a QrCode, a QrPixelGrid, and options, and draws everything via Canvas 2D. The pipeline:
- Background - fill or clear
- Data modules - dispatched by variant:
basic- filled rectangles with 0.5px overlap for hairline eliminationdots- circles at configurable size fractionsmooth- single-path outline per module with convex/concave corner classification based on 8-neighbour analysis
- Finder patterns - drawn separately in square, rounded-rect, or circle style
- Centre cutout - exclusion zone that skips data modules + optional background overlay
Smooth Variant ​
The smooth renderer classifies each module's four corners by inspecting the two adjacent cardinal neighbours and the diagonal:
- Neither cardinal present → convex quarter-circle (isolated module becomes a circle)
- One cardinal present → square corner
- Both cardinals, diagonal present → square corner
- Both cardinals, diagonal absent → concave quarter-circle notch
Concave fills extend into the empty diagonal cell as small arc segments, creating organic blob shapes.
Vue Component ​
CarrotQr wraps the renderer with reactive props. It:
- Reads CSS custom properties (
--qr-fg,--qr-bg,--qr-accent) as colour defaults - Auto-enables centre cutout when slot content is provided
- Re-renders on any prop change via
watch+nextTick - Renders at 2x DPR for retina displays
File Structure ​
src/
├── index.ts # Public API barrel
├── render.ts # Canvas renderer (framework-agnostic)
├── types/
│ └── types.ts # QrRenderOptions, CenterCutout, QrProps
├── components/
│ └── CarrotQr.vue # Vue 3 component
└── styles/
└── qr.css # Component stylesDependencies ​
| Dependency | Kind |
|---|---|
@carrot/qr | runtime |
vue | peer |
Build ​
bash
npm run buildBuilds via vue-tsc --noEmit && vite build. Output lands in dist/.
Usage Guide ​
Canvas-based QR code renderer and Vue component with render variants, finder styles, and centre cutout for logos.
Import ​
ts
import { CarrotQr } from '@carrot/qr-vue';Common Patterns ​
1. Basic component usage ​
vue
<CarrotQr url="https://example.com" />Defaults: smooth variant, circle finders, white foreground, transparent background, high ECC.
2. With a logo cutout ​
vue
<CarrotQr url="https://example.com" :cutout="0.2">
<img src="/logo.svg" width="40" height="40" />
</CarrotQr>Slot content is centred in the cutout area. The cutout auto-enables when slot content is provided (defaults to 0.2 size).
3. Render variants ​
vue
<!-- Smooth blob style (default) -->
<CarrotQr url="..." variant="smooth" />
<!-- Circular dots -->
<CarrotQr url="..." variant="dots" :dot-size="0.6" />
<!-- Plain squares -->
<CarrotQr url="..." variant="basic" />4. Finder pattern styles ​
vue
<CarrotQr url="..." finder-style="circle" />
<CarrotQr url="..." finder-style="rounded" />
<CarrotQr url="..." finder-style="square" />5. Colours via props ​
vue
<CarrotQr url="..." fg="#1a1a2e" bg="#ffffff" accent="#e94560" />6. Colours via CSS custom properties ​
css
.my-qr {
--qr-fg: var(--color-text);
--qr-bg: var(--color-surface);
--qr-accent: var(--color-primary);
}vue
<CarrotQr url="..." class="my-qr" />Props override CSS custom properties when both are set.
7. Framework-agnostic renderer ​
Use renderToCanvas directly without Vue:
ts
import { create, createGrid, ErrorCorrection } from '@carrot/qr';
import { renderToCanvas } from '@carrot/qr-vue';
const code = create('https://example.com', ErrorCorrection.High);
const grid = createGrid(code);
const canvas = document.getElementById('qr') as HTMLCanvasElement;
renderToCanvas(canvas, code, grid, {
variant: 'smooth',
foreground: '#ffffff',
background: 'transparent',
finderStyle: 'circle',
centerCutout: { size: 0.2 },
});8. Offscreen rendering ​
ts
import { renderToOffscreen } from '@carrot/qr-vue';
const canvas = renderToOffscreen(code, grid, 400, {
variant: 'dots',
foreground: '#000000',
background: '#ffffff',
});
// Use as image source
const dataUrl = canvas.toDataURL();Tips ​
- Use
ecc="high"with cutouts - the default. Centre cutouts destroy data modules, so high ECC ensures the code remains scannable. - Smooth variant looks best at larger sizes - the convex/concave corner detection creates organic blob shapes that shine at 200px+.
- CSS custom properties are read at render time - they react to theme changes without prop updates.