Web Orientation

Cross-platform web library to read device orientation with automatic sensor calibration, gimbal-lock-free quaternion conversion, and automated permission management.

Overview

Reading mobile device orientation in modern browsers presents several challenges:

  • Gimbal lock: Standard DeviceOrientationEvent emits Euler angles (alpha, beta, gamma) which suffer from gimbal lock at specific pitch angles.
  • Permission gating: Modern iOS / WebKit browsers require explicit user activation before granting access to sensor APIs.
  • Coordinate reference frames: Initial phone orientation often points away from the user's intended zero-view direction.

Web Orientation provides a unified, quaternion-based API that abstracts these platform quirks with zero external runtime dependencies besides lightweight quaternion math.

Features

  • Simple Quaternion Interface: Easy-to-use interface for reading orientation data using industry-standard quaternions to avoid gimbal lock issues.
  • Automatic & Custom Permission Handling: Automatic permission requests for browsers that require it (such as iOS Safari/WebKit) with built-in modal UI and the ability to define custom permission workflows.
  • Automatic Gimbal-Lock-Free Conversion: Automatic conversion of DeviceOrientationEvent Euler angles to 3D unit quaternions ({ x, y, z, w }).
  • In-Built Reference Frame Reset: In-built helpers for resetting orientation reference frame (resetOrientation()).
  • Mocking Tool: Provides mocking tool for simplifying debugging on non-mobile devices.
  • Configurable Polling Rate: Throttles orientation updates to maintain optimal FPS and conserve battery life.

Installation

CODE
npm install web-orientation

Quick Start

Basic Usage

CODE
import { deviceRotation } from "web-orientation";

// 1. (Optional) Configure listener
deviceRotation.setConfig({
  pollingRate: 60, // Limit updates to 60 FPS
  onPermissionDenied: () => console.warn("Permission denied by user"),
  onPermissionGranted: () => console.log("Sensor permission granted"),
});

// 2. Subscribe to orientation changes
deviceRotation.onUpdate((update) => {
  const { x, y, z, w } = update.quaternion;
  console.log(`Current rotation quaternion: [${x}, ${y}, ${z}, ${w}]`);
});

Examples

Three.js Integration

CODE
import * as THREE from "three";
import { deviceRotation } from "web-orientation";

// Set up your Three.js scene and target mesh/object
const targetObject = new THREE.Mesh(geometry, material);
scene.add(targetObject);

// Update object rotation on each sensor tick
deviceRotation.onUpdate((event) => {
  const { x, y, z, w } = event.quaternion;
  const orientation = new THREE.Quaternion(x, y, z, w);
  targetObject.setRotationFromQuaternion(orientation);
});

CSS 3D Transform Integration

CODE
import Quaternion from "quaternion";
import { deviceRotation } from "web-orientation";

const cardElement = document.getElementById("card");

deviceRotation.onUpdate((event) => {
  const q = new Quaternion(event.quaternion);
  cardElement.style.transform = q.toCSSTransform();
});

Manual Start & Reference Calibration

CODE
import { deviceRotation } from "web-orientation";

// Disable auto-start on init
deviceRotation.setConfig({
  startOnInit: false,
});

// Attach manual controls to UI buttons
document.getElementById("start-btn").addEventListener("click", () => {
  deviceRotation.start();
});

document.getElementById("stop-btn").addEventListener("click", () => {
  deviceRotation.stop();
});

// Calibrate the phone's current position as the new (0, 0, 0, 1) zero-point
document.getElementById("recalibrate-btn").addEventListener("click", () => {
  deviceRotation.resetOrientation();
});

API Summary

deviceRotation

FunctionDescription
onUpdate(callback)Registers callback for rotation updates and starts listening (if startOnInit: true).
resetOrientation()Sets the current orientation as the calibrated identity origin (0, 0, 0, 1).
setConfig(config)Configures polling rate, callbacks, and autostart behavior.
start()Manually prompts for permissions and starts listening for device orientation.
stop()Stops listening to orientation events.

Types