WWDC2023から見えてくるvisionOSアプリケーションの開発について

WWDC2023でApple Vision Proが発表され、そのOSであるvisionOSも発表されました。
本記事ではvisionOS向けにどのようにアプリを開発するか、WWDC2023で公開された動画を元に紹介していきたいと思います。

# Apple Vision Proについて

空間コンピューティングと言われているように、Apple Vision Proでは映像として映される現実世界に仮想のディスプレイなどを配置し、それを操作するようなコンピューティングを実現しています (もちろんVRのような視界全体を埋め尽くすような別世界に没入することもできます) 。

![8350_wide_900x506_2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/efd8eab7-9df0-8751-9fe4-461e9c9370dd.jpeg)

Apple Vision Pro上で動作するアプリはさまざまな形式があるのですが。上の写真にあるような従来の平面のアプリケーションはWindowsと呼ばれており、他にはVolumes、Spacesがあります。

特にWindowsはmacOSやiOS上で動作するアプリと大きくは違わない外観をしていますが、これらは従来のデバイスとは異なり、視線と手の動き、そして声によって操作するものとなっています。

![スクリーンショット 2023-06-18 22.37.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/d2cbddff-6ff4-ddcd-44c0-2f1cf84766f7.png)

# visionOSのユーザインタフェース

macOSやiOSと特に異なるUIの特徴について紹介します。

### Glass Material

デモで登場したアプリの背景部のパネルは磨りガラスのように透過していました。
これは空間に馴染むよう設計され、角が丸くなっていたり、部屋の明るさによって背景色が変わるようになっています。
逆に、不透明な背景色は避けることが推奨されているようです。

| 明るい部屋の場合 | 暗い部屋の場合 |
| ---- | ---- |
| ![スクリーンショット 2023-06-18 22.44.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/5a2923dc-7af2-4910-58fb-ba0129a7795d.png) | ![スクリーンショット 2023-06-18 22.44.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/a4a856ec-f49a-56d0-ab17-3523daf77ef0.png) |

上の画像ではナビゲーション部分の背景色と、コンテンツ部分の背景色が異なります。
このようにして、異なる透過な背景色を用いることで領域を分けることが推奨されているようです。

### タイポグラフィ

visionOSではiOSよりも大きなフォントが推奨されています。
これは実際にApple Vision Proをつけてみて実感したいですね。

![スクリーンショット 2023-06-20 9.08.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/ba30fb12-af3d-1432-9681-a9482aabf4a6.png)

# visionOSアプリケーションの構成要素

visionOSにおけるUIコンポーネントについて紹介します。

### Button

macOSやiOSと同様にvisionOSアプリにもボタンがあります。
iOSとの大きな違いはホバーの存在で、視線を合わせると背景色が変わります。
分かりにくいですが、下の画像は2つのボタンのうち上のボタンに視線を合わせており、微妙に色が異なっています。
macOSでマウスポインタをボタンに合わせたときに色が変わるのに似ています。

![スクリーンショット 2023-06-19 22.40.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/b76adb67-983e-4aab-8b24-d83d3fbb240a.png)

SwiftUIのコード自体は変わりないようです。

```swift
Button("Of course") {
  // perform action
}
```

また、Toggleの例ですが、視線を合わせたときにラベルを表示することもできるようです。

<img width="300" alt="c6f03701394f" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/52fc83b2-b5c7-1c56-6caa-c6f03701394f.png">

```swift
Toggle(isOn: $favorite) {
    Label("Favorite", systemImage: "star")
}
```

### TabView

visionOSアプリでのTabViewは、下の画像のようにWindowの横にアイコンが独立して存在するようなかたちになっています。

![スクリーンショット 2023-06-19 21.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/640e0c64-5a65-5a7f-1895-91fd36dd1f74.png)

TabViewのコードをSwiftUIで書くと以下のようになり、従来とあまり変わらないようになっています。

```swift
@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")
                    }                    
            }
        }
    }
}
```

ただ、従来のTabViewと異なる点として、視線を合わせることによって表示される内容が変わる、というものがあります。

![スクリーンショット 2023-06-19 21.56.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/2bf9ed36-126d-9ccb-d815-33fbeae6bf4b.png)

### Volume

3Dのオブジェクトを表現する場合　 `volumetric` という `windowStyle` を使います。

<img width="500" alt="3c7f36f356e4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/48fc6a96-d37b-18ea-ccd3-3c7f36f356e4.png">

3DオブジェクトはRealityKitの `Model3D`　を使うようです。

```swift
@main
struct WorldApp: App {
    var body: some Scene {
        WindowGroup {
            Globe()
        }
        .windowStyle(.volumetric)
        .defaultSize(width: 600, height: 600, depth: 600)
    }
}

struct Globe: View {
    var body: some View {
        Model3D(named: "Earth")
    }
}
```

`Model3D` 自体にはタップジェスチャーなどをつけることができるようで、デモではタップしたら回転する地球が紹介されていました。

```swift
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)
    }
}
```

また、コントロール部を置くこともできるようで、デモでは `GlobeControls` というViewを追加していました。

<img width="500" alt="91e0a7f7a8dd" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42150/2bb6ec37-48bc-b18a-cac7-91e0a7f7a8dd.png">

# まとめ

visionOSアプリの開発についてWWDC2023の内容をベースにまとめました。
世間の期待度も大きいので、早く開発してみて、知見をためていければと思っています。

# 引用元
https://developer.apple.com/videos/play/wwdc2023/10109/
https://developer.apple.com/videos/play/wwdc2023/10076/