Open14

[SwiftUI] PizzaApp

🍤🍤

[View]HomeView

サイズについて現在選択しているものが浮かび上がるようにした。

🍤🍤

[View]HomeView

ピザの大きさに合わせていろいろ動くようにした。
サイズはeurm型に入れた。
それをForEachでsizeに入れる。
Buttonで現在認識しているsizeを取得させていい感じに動かす。

🍤🍤

[View]HomeView

トッピング画像の表示。

🍤🍤

[View]HomeView

カートに追加するButton。

🍤🍤

[View]HomeView

まずPizzaのindexを取ってくる。

インデックスを検索し、トッピングを追加&削除する。
ランダムに配置。

🍤🍤

struct ~ var body: some View

  • @State var pizzas: [Pizza] = [ ] でPizza配列を作成。
  • ピザ生地の初期値を @State var currentPizza: String = "Bread_1" とする。
  • サイズの初期値をmediumにする。
  • @Namespace var animation
  • toppings配列を定義
  • ヘッダー画像関係のコードをアクセス修飾詞fileprivateで囲う。func extractedFunc。

ヘッダー Image

  • VStack ヘッダー 〜 サイズ選択部分まで囲う。
  • extractedFunc()
  • VStack内にGometryReaderを設置。取得したViewサイズ = インスタンスsizeに入れる。
  • ZstadeでAssetsのPlateを配置。

スワイプでピザの切り替え

  • TabView(selection: $currentPizza) { ForEach ...

現在選択しているPizza画像を認識する挙動

  • まだここはVStack,ZStack配下。
  • ZStack上にTabViewを形成する。
  • TabView内にもZStackを設置し、ピザ生地とトッピングを一体の画像として配置できるようにする。
  • 子ViewとしてPizza配列にいるbreadNameで識別できるImageを設定する。
  • 別で定義した関数 ToppingsViewを設置。
  • ピザ生地とトッピングの入っているZStackのモディファーとして.scaleEffecttagを設置。
  • enum型に入っているサイズS,M,Lの変動に合わせて、.largeだったら1,.mediumだったら0.95,それでもなかったら0.09にサイズを変更させる。
🍤🍤

関数 ToppingsView

  • トッピングの画像の挙動を定義している関数。
  • Groupで全体を大きく囲う。
  • ForEachでトッピング配列を回す。この時.indicesをつける。
ForEach () { in ...
ForEach(toppings.indices,id: \.self){index in
                //各トッピングは10枚のトッピング画像から構成される
                let topping = toppings[index]
  • .indicesは配列のアクセスできる範囲を示している。
  • トッピングがランダムに配置できるようにしたい。
  • 先のForEach配下にForEachをもう一つ作成する。
  • トッピング20個配置。
         ForEach(1...20,id: \.self){subIndex in
                        
                        // 360/10 = 36....
                        let rotation: Double = Double(subIndex) * 36
                        let crtIndex = (subIndex > 10 ? (subIndex - 10) : subIndex)
                        
                        Image("\(topping.toppingName)_\(crtIndex)")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 35, height: 35)
                        //インデックスは0から始まる
                            .offset(x: (width / 2) - topping.randomToppingPostions[subIndex - 1].width,y: topping.randomToppingPostions[subIndex - 1].height)
                            .rotationEffect(.init(degrees: rotation))
                        
                        // 360回転でランダムな位置にToppingを展開する.
                        //offset(x:y:)指定された水平および垂直距離だけ、このビューをずらして配置
                        //.rotationEffectで回転を動きに加えている。
                    }
  • let rotation: Double = Double(subIndex) * 36
  • let crtIndex = (subIndex > 10 ? (subIndex - 10) : subIndex)
  • Imageを指定。トッピング画像グループは10までしか登録されていないので crtIndexを用いる。
  • offsetでtopping.randomToppingPostionsに紐づけられているCGSizeを取得する。
  • .rotationEffect(.init(degrees: rotation))で回転
🍤🍤

widthには

VStack {
GeometryReader{proxy in
                let size = proxy.size
//ヘッダー、プレート、トッピング&ピザのVIew (値段より上の部分)
 }
}

の、sizeが入っている。

ofset1
.offset(x:  topping.randomToppingPostions[subIndex - 1].width,y: (width / 2) - topping.randomToppingPostions[subIndex - 1].height)


offset2
.offset(x:  topping.randomToppingPostions[subIndex - 1].width,y: topping.randomToppingPostions[subIndex - 1].height)

offset3
.offset(x: (width / 2) - topping.randomToppingPostions[subIndex - 1].width,y: (width / 2) - topping.randomToppingPostions[subIndex - 1].height)

offset4
.offset(x: (width / 2) - topping.randomToppingPostions[subIndex - 1].width,y:  topping.randomToppingPostions[subIndex - 1].height)

🍤🍤
.rotationEffectをコメントアウト
  let rotation: Double = Double(subIndex) * 36
                        let crtIndex = (subIndex > 10 ? (subIndex - 10) : subIndex)
                        
                        Image("\(topping.toppingName)_\(crtIndex)")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 35, height: 35)
                        //インデックスは0から始まる
                            .offset(x: (width / 2) - topping.randomToppingPostions[subIndex - 1].width,y:  topping.randomToppingPostions[subIndex - 1].height)
//                            .rotationEffect(.init(degrees: rotation))

回転の挙動は .rotationEffectが担っている。。。?

🍤🍤

引き続き関数 ToppingsView の中身を見る。

  • .scaleEffectでViewの拡大縮小の動き。
  • 上からトッピング画像が落ちてくるという挙動になっているが、まずここでtoppingを10倍の大きさにする。
  • .scaleEffectはtoppingのBool値が trueだったら作動する。
  • .onAppear以下でトッピングがタップされた直後のアニメーションを書いている。
  • DispatchQueue.main.asyncAfter(deadline: .now() + 0.08) {}
  • 括弧内にwithAnimation