-
Explorez des environnements de site web immersifs dans visionOS
Transportez les visiteurs de votre site web dans des environnements virtuels sur l'Apple Vision Pro grâce à la nouvelle API Immersive en JavaScript. Découvrez comment demander des transitions immersives à partir d'un élément de modèle intégré, créer des expériences immersives captivantes grâce à des fonctionnalités telles que l'ancrage vidéo, et optimiser les performances pour des expériences riches à l'échelle du monde réel, le tout avec seulement quelques lignes de code sur votre site.
Chapitres
- 0:00 - Introduction
- 1:46 - Découvrez l’API immersive
- 4:16 - Aperçu des environnements en ligne
- 7:01 - Passez en mode immersif
- 12:04 - Optimiser l’expérience
- 17:17 - Commandes d’image
- 18:09 - Étapes suivantes
Ressources
- Download - Immersive model add-on for Blender
- WebKit.org - Theater Ticket Sales immersive website environment demo for Apple Vision Pro
- WebKit.org - Escape Game immersive website demo for Apple Vision Pro
- GitHub: Spatial Backdrop explainer
- WebKit.org – Report issues to the WebKit open-source project
- Submit feedback
Vidéos connexes
WWDC26
- Concevez des environnements immersifs pour les apps visionOS et le Web spatial
- Exploitez l’élément de modèle HTML
- Nouveautés de WebKit pour Safari 27
WWDC25
-
Rechercher dans cette vidéo…
-
-
1:51 - Basic model element
<model src="teapot.usdz"> </model> -
2:06 - Model element with environment map
<model src="teapot.usdz" environmentmap="kitchen.hdr"> </model> -
4:40 - Adding the environment model on the page for inline preview
<div class="seat-preview"> <model id="theater" src="theater-model.usdz" environmentmap="theater-lighting.hdr"> </model> </div> -
5:14 - Reset the model entity transform
const theater = document.getElementById("theater"); async function updateModelTransform() { // Make sure the model is loaded await theater.ready; // Create a transform matrix const identity = new DOMMatrix(); // Apply the transform matrix to the model theater.entityTransform = identity; } updateModelTransform(); -
5:42 - Translate the model down
const theater = document.getElementById("theater"); async function updateModelTransform() { // Make sure the model is loaded await theater.ready; // Create a transform matrix const transform = new DOMMatrix(); // Translate model down, for eye level preview transform.translateSelf( 0, // x -1.0, // y 0 // z ); // Apply the transform matrix to the model theater.entityTransform = transform; } updateModelTransform(); -
6:40 - Build the seat transform
function buildTransform(seat) { const transform = new DOMMatrix(); const { x, y, z, ry } = seat; // Rotate and translate the model to match // the seat's origin and orientation transform.rotateSelf(0, -ry, 0); transform.translateSelf(-x, -y, -z); // Translate the model down, for eye level preview transform.translateSelf(0, -1.0, 0); return transform; } -
7:16 - Detect feature availability
if (document.immersiveEnabled) { immersiveButton.hidden = false; } -
7:34 - Request the immersive transition on the model
immersiveButton.addEventListener("click", async () => { await model.requestImmersive(); }); -
8:24 - Build immersive transform
function buildTransform(seat, immersive) { const transform = new DOMMatrix(); // [...] Seat transform logic if (immersive) { // Rotate to the left transform.rotateSelf( 0, // x 45, // y 0 // z ); } else { // [...] Eye level translation } return transform; } -
9:01 - Update the entity transform and the layout on immersive state updates
theater.addEventListener("immersivechange", () => { const isImmersive = !!document.immersiveElement; const transform = buildTransform(isImmersive, currentSeat); theater.entityTransform = transform; document.body.classList.toggle("immersive", isImmersive); }); -
10:53 - Hide the inline preview
<model id="escapeRoom" src="escape-room.usdz" environmentmap="room-lighting.hdr" style="display: none"> </model> -
11:25 - Request an immersive transition on the escape room model
const enterButton = document.getElementById("enterButton"); const escapeRoom = document.getElementById("escapeRoom"); enterButton.addEventListener("click", () => { await escapeRoom.requestImmersive(); }); -
11:52 - Handle the request result and show a loading animation
enterButton.addEventListener("click", async () => { showLoadingAnimation(); try { await escapeRoom.requestImmersive(); } catch (error) { console.log(error); } finally { hideLoadingAnimation(); } }); -
13:16 - Dock the video in the environment with the fullscreen API
const trailerVideo = document.getElementById("trailerVideo"); const demoButton = document.getElementById("demoButton"); demoButton.addEventListener("click", async () => { await trailerVideo.requestFullscreen(); }); -
14:01 - Play the model animation
const trailerVideo = document.getElementById("trailerVideo"); const escapeRoom = document.getElementById("escapeRoom"); trailerVideo.addEventListener("ended", async () => { await document.exitFullscreen(); escapeRoom.play(); }); -
16:38 - Compress your USDZ with usdcrush
usdcrush model.usdz -o optimized.usdz
-