Omni SpatialQR

Smart
Initializing...

QR Generator

Printable assets. Tap any QR code to isolate it.

Showcase

The core capabilities.

Rich Cards

JSON-driven layout mapping.

Custom HTML Elements

Mapping hidden DOM nodes in 3D.

Smart Text & Data

Regex parsed native integrations.

3D Models

WebGL .glb loaders.

Video Players

Liquid morphing media.

Image Frames

Static spatial assets.

Audio Players

Interactive widgets.

Live Configuration


Advanced Settings

Changing these requires a full hardware/DOM reload.

Omni SpatialQR

Zero-Friction WebAR Framework. A blazing-fast Vanilla JS library for mapping rich HTML interfaces and 3D models perfectly onto physical QR codes.

The physical world is static. The digital world is limitless. Omni SpatialQR is the bridge between them.

Until now, Augmented Reality required massive friction: forcing users to download heavy apps, scanning weird proprietary markers, or waiting for bloated 3D engines to load. Omni SpatialQR changes the paradigm. It turns standard, everyday QR codes—on business cards, restaurant menus, retail packaging, and real estate signs—into instant, zero-friction spatial interfaces directly in the mobile browser.

Make your print media play video. Turn a coaster into a 3D showroom. Turn a poster into a glassmorphic checkout interface. It’s lightweight, instantly familiar to users, and feels like native magic.

README.md

A vanilla JavaScript library that calculates camera pose homography from the native BarcodeDetector API to project HTML DOM elements and Three.js WebGL models onto physical QR codes via mathematically precise CSS matrix3d transforms.

Installation

<script src="omni-spatial-qr.js"></script>

Minimal Quick Start

const visionAR = new OmniSpatialQR({
  container: '#ar-wrapper',
  type: 'dynamic'
});

visionAR.start();

// Essential for SPA (React/Vue) routing to prevent memory leaks
visionAR.stop();

Use Cases & Data Routing

Physical QR codes should be as simple as possible (low data density) so they scan instantly from far away. Omni SpatialQR provides two powerful architectures to keep your codes microscopic while rendering massive data payloads.

Use Case A: The Universal Billboard

