Apple Vision Pro (visionOS) の SwiftUIでhoverEffectを実装する  | 技術ブログ | 株式会社OnePlanet 読み込まれました

Apple Vision Pro (visionOS) の SwiftUIでhoverEffectを実装する

はじめに

Apple Vision Pro の Windowアプリにおいて、アイトラッキングによる視線に対してホバーの状態をビジュアルで表現するための実装について説明します。

Apple Vision Pro について

Apple Vision Pro について、以下の記事にまとめてます。


Windowプロジェクト

Initial SceneをWindowを選択してvisionOSプロジェクトを作成します。

使用したアイコン

https://www.svgrepo.com/collection/fitness-and-health-food-vectors/

上記の任意のフルーツのSVGファイルをダウンロードします。ダウンロードしたSVGファイルをXcodeで作成したvisionOSプロジェクトのAssetsにドラッグ&ドロップします。

RectFruitButton.swift

import SwiftUI

struct RectFruitButton: View {
    @State var name:String
    @State var action: (_ tap:String) -> Void
    @State private var tap: Bool = false
    
    var body: some View {
        Image(name)
            .resizable()
            .frame(width: 120, height: 120)
            .padding(.all, 20)
            .background(.fill.tertiary, in: .rect(cornerRadius: 24))
            .contentShape(.hoverEffect, .rect(cornerRadius: 24))
            .scaleEffect(self.tap ? 1.5 : 1)
            .onTapGesture {
                self.tap.toggle()
                action(self.tap ? "ON" : "OFF")
            }
        .hoverEffect()
    }
}

四角形のフルーツのImageを実装します。ホバーしている間はビジュアルで表現したいため、.hoverEffectを設定しています。backgroundの形に合わせてcontentShapeでホバー時の形を合わせています。

CircleFruitButton.swift

import SwiftUI

struct CircleFruitButton: View {
    @State var name:String
    @State var action: (_ tap:String) -> Void
    @State private var tap: Bool = false
    
    var body: some View {
        Image(name)
            .resizable()
            .frame(width: 120, height: 120)
            .padding(.all, 20)
            .background(.fill.tertiary, in: .circle)
            .contentShape(.hoverEffect, .circle)
            .scaleEffect(self.tap ? 1.5 : 1)
            .onTapGesture {
                self.tap.toggle()
                action(self.tap ? "ON" : "OFF")
            }
        .hoverEffect()
    }
}

backgroundとcontentShapeを.circleで設定している所以外、RectFruitButton.swiftと同じです。


ContentView.swift

import SwiftUI

struct ContentView: View {
    
    @State var name:String
    
    var body: some View {
        
        VStack(spacing: 100) {
            HStack(spacing: 100) {
                RectFruitButton(name: "grape", action: { tap in self.name = "rect grape \(tap)" })
                RectFruitButton(name: "lemon", action: { tap in self.name = "rect lemon \(tap)" })
                RectFruitButton(name: "peach", action: { tap in self.name = "rect peach \(tap)" })
            }
            HStack(spacing: 100) {
                CircleFruitButton(name: "grape", action: { tap in self.name = "circle grape \(tap)" })
                CircleFruitButton(name: "lemon", action: { tap in self.name = "circle lemon \(tap)" })
                CircleFruitButton(name: "peach", action: { tap in self.name = "circle peach \(tap)" })
            }
            Text(name).font(.extraLargeTitle)
        }
    }
}

RectFruitButtonとCircleFruitButtonを縦2行、横3列で並べています。


実行

カーソルを合わせると、ホバーします。RectとCircleの形に合わせて、違和感なく状態が変化します。タップすると、スケールが変わり、スケールにあったホバー状態になります。

XR エンジニア

徳山 禎男

SIerとして金融や飲料系など様々な大規模プロジェクトに参画後、2020年にOnePlanetに入社。ARグラスを中心とした最先端のAR技術のR&Dや、法人顧客への技術提供を担当。過去にMagic Leap 公式アンバサダーを歴任。

View More

お問い合わせ・ご相談

ARでやってみたいことやお困りごとなど
お気軽にお問い合わせください。

お問い合わせ