Skip to main content
Version: 11.12.1

Virtual reality (360°)

Tip: open your browser's developer console and use the player and THEOplayer variables to interact with this demo.

vr.state-
vr.stereo-
vr.direction.yaw-
vr.direction.pitch-
vr.direction.roll-
vr.verticalFOV-
vr.canPresentVR-

This example plays a 360° video. To mark a source as a 360° video, set vr: { 360: true } on the source description. Drag the video (or move your phone) to look around.

The box below the player reports the values of the VR API. They are updated using the directionchange, stereochange and statechange events of player.vr. Stereo mode is toggled with the button in the player's control bar, which only appears when player.vr.canPresentVR is true (for example, when a WebXR device such as a VR headset is available). Entering an immersive WebXR session must be triggered by a user gesture inside the player's page.

Code
demo.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Virtual reality (360°)</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet" />
<style>
html,
body {
margin: 0;
padding: 0;
}

theoplayer-default-ui:not(:defined) {
display: inline-block;
box-sizing: border-box;
}

theoplayer-default-ui {
width: 100%;
aspect-ratio: 16 / 9;
font-family: 'Noto Sans', sans-serif;
background: #000;
}
</style>
<script src="https://cdn.theoplayer.com/dash/theoplayer/THEOplayer.js"></script>
<script nomodule src="https://unpkg.com/@theoplayer/web-ui@2/polyfills"></script>
<script async src="https://unpkg.com/@theoplayer/web-ui@2"></script>
</head>
<body>
<!--
libraryLocation: For demonstration purposes, we use the theoplayer.com CDN.
For production use, we recommend hosting THEOplayer yourself
and changing this (as well as the <script> tags above)
to point to THEOplayer's location on your own website.

licenseUrl: Change this to point to your THEOplayer license file.
Alternatively, replace it with a "license" property whose value is your THEOplayer license itself.
-->
<theoplayer-default-ui
configuration='{"libraryLocation":"https://cdn.theoplayer.com/dash/theoplayer/","licenseUrl":"../../../../theoplayer-license.txt","vr":{"useWebXR":true}}'
source='{"sources":{"src":"https://demo.theoplayer.com/hubfs/videos/natgeo/playlist.m3u8","type":"application/x-mpegurl"},"poster":"https://demo.theoplayer.com/hubfs/videos/natgeo/poster.jpg","vr":{"360":true},"metadata":{"title":"National Geographic 360\u00b0"}}'
>
<theoplayer-button
id="stereo-toggle"
slot="bottom-control-bar"
aria-label="Toggle stereo (VR headset)"
title="Toggle stereo (VR headset)"
hidden
>Stereo</theoplayer-button
>
</theoplayer-default-ui>
<script src="../utils.js"></script>
<script>
onPlayerReady((player) => {
const vr = player.vr;
let pending = false;

function reportState() {
// Report at most once per animation frame, since the direction changes very often.
if (pending) return;
pending = true;
requestAnimationFrame(() => {
pending = false;
sendToParent('vr', {
state: vr.state,
canPresentVR: vr.canPresentVR,
stereo: vr.stereo,
verticalFOV: vr.verticalFOV,
direction: { ...vr.direction },
});
});
}
vr.addEventListener(['directionchange', 'stereochange', 'statechange'], reportState);

const stereoButton = document.querySelector('#stereo-toggle');
function updateStereoButton() {
const canPresentVR = vr.canPresentVR;
stereoButton.hidden = !canPresentVR;
stereoButton.disabled = !canPresentVR;
stereoButton.setAttribute('aria-pressed', String(vr.stereo));
stereoButton.textContent = vr.stereo ? 'Stereo on' : 'Stereo';
}
stereoButton.addEventListener('click', () => {
vr.stereo = !vr.stereo;
});
vr.addEventListener(['statechange', 'stereochange'], updateStereoButton);
updateStereoButton();

reportState();
});
</script>
</body>
</html>