Package Exports
- js-camera
- js-camera/dist/build.esm.js
- js-camera/dist/build.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (js-camera) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
js-camera

Zero-dependency camera element for the web.
Drop in <js-camera>, capture frames, and ship.
- Web Components V1 — works with React, Vue, Svelte, or vanilla
- Capture as PNG / JPEG / WebP with resize, crop, and fit options
- Pinch-to-zoom on touch devices
- Built-in controls (play/pause, capture, face-switch) or go fully programmatic
- Front / back camera switching and device selection
- Zero dependencies, ~10 KB gzipped
npm install js-camera3 Lines to Camera
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<js-camera autoplay facing="back" controls></js-camera>import 'js-camera';That's it. Play/pause, capture, face-switch — all built in. Fills the viewport by default. The viewport meta prevents the browser from hijacking pinch-to-zoom.

Custom Size
js-camera {
width: 400px;
height: 300px;
}Go Deeper
Drop the controls attribute and take full control.
import 'js-camera';
const camera = document.querySelector('js-camera');
// Open rear camera at Full HD
await camera.open({ facingMode: 'back', width: 1920, height: 1080 });
// Capture
const png = camera.capture();
const jpeg = camera.capture({ format: 'image/jpeg', width: 640, height: 480, fit: 'cover' });
const cropped = camera.capture({ extract: { x: 100, y: 50, width: 200, height: 200 } });
// Playback
camera.pause();
camera.play();
// Done
camera.close();Create on the Fly
import Camera from 'js-camera';
const camera = Camera.createElement();
document.body.appendChild(camera);
await camera.open({ facingMode: 'front' });Listen
camera
.on('opened', () => console.log('Ready'))
.on('captured', (e) => upload(e.detail.capture))
.on('paused', () => console.log('Paused'))
.on('played', () => console.log('Resumed'));| Event | Fires when | event.detail |
|---|---|---|
opened |
Stream is ready | — |
captured |
Frame captured via built-in button | .capture — data URL |
paused |
Playback paused | — |
played |
Playback resumed | — |
API
HTML Attributes
| Attribute | Description | Default |
|---|---|---|
autoplay |
Open camera on DOM insertion | — |
facing |
"front" or "back" (used with autoplay) |
"back" |
width |
Desired resolution width (px) | device default |
height |
Desired resolution height (px) | device default |
controls |
Show built-in UI | — |
Static Methods
| Method | Returns | Description |
|---|---|---|
Camera.define() |
typeof Camera |
Register <js-camera>. Auto-called on import. |
Camera.createElement() |
Camera |
Create a new element. Calls define() if needed. |
Properties (read-only)
| Property | Type | Description |
|---|---|---|
state |
'open' | 'loading' | 'close' |
Lifecycle state |
opened |
boolean |
Stream is active |
paused |
boolean |
Playback is paused |
facingMode |
'front' | 'back' | undefined |
Current direction |
deviceId |
string | undefined |
Active camera device ID |
resolution |
{ width, height } |
Actual hardware resolution |
track |
MediaStreamTrack | undefined |
Active video track |
zoom |
number |
Current zoom level (1 = no zoom) |
Methods
open(options?): Promise<MediaTrackSettings>
Opens the camera. Re-opens if already active.
Throws DOMException on denial or unavailable device.
| Option | Type | Default | Note |
|---|---|---|---|
facingMode |
'front' | 'back' |
'front' |
Ignored when deviceId is set |
width |
number |
— | Falls back to HTML attribute |
height |
number |
— | Falls back to HTML attribute |
deviceId |
string |
— | Target a specific camera |
waitOpen(): Promise<void>
Resolves when the camera finishes opening. Instant if not loading.
close()
Stops the stream and releases all resources.
play(): Promise<void>
Resumes from pause.
pause()
Freezes the current frame.
resetZoom()
Resets zoom level to 1. Pinch-to-zoom is built in — use two fingers on touch devices.
capture(options?): string
Returns a data URL of the current frame.
| Option | Type | Default | Note |
|---|---|---|---|
width |
number |
— | Omit one to keep aspect ratio |
height |
number |
— | Omit one to keep aspect ratio |
fit |
'cover' | 'contain' | 'fill' |
'fill' |
Same as CSS object-fit |
format |
string |
'image/png' |
'image/jpeg', 'image/webp', etc. |
extract |
{ x, y, width, height } |
— | Crop region in CSS pixels |
queryPermission(): Promise<PermissionState | undefined>
Returns 'granted', 'denied', 'prompt', or undefined if unsupported.
revokePermission(): Promise<void>
Revokes camera permission. Not supported in all browsers.
getDevices(): Promise<Array<{ deviceId, label }>>
Lists available cameras. Requests temporary access if needed.
on(type, listener, options?): Camera
Adds a listener. Returns this for chaining. Pass { once: true } to auto-remove.
off(type, listener): Camera
Removes a listener. Returns this for chaining.
Types
import Camera, { type CameraOpenOptions, type CaptureOptions } from 'js-camera';interface CameraOpenOptions {
facingMode?: 'front' | 'back'; // default: 'front'
width?: number;
height?: number;
deviceId?: string;
}
interface CaptureOptions {
width?: number;
height?: number;
extract?: { x: number; y: number; width: number; height: number };
fit?: 'cover' | 'contain' | 'fill'; // default: 'fill'
format?: string; // default: 'image/png'
}Browser Support
Custom Elements V1 + getUserMedia
Changelog
Author
shumatsumonobu — GitHub / X / Facebook