-
探索 visionOS 中的沉浸式网站环境
借助 JavaScript 中新推出的 Immersive API,将你的网站访客带入 Apple Vision Pro 中的虚拟环境。探索如何从内联模型元素请求沉浸式过渡,利用视频对接等功能打造引人入胜的沉浸式体验,并优化性能以实现按真实比例复刻的丰富体验——只需在你的网站上运行几行代码即可。
章节
- 0:00 - Introduction
- 1:46 - Meet the immersive API
- 4:16 - Preview environments inline
- 7:01 - Go immersive
- 12:04 - Optimize the experience
- 17:17 - Image controls
- 18:09 - Next steps
资源
- 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
相关视频
WWDC26
WWDC25
-
搜索此视频…
-
-
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
-
-
- 0:00 - Introduction
The immersive API in visionOS Safari is previewed through two example websites — a theater ticket sales experience and an escape-room marketing site — that transport visitors into virtual environments using just a few lines of code.
- 1:46 - Meet the immersive API
Get a high-level overview of how the HTML `
` element pairs with the new JavaScript `requestImmersive()` API and a `:immersive` CSS pseudo-class. Unlike the Fullscreen API, the immersive API opens an environment around your existing webpage rather than replacing its content. - 4:16 - Preview environments inline
Build the inline portion of the ticket sales site: load a theater model into the page, let visitors pick a seat by applying a `DOMMatrix` transform to the `
` element, and prepare the same model for an immersive transition. - 7:01 - Go immersive
Transition from the inline preview into a full immersive environment. Covers the difference between inline and immersive coordinate systems, listening to `immersivechange` events, dismissing the environment, and skipping the inline preview entirely for the escape-room marketing site.
- 12:04 - Optimize the experience
Polish your environment with RealityKit annotations authored in Reality Composer Pro or via a Blender plugin. Dock playing video into a TV inside the scene, trigger model animations from JavaScript, cast Safari's window shadow with the Scene Understanding component, and reduce vertex/entity counts to keep assets fast to load and render.
- 17:17 - Image controls
Add a single `controls` attribute to an `
` element to give visitors an immersive viewing affordance for spatial photos — a small markup change that pairs naturally with model-based environments.
- 18:09 - Next steps
Try the immersive demos on webkit.org with an Apple Vision Pro, file feedback at bugs.webkit.org, and watch "Design immersive environments for visionOS apps and the spatial web" for the design principles behind great photorealistic environments.