Immersive images, one element away.
xr-view is a custom HTML element for 360° and panoramic images. This guide covers installation, sizing, configuration, and runtime updates.
Quick start
Install the package, then import it once in your application.
npm install xr-view
Import from JavaScript
Importing the module registers <xr-view> with the browser's custom
element registry.
import 'xr-view';
Add the element
Set src to the URL of an equirectangular image (a full photosphere).
<xr-view src="/images/photosphere.jpg"></xr-view>
Sizing
The component fills its available width and has a default height of 400px. Override its dimensions with ordinary CSS to fit your layout.
xr-view {
width: 100%;
height: min(70vh, 720px);
border-radius: 16px;
}
Keep both dimensions greater than zero. xr-view observes its container and updates the camera whenever its rendered size changes.
Attributes
Configure the viewer directly in HTML. Attribute changes are reactive.
| Attribute | Type / default | Description |
|---|---|---|
src |
String / "" |
URL of the image to display. |
type |
auto, 360, or pano /
auto
|
360 renders a full equirectangular sphere. pano renders
a curved partial-panorama surface for images that are not 2:1. auto
measures the image and picks, treating anything within 5% of a 2:1 ratio as a
photosphere. Pano and auto use render mode.
|
autopan |
Boolean / enabled |
Slowly rotates the view until the visitor interacts. Set the JavaScript property
to false when you want a still initial view.
|
mode |
render or model |
render draws the image with Three.js on a WebGL canvas.
model uses the platform <model> element for true
3D display within the page, on supported platforms (visionOS). Unsupported model
mode falls back to render mode.
|
Mode example
<xr-view
src="/images/panorama.jpg"
type="pano"
mode="render"
></xr-view>
Model mode
The <model> element displays real 3D content inline in the page, the
way an image element displays a picture—the platform composites it rather than a canvas
drawing it. On platforms that implement it, currently visionOS, model mode shows the
image as genuine 3D geometry in the page instead of a rendered projection, and it is the
default. xr-view generates the USDZ the element needs in the browser from the same
src. Where the element is unavailable, the viewer uses render mode.
Update with JavaScript
Change the source without recreating the viewer, or turn automatic movement on and off at runtime.
const viewer = document.querySelector('xr-view');
viewer.src = '/images/second-photosphere.jpg';
viewer.autopan = false;
Load events
The viewer emits bubbling xr-view.load and
xr-view.error custom events for the current non-empty source. Superseded
and aborted requests do not emit either event.
viewer.addEventListener('xr-view.load', (event) => {
console.log('Loaded', event.detail.src);
});
viewer.addEventListener('xr-view.error', (event) => {
console.error('Could not load', event.detail.src, event.detail.error);
});
The class is also available as a named export when you need it directly.
import { XrView } from 'xr-view';
Built-in controls
- Drag with a pointer or touch gesture to look around.
- Use Fullview for an app-like viewport overlay.
- Use Fullscreen for the browser's native fullscreen mode.
- On supported devices, use WebXR to enter immersive VR.
- Press Escape to leave Fullview or an active WebXR session.
A visitor's first pointer interaction stops auto-pan, keeping manual navigation under their control.
Iframe embed
Use the hosted embed page when adding the component directly is not practical. Encode
the complete HTTPS image URL as the src query parameter.
<iframe
src="https://xrview.dev/embed/?src=https%3A%2F%2Fsite.com%2F360img.jpg&type=360"
width="600"
height="400"
title="360° image viewer"
loading="lazy"
allow="fullscreen; xr-spatial-tracking"
allowfullscreen
></iframe>
The optional type parameter accepts auto, 360, or
pano. Set autopan=false to disable initial movement.
Embedded images load directly in the visitor's browser. The image host must serve the
file over HTTPS and allow cross-origin access with an
Access-Control-Allow-Origin response header.
Image guidance
Standard browser-readable image URLs work for both supported projections.
360° photospheres
Use an equirectangular image with a 2:1 aspect ratio—for example, 4096×2048 or 8192×4096 pixels. Anything within 5% of 2:1 is treated as a full photosphere, so a slightly cropped export still wraps the whole sphere.
Panoramas
Wide shots that do not cover a full sphere display on a curved surface instead. Use an
image that is wider than it is tall—a cylindrical stitch from a phone's panorama mode is
a good fit. The wider the aspect ratio, the wider the arc the image wraps around the
viewer, up to a half circle. The curved surface needs render mode, which
auto selects for you.
Images fetched from another origin must allow cross-origin access. Compress large images carefully: dimensions preserve detail, while file size affects load time.
Browser support
The standard renderer requires custom elements, WebGL, and modern JavaScript module support. Fullscreen and WebXR controls appear or work only where the corresponding browser APIs are available.
If the image cannot be loaded, the viewer displays an error message. Test immersive features on the target device because WebXR support and permissions vary by browser and headset.
Report an issue →