Use this if your QR codes are standard URLs designed to be scanned by native iPhone/Android cameras to open your website. The library automatically extracts your query parameters (e.g. https://mysite.com?promo=vip).

const visionAR = new OmniSpatialQR({
  type: 'dynamic',
  parseParam: ['promo'], // Safely extracts { promo: "vip" }
  assetResolver: async (parsedObj) => {
    if (parsedObj.promo === 'vip') {
      // Return JSON to instantly build a Glassmorphic Card!
      return {
        title: "VIP Status",
        description: "Welcome back.",
        buttons: [{ label: "Enter", color: "#22c55e" }]
      };
    }
  }
});

Use Case B: The Lightning In-App Scanner

If users scan codes inside your webapp, you don't need full URLs. Use custom URIs (e.g., omni:vip). This makes the physical QR code smaller, allowing the camera to track it significantly faster and from much further away.

const visionAR = new OmniSpatialQR({
  type: 'dynamic',
  uriPrefix: 'omni', // Intercepts "omni:vip"
  assetResolver: async (payload) => {
    // Payload is the raw string "vip"
    const dbItem = await fetch(`/api/items/${payload}`);
    return dbItem.json();
  }
});

Use Case C: The 3D Model Viewer

Ideal for e-commerce or museums. Map physical items to their 3D digital twins automatically.

const visionAR = new OmniSpatialQR({
  type: 'dynamic',
  enable3D: true, // Triggers Three.js CDN download
  autoRotate3D: true, // Creates a turntable effect
  uriPrefix: 'model',
  assetResolver: async (payload) => {
    if (payload === 'shoe') return 'https://mysite.com/shoe.glb';
  }
});

Type Overrides & Custom Injection

Direct Type Forcing

You can bypass the assetResolver completely and explicitly force a UI type directly within the QR Code string:

  • URL Parameter: Append ?omni=type. Example: https://mysite.com/file?omni=audio guarantees the Audio Pill UI builds.
  • Omni URI Scheme: Prefix the string with type:payload. Example: video:https://mysite.com/vid.mp4 or 3d:duck.glb renders the specific player/model.

AssetResolver Overrides & Error Handling

If your backend returns a video URL without an extension (e.g. https://api.com/file_77), dynamic mode will fail. Your resolver can return a config object to force the engine.

Furthermore, if your database lookup fails, return null. The engine will gracefully abort the visual update and fire the onError hook.

assetResolver: async (id) => {
  if (!isValid(id)) return null; // Aborts render, fires onError()

  return {
    type: 'video', // Forces the Video Player UI
    data: 'https://api.com/file_77'
  };
}

Custom HTML vs. DOM Templates

You have two distinct ways to render custom user interfaces in 3D:

1. DOM Templates (Static): Best for React/Vue components already mounted on your page. Map an ID string to a hidden DOM node.

<!-- Your hidden custom UI -->
<div id="my-rating" style="display:none;">⭐⭐⭐⭐⭐</div>

const visionAR = new OmniSpatialQR({
  templates: {
    'stars': '#my-rating'
  }
});
// If the scanner reads the exact string "stars", it clones your HTML!

2. Raw HTML Injection (Dynamic): Best for backend-driven content. Simply return an object with an html property from your resolver.

assetResolver: async (payload) => {
  return { html: "<div class='live-price'>$99.00</div>" };
}

CSS Resolution Nuance: The library uses a strict CSS reset (all: initial) to protect your layout, but explicitly inherits your font-family. Due to the default overlayResolution: 100, 1 unit equals 1 physical pixel relative to the QR code size. Scale your CSS padding and fonts accordingly!


Full Configuration API Reference

  • container (String): DOM selector for the AR viewport.
  • type (String): 'dynamic', 'square', 'text', 'card', 'image', 'video', 'audio', '3d', 'youtube', 'customHtml'
  • scale (Number): Base scale multiplier (Default 1.0).
  • position (String): 'center', 'top', 'bottom', 'left', 'right'.
  • gap (Number): Unit offset if position is not center.
  • overlayResolution (Number): Base render matrix (Default 100). Higher numbers increase clarity but can reduce performance. Use 100 for optimal performance.
  • spawnAnimation (Boolean): Triggers a premium Apple-style pop-up animation for all DOM overlays and 3D models when they spawn.
  • autoPlay (Boolean): Auto-plays injected media loops.
  • showControls (Boolean): Toggles custom SVG HUD overlays.
  • textTruncate (Boolean): Truncates strings vs wrapping to paragraph block.
  • cameraFacing (String): 'environment' or 'user'.
  • mirrorVideo (String|Bool): 'auto' (mirrors webcams/front-cameras flawlessly), true, or false.
  • gpuTransform (Boolean): Applies will-change. Keep false to prevent text blurring on high-end devices. Recommand first playing with overlayResolution
  • enable3D (Boolean): Requires true to dynamically fetch Three.js from CDN.
  • autoRotate3D (Boolean): Rotates models on Y-axis.
  • rotateSpeed (Number): Turntable speed multiplier.
  • parseParam (Array/String): e.g. ['id', 'user']. Extracts parameters natively to use in assetResolver
  • uriPrefix (Array/String): e.g. 'nike'. Enables custom nike:payload extraction to force an overlay type or use in assetResolver
  • assetResolver (Async Function): Receives payload, returns mapped URLs, Config Overrides, or JSON Cards.
  • templates (Object): Maps IDs to hidden DOM elements for custom HTML rendering.

Lifecycle Events

  • onDetect(parsedData): Fires the instant a payload is decoded and extracted, before the UI builds. Perfect for firing a background analytics pixel or triggering an auto-download.
  • onTrackingRestored(): Fires when AR physically locks onto the square.
  • onTrackingLost(): Fires when AR loses physical tracking.
  • onClick(parsedData): Fires when the user taps anywhere on the AR overlay (excluding inner buttons/media controls which handle their own clicks natively). Great for navigating to an external product page.
  • onError(err): Captures Camera, WebWorker, and Resolver failures gracefully.

Pro-Tips & Gotchas

  • HTTPS Requirement: Modern browsers strictly require https:// (or localhost) to access the getUserMedia camera API.
  • CORS for 3D/Media: If you are loading .glb or video files from an external server (like AWS S3 or a custom CDN), ensure your server is configured with Access-Control-Allow-Origin: *, otherwise the WebGL canvas will block the download for security reasons.

Physical QR Code Generator API

Don't use a third-party generator. Our static helper creates beautiful, branded physical anchors instantly. With maximum error correction (Level H) when adding an embedded logos.

const qr = await OmniSpatialQR.generate({
  data: 'omni:promo1',
  type: 'soft', // standard, soft, dots
  size: 300,
  color: '#18181b', // Dot color
  bgColor: '#ffffff',// Background color
  logo: '/logo.png' // Drops your brand into the center
});
document.body.appendChild(qr);