ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
SwiftUIにおける空間コンピューティングの概要
太陽系をツアーしながらSwiftUIでvisionOSを探求しましょう。ウインドウ、ボリューム、スペースを通じてまったく新しいアプリの世界を創造する方法を紹介します。天文学アプリを作成しながら、3Dコンテンツを追加し人々を宇宙へといざなうイマーシブな体験を創造して、このプラットフォームでのSwiftUIの使い方を学びます。
関連する章
- 0:00 - Introduction
- 5:29 - Windows
- 14:06 - Volumes
- 20:35 - Full Spaces
リソース
関連ビデオ
WWDC23
-
ダウンロード
♪ ♪ ♪ こんにちは 「SwiftUIにおける空間コンピューティング」に ようこそ SwiftUIチームのエンジニアのAndrewです 空間コンピューティングにはワクワクします 画期的なアプリを作る機会が 大きく広がります ここではこのプラットフォームの アプリ開発に必要な情報と それを可能にするSwiftUIの パワフルな新機能についてお話しします 空間コンピューティングの アプリ開発にはSwiftUIが最適です SwiftUIの新機能には ボリュームのような最新の3D機能や フルスペースでのイマーシブな体験 新しい3Dジェスチャーや効果にレイアウト RealityKitとの統合など まだたくさんあります これらの新しい機能はSwiftUIだけに存在します また アプリの既存コードがあれば ほとんどがそのまま作動します でも新しいコードは SwiftUIで書くのが一番です SwiftUIの可能性を信じているため SwiftUIでシステムを一から構築しました ボタンやトグルやTabViewなど 主要基礎的要素から Home Viewや コントロールセンター そして親しみのある TVやSafariなどのアプリから Freeformの3D boardsなど新体験に加え Keynoteのイマーシブなリハーサルなど SwiftUIはこれらの原動力となり またそれ以上のことを提供します SwiftUIで アプリのインターフェイスを設計し 賢いデフォルトの選択をシステムにまかせます 一度このコンセプトを学べば どこにでも応用できます これは新プラットフォームではさらに役に立ちます 既存のSwiftUIの知識が まったく新しい見た目や体験に シームレスに移されます ボタンを見てみましょう このシステムのボタンは ほかのプラットフォームのものと似ています 例えばmacOSでは bordered styleがデフォルトで ボタンに使われています しかしプラットフォームの特徴に合わせるため いくつかの違いがボタンにあります シミュレータをつかって 詳細に見てみましょう このようなBordered buttonsは 鮮やかな背景を使っています そして目や手及びポインター入力に反応する ホバーエフェクトが得られます またボタンを押すと スケールダウンして 音を出すこともできます またナビゲーションバーのボタンなどは 視線でフォーカスすると ラベルを示し ツールチップを自動的に 表示することもできます またTabViewは アプリの端に設置され コンテンツを遮ることなく 手早く簡単なナビゲーションを提供します またTabViewは視線でフォーカスがあたるだけで 拡張してラベルなどの詳細を表示できます TabViewはSwiftUIがいかにして プラットフォームの特性を活かす例であり インターフェイスを見たものに 反応させることができます ナビゲーションからプレゼンテーション そしてコントロールやインタラクションまで この同じデザインを アプリの主なブロック要素に適用しています これらはデフォルトとして提供されるので アプリ開発のスタート時点から みなさんはアプリ自体をよくすることに 集中できます それだけではありません SwiftUIは3D環境のために作られた 最新APIも数々含まれています それらはシーンから始まります SwiftUIのアプリは複数のシーンで構成され 一つのシーンは複数のviewsで構成されています シーンははアプリの最も上位のエントリポイントで 1つ以上のウインドウを表示する WindowGroupがその例です 空間コンピューティングには 3つのシーンタイプがあり ウインドウ ボリューム そして フルスペースです ウインドウは従来とおなじ インターフェイスに最適です SafariやFreeformのような リッチで完成されたアプリから 軽量なメニューを提供するようなアプリまでサポートします またMindfulnessのような イマーシブな体験もあります ボリュームは物体を表示したり 限られた空間の中で体験を提供するために作られた 3Dウインドウです ボリュームは他のアプリと共に表示でき ライトな3D体験の作成に適したツールです Quick Lookの3Dモデルや FaceTimeで友達と ボードゲームで遊べます そしてフルスペースでリッチで イマーシブなアプリを作成できます アプリがすべてをコントロールし ほかのウインドウを隠し どこでもコンテンツを配置できます 周りの環境とつながったまま 実世界を拡張させたり まったく新しい体験に 浸らせることもできます Keynoteでのリアルなリハーサルや スリルなゲームまで フルスペースで可能性が広がります それらは同時に使用できます そして目的別にデザインされており 組み合わせたりして アプリのニーズに応えられます 建築モデルの軽量な3Dプレビューを ウインドウから ボリュームとして表示できます。 また、ボリュームからフルスペースを表示させ イマーシブな環境を作ることもできます 同じタイプのシーンを幾つか使って アプリを独立したスペースに配置すれば 個別にウインドウを開閉することができます ではこれらのシーンの種類を詳しく見てみましょう まずはウインドウからです 私は天文学のファンで仲間と 地球と太陽系について 学ぶことができるアプリを作っています アプリは順調に開発が進み しっかりとした紹介ページを ウインドウで作成しました でもさらなるプランがあります この作成には 全プラットフォームで使える WindowGroup APIを使用しました それにより macOSやiPadOS同様 複数のウインドウ作成が 自動的にサポートされています さらに新しい機能を足そうと思います 太陽系と宇宙について 豆知識を集めたライブラリです 天文学の生徒の役に立ちますね でもこの機能を どこに追加すればよいのか迷っていました 答えを見つけるため ウインドウの構造を 基礎的要素に分割します ウインドウは美しいガラスの背景から始まり コンテンツを明確に見せながらも 周囲にうまく溶け込んでいます またここではほかのプラットフォームと同じ ナビゲーションコンテナを使えます 例えばTabViewでアプリを トップレベルのコンポーネントに分割し ウインドウの上に表示できます またNavigationStackやNavigationSplitViewで アプリの階層を整理し 情報を表示できます iPadOSの構造に似ています Listsも情報整理のための パワフルなツールで その美しいスタイルは非常にフィットしています またインタラクティブ性を ボタンやトグルやピッカーなどのコントロールで 追加することもできます 今回のライブラリには TabViewがよさそうです 各コンテンツのトップに いつでもアクセスできるので 深い知識へのアクセスを タップひとつで切り替えられます まずTabViewでコンテンツを囲い 各tabにlabel付きのtabItemを設定します よさそうですね! TabViewはユニークな外観で 端にぶら下がっています TabViewにはSwiftUIに加わった 新概念のオーナメントがあります オーナメントはウインドウに 付属的なビューをつけたし ウインドウの枠外にまで拡張できます ウインドウには属さない 追加するコントロールに最適で コンテンツを邪魔しません またornament modifierで 独自のオーナメントを作ることもできます ではLibrary detail viewを 見てみましょう 既に作成途中ですが 概要に関するテキストや興味深い統計情報が 配置され そして水平方向にスクロールできる 豆知識のリストもあります でも何かが足りません それが何か知るために アプリのマテリアルをみてみましょう ウインドウにはデフォルトで 美しいガラス背景があります ガラスは鮮やかな素材のデザインで アプリに視覚的なレイヤー表示を提供します ガラスは自動的に環境に適応し どこで使われてもコンテンツを読みやすくし どの設定でもアプリの見栄えがよくなります つまりここでは 外観の明暗を気にする必要がなく マテリアルにすべてを任せられます ではマテリアルで Library tabを調和し 読みやすさを向上させます StatsGridからです 現在StatsGridは TitleとGrid自体からつくられたVStackです Material backgroundを与えて このカードを目立たせましょう Regular materialを使います ガラスの上に 鮮やかで暗い背景を加え カードの形が落ち着き 文字が読みやすくなります 丸角長方形であるrectを選び paddingを足し 見栄えをよくしました 豆知識カードも同様にします ずっとよくなりました! 次は豆知識カードです ズームして詳細を見ます このカードはボタンになっており クリックと詳細が見れます またbutton styleで すてきな素材背景を供給しています ボタンの中身はタイトルと 本文 そして脚注があり タップすると詳細が見れます でもLearn moreのテキストが すこしだけ重く見えます そこでsecondary foreground styleを textに使います ご覧のように secondary styleは自動的に背景に適応し 鮮やかな色彩変化を与えて しっかりと読めるように 本文を際立たせています これらの階層的なshape stylesは 視覚的に重要性を表現し コンテキストに基づき SwiftUIが自動的に適応させます これらのshape styleやmaterial APIsで どんなコンテキストやプラットフォームでも 素晴らしいインターフェイスが作成できます 次はインタラクションです 空間コンピューティングに 新しいインタラクション方法が加わります 最も一般的なのは 単に要素を見ることと 間接的なピンチジェスチャーでのタップです また両手を伸ばしてタッチして アプリとインタラクトする 直接的な方法もあります また接続されたタッチパッドで、ハンドジェスチャーや 正確な入力のポインターとして使用できます またハードウェアキーボードでも ショートカットやフォーカスをサポートします そしてkey modifiersで アプリでの生産性を改善できます 最後にVoiceOverや Switch Controlなど 馴染みのあるアクセシビリティ技術も サポートしています さらにSwiftUI controlsは 最初からアクセシブルで ほとんどの作業を行うための アプリの素晴らしい体験を 誰にでも提供することができるのです 既にSwiftUIで TapGestureやDragGestureなどの 馴染みあるジェスチャーを使え それらが自動的に適応されます また新しいジェスチャーで 新しい3Dインタラクションが可能です RotateGesture3Dでは 両手かトラックパッドで ビューを3次元に回転できます もちろんほかのプラットフォームの アクセシビリティAPIや技術も 使用できます VoiceOverやrotorsやDynamic Type Invert Colorsはその一部です そしてまた 多くの機能はこのプラットフォームのために再設計され Dwell Controlは目だけで アプリを操作することができます これらの素晴らしい機能と アクセシビリティについては 「Create accessible spatial experiences」をご覧ください 空間コンピューティングにおいて 簡単で直感的に操作できるのが ホバーエフェクトです 例えば 操作可能な viewを見るだけで システムはうっすらとハイライトを与え インタラクト可能だと示します これらの効果は 入力方法に対して自動的に適応し 安心感を与えます さらにホバーエフェクトは ターゲットを設定するための 手助けにもなります 視線によって、アプリから反応を得られるのは ホバーエフェクトだけです またプライバシーを重視するため この処理はアプリ外で行われます ホバーエフェクトは自動的に ボタンやトグルなど 多くのコントロールに追加されます SwiftUIが提供するスタイルを使用すれば これらは自動的にアプリに追加されます カスタムコントロールであれば ホバーエフェクトを追加して 簡単に使えるようにしましょう それでは先程の豆知識カードに戻って ホバーエフェクトの応用例を見てみます カードの見た目はなかなかですが 問題があります カスタムButtonStyleを使ったので ホバーエフェクトを足さねば このボタンがインタラクティブだと 示す反応がありません しかしこれは簡単に直せます 現在ButtonStyleには paddingとbackgroundが labelにあるだけです ホバーエフェクトを追加するには ButtonStyleに hoverEffect modifierを足します これで自動的に 状況に合う効果が選ばれます この場合 highlight effectです では詳細を見てみましょう カードのボタンを見ると うっすらとしたハイライトで インタラクティブだと分かります この効果は自動的に 背景の形にマッチし みんなが豆知識を見逃すことはありません ウインドウを使った アプリ開発について さらに学びたければ 「Elevate your windowed app for spatial computing」で マルチプラットフォームアプリの更新や オーナメントの足し方 ホバーエフェクトやマテリアルの詳細などを 学ぶことができます それでは次の次元である ボリュームについてです 宇宙に興味がある仲間に 地球を別の観点から見れるようにしましょう それにはボリュームがピッタリです ボリュームを足すには ウインドウで使った WindowGroup シーンを使い volumetric window styleと設定します またコンテンツが収まるよう default sizeも設定します ではシミュレータで見てみましょう このボリュームでは RealityKitにあるModel3D APIで 地球の3Dモデルを表示しています Model3D使えば 3Dコンテンツを 簡単に足すことができます Model3Dは画像を表示するのと同様に 美しい3Dコンテンツを 簡単に読み込み表示できます ただし画像読み込みとは異なり Model3Dは常に非同期で読み込みます 3Dコンテンツは読み込みと表示に 時間がかかるからです AsyncImage viewのように Model3Dはコンテンツの読み込み中 自動的にプレースホルダーを表示し もしくは 独自のプレースホルダーも表示できます ここで重要なことは Model3DはSwiftUI Viewであるということです いままでと同じ世界観で 3DをSwiftUIアプリに持ち込むことができます レイアウトシステムや視覚効果 ジェスチャーなどはすでにご存知の概念です ではこのアプリで試してみましょう コントロールで 地球に息を吹き込みます Control panel UIは作成済みで 地球モデルの前に置くことにします そのためにZStackレイアウトを使います ZStackのようなレイアウトは 高さや幅と同様に 奥行きも既にもっています Model3Dは自動的に 2Dのイメージ同様に コンテンツのサイズを調整します 実際 レイアウトシステムが コンテンツの奥行きとスペースに応じて レイアウトを調節します また奥行きのレイアウトに対する動作を 制御するmodifierがあり padding3D modifierは SwiftUI viewsの 前と後ろにスペースを追加します ではコントロールの配置に 使用してみましょう ボリュームはどの角度でも 見られるため コンテンツの配置を 3次元で考える必要があります 最後にコントロールの見た目を良くし 調和させるため glassBackgroundEffect modifierで 先程のウインドウのような 美しいガラス感を与えることにします これでコントロールが完成しました この地球をスピンさせ 場所をランダムに 選べる方法を追加しましょう 次の休暇先を選ぶのに お気に入りの方法です 3D rotation effectをModel3Dに足します ここではY軸を操作します State variableで回転を追跡します タップされると回転が変わるように bouncy spring animationで タップジェスチャーを足します 試してみましょう ああ 西半球か! 次の休暇先が狭まりましたね 今の効果が 実に3Dだと気付きましたか? みなさんもご存知の geometry effectsにスケールや オフセットなどの3D能力を追加したのです これでもなかなかだとは思いますが まだ改善できます 新しいSwiftUI Viewで RealityKitが持つパワフルな機能に 簡単にアクセスできる RealityViewを使います RealityViewでクロージャを設定し RealityKitコンテンツを表示させます Earth modelの表示に ModelEntityを用意し 読み込むのを待ちます 読み込み終わったら RealityViewのコンテンツに追加します RealityViewのクロージャで async-awaitを直接使用できます コンテンツが読み込まれるまで Model3D同様 プレースホルダーが表示されます Earth entityを読み込み RealityKit APIsライブラリにアクセスし コンテンツをブラッシュアップできます ここでは地球に光を当て 明るい感じを与えようと思います 既にRealityKitでImage-based lightingという コードを書いてあるため ここに呼び出します なかなかよくなりました! RealityViewのトピックはまだまだあります RealityViewでインターフェイスの世界と リッチな3D体験のブレンドが 非常に簡単になりました RealityKitでcustom materials、シェーダー 物理演算など 様々なリッチな要素を追加できます RealityViewとRealityKitについて さらに詳細を学ぶSession 「Build spatial experiences with RealityKit」を ご覧ください ここではRealityViewの 2機能に焦点を当てます gesturesとattachmentsです RealityViewでは SwiftUI gesturesが自動的に付与されるので 3Dコンテンツに息を吹き込むのが簡単です 先程追加したタップジェスチャーと 同じ機能を追加するため タップした場所を取得し マーカーを付け 休暇先を特定できるようにします そのためにSpatialTapGestureを使えば タップした3Dの位置がわかります 地球のどこをタップしたかを確認するため targetedToAnyEntity gesture modifierを 使用します これによりどの部分をタップし それがどこを示すのかといった 情報が得られます それを使ってピンの位置を調べ出します 地球にピンを表示するため RealityView attachmentsを使います Attachmentsクロージャは custom SwiftUI viewsとRealityKit entitiesを 一緒に動作させるために最適な機能です ほかのSwiftUI viewsも RealityViewのattachments クロージャ内で直接足せるため RealityViewのどこにでも RealityKit entitiesとして配置できます ここではpin attachmentを足し 確認のtagを足します そしてupdateクロージャで attachmentのためのentityを探し RealityViewのcontentに足し表示します そしてそのentityを タップした場所に配置します ではスピンしてみましょう すぐに荷造りを始めるべきですね! Volumetricアプリは 可能性に満ちています 「Take SwiftUI to the next dimension」 というセッションでは SwiftUIをRealityKitと使い リッチな3Dインタラクションを構築し レイアウトに奥行きを追加するといった トピックを用意しているので ぜひご覧ください 最後にSwiftUIを使って リッチでイマーシブな3D体験を作れる フルスペースについてお話ししましょう フルスペースではフルコントロールを可能にします どこにでもコンテンツを配置でき クリエイティブな新しい形で 環境を拡張できます またまったく新しい体験を創造するため 周囲を隠して イマーシブにできます では宇宙に飛び出し 太陽系を生き返らせましょう 既にメインウインドウで このページを作り お茶の間宇宙飛行士を 宇宙旅行に招待しています あとは空間を作り上げ 発射ボタンを用意するだけです フルスペースを足すには WindowGroupsの時と同様に ImmersiveSpace sceneを足します ボディ内にスペースのコンテンツの root viewを供給します またスペースのIDも供給して プログラムに従い メインウインドウを開かせます このスペースを新しく開くために openImmersiveSpace environment actionを使います Button内でアクションを起こし スペースのIDっをパスします そうすると… 発射成功です! いいスタートです これまでにない方法で 地球に近づくことができます リアルな雲などの詳細な描画には 感動を覚えるほどです しかし何かが足りません 本当に宇宙にいるように感じたい そのためにパワフルなツールを使います immersion stylesです フルスペースにはいくつかのimmersion stylesがあり 簡単に切り替えることができます Mixed immersionではコンテンツが 実世界と共存しており 軽い体験や環境の拡張に 最適のスタイルです Full immersionでは アプリは完全にイマーシブで 周りの環境を隠し 素晴らしい新たな世界に送られます Progressive immersionは その中間で周りの環境を 残すことができます Progressive immersionでは デバイスにあるDigital Crownで 没入度合いを調節できます このアプリでは 現実から離れたいので full immersionがピッタリです それを実現するため ImmersiveSpace sceneに戻り immersionStyle modifierを足し full immersion styleを指定します ここでサポートするスタイルのリストと 現在のselectionを設定し スタイルを瞬時に変えられるようにします Full immersionを使うとシステムは 実世界の環境を完全に隠します イマーシブにするため 代わりの 仮想環境を提供せねばなりません もちろん今回は 宇宙空間しかありません 新しいRealityViewを作り 宇宙空間を映し出します RealityViewのmakeクロージャで star field entityを読み込み 用意ができたら RealityViewのコンテンツに足します そしてStarfield viewを 地球と太陽の横の太陽系ボディに足します ではズームしてみましょう
まさに宇宙空間に漂う星たちって感じですね
アプリをさらによくするため ARKitを使用できます ARKitはシステムと深く統合された パワフルなフレームワークで 実世界の環境に リアルタイムにアクセスでき world trackingや scene understandingなどのAPIsで コンテンツを実世界の表面に配置できます 新しいツールであるハンドトラッキングは カスタムハンドジェスチャーが作れ コンテンツとリアルに接するなどの 操作を可能にします ARKitをスペースでどう使えるかは 「Meet ARKit for spatial computing」を ご覧ください ARKitを使えば 私のアプリの可能性も広がります そこでもう一つ機能をお見せしましょう ARKitをスペースに統合させ ハンドジェスチャーで 地球を呼び出せるようにしました これで宇宙空間を手で操作が可能です フルスペースの可能性は まだまだあります スペースに飛び出す方法をご紹介する 「Go beyond the window with SwiftUI」で スペースの基本についてさらに掘り下げ 環境に効果を足したり バーチャルハンドを表示させたり SharePlayとの統合などを 学ぶことができます またスペースにおける コンテンツのレンダリングは Metalでコントロールでき CompositorServices frameworkを 使用できます 詳細は「Discover Metal for immersive apps」をご覧ください SwuiftUIで皆さんがどのような素晴らしいアプリを 作るのか非常に楽しみです 美しいウインドウや ボリュームでの新しい次元 そしてフルスペースのイマーシブな体験など 可能性が待っています もっと学びたいなら さらなるトピックもカバーしています 「Principles of Spatial Design」で アプリを輝かせるデザインを 学ぶことができます 既存のUIKitコードを 利用したい場合は 「Meet UIKit for spatial computing」 をご覧ください ありがとうございました 空間コンピューティングを楽しんでください! ♪
-
-
2:02 - Button
Button("Of course") { // perform action }
-
2:41 - Toggle Favorite
Toggle(isOn: $favorite) { Label("Favorite", systemImage: "star") }
-
2:48 - TabView
TabView { DogsTab() .tabItem { Label("Dogs", systemImage: "pawprint") } CatsTab() .tabItem { Label("Cats", image: "cat") } BirdsTab() .tabItem { Label("Birds", systemImage: "bird") } }
-
3:37 - World App
@main struct WorldApp: App { var body: some Scene { WindowGroup("Hello, world") { ContentView() } } }
-
7:03 - World TabView
@main struct WorldApp: App { var body: some Scene { WindowGroup("Hello, world") { TabView { Modules() .tag(Tabs.menu) .tabItem { Label("Experience", systemImage: "globe.americas") } FunFactsTab() .tag(Tabs.library) .tabItem { Label("Library", systemImage: "book") } } } } }
-
8:42 - Stats Grid Section
VStack(alignment: .leading, spacing: 12) { Text("Stats") .font(.title) StatsGrid(stats: stats) .padding() .background(.regularMaterial, in: .rect(cornerRadius: 12)) }
-
9:23 - Fun Fact Button
Button(action: { // perform button action }) { VStack(alignment: .leading, spacing: 12) { Text(fact.title) .font(.title2) .lineLimit(2) Text(fact.details) .font(.body) .lineLimit(4) Text("Learn more") .font(.caption) .foregroundStyle(.secondary) } .frame(width: 180, alignment: .leading) } .buttonStyle(.funFact)
-
13:15 - FunFactButtonStyle
struct FunFactButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .padding() .background(.regularMaterial, in: .rect(cornerRadius: 12)) .hoverEffect() .scaleEffect(configuration.isPressed ? 0.95 : 1) } }
-
14:17 - Globe Volume
@main struct WorldApp: App { var body: some Scene { WindowGroup { Globe() } .windowStyle(.volumetric) .defaultSize(width: 600, height: 600, depth: 600) } }
-
14:36 - Model3D
import SwiftUI import RealityKit struct Globe: View { var body: some View { Model3D(named: "Earth") } }
-
15:40 - Globe with rotation and controls
struct Globe: View { @State var rotation = Angle.zero var body: some View { ZStack(alignment: .bottom) { Model3D(named: "Earth") .rotation3DEffect(rotation, axis: .y) .onTapGesture { withAnimation(.bouncy) { rotation.degrees += randomRotation() } } .padding3D(.front, 200) GlobeControls() .glassBackgroundEffect(in: .capsule) } } func randomRotation() -> Double { Double.random(in: 360...720) } }
-
17:30 - RealityView
RealityView { content in if let earth = try? await ModelEntity(named: "Earth") { earth.addImageBasedLighting() content.add(earth) } }
-
18:57 - RealityView Gesture
struct Earth: View { @State private var pinLocation: GlobeLocation? var body: some View { RealityView { content in if let earth = try? await ModelEntity(named: "Earth") { earth.addImageBasedLighting() content.add(earth) } } .gesture( SpatialTapGesture() .targetedToAnyEntity() .onEnded { value in withAnimation(.bouncy) { rotation.degrees += randomRotation() animatingRotation = true } completion: { animatingRotation = false } pinLocation = lookUpLocation(at: value) } ) } }
-
19:34 - RealityView Attachments
struct Earth: View { @State private var pinLocation: GlobeLocation? var body: some View { RealityView { content in if let earth = try? await ModelEntity(named: "Earth") { earth.addImageBasedLighting() content.add(earth) } } update: { content, attachments in if let pin = attachments.entity(for: "pin") { content.add(pin) placePin(pin) } } attachments: { if let pinLocation { GlobePin(pinLocation: pinLocation) .tag("pin") } } .gesture( SpatialTapGesture() .targetedToAnyEntity() .onEnded { value in withAnimation(.bouncy) { rotation.degrees += randomRotation() animatingRotation = true } completion: { animatingRotation = false } pinLocation = lookUpLocation(at: value) } ) } }
-
21:11 - ImmersiveSpace
@main struct WorldApp: App { var body: some Scene { // (other WindowGroup scenes) ImmersiveSpace(id: "solar-system") { SolarSystem() } } }
-
21:25 - Open ImmersiveSpace Action
@Environment(\.openImmersiveSpace) private var openImmersiveSpace Button("View Outer Space") { openImmersiveSpace(id: "solar-system") }
-
22:50 - ImmersionStyle
@main struct WorldApp: App { @State private var selectedStyle: ImmersionStyle = .full var body: some Scene { // (other WindowGroup scenes) ImmersiveSpace(id: "solar-system") { SolarSystem() } .immersionStyle(selection: $selectedStyle, in: .full) } }
-
23:17 - Starfield
struct Starfield: View { var body: some View { RealityView { content in let starfield = await loadStarfield() content.add(starfield) } } }
-
23:28 - SolarSystem
struct SolarSystem: View { var body: some View { Earth() Sun() Starfield() } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。