【初心者】Swift UIを勉強する その⑦ ーーーmatchedGeometryEffect

# はじめに

前回のアニメーションを踏まえて、`matchedGeometryEffect()`を使って少し複雑なアニメーションを作っていきます。
![Mar-07-2021 21-53-52.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1065841/8181f8f8-ac22-298c-08a3-913d97ff88a9.gif)


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [matchedGeometryEffect](#matchedGeometryEffect)
2. [まとめ](#まとめ)
3. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#matchedGeometryEffect"></a>
# matchedGeometryEffect
・[`matchedGeometryEffect()` --- If inserting a view in the same transaction that another view with the same key is removed, the system will interpolate their frame rectangles in window space to make it appear that there is a single view moving from its old position to its new position.](https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:))

・つまり、アニメーションを作成の際に、初めの状態と終わりの状態を定義すれば、プログラムが勝手に動いてくれるということです。
・例えば、以下のように楕円は初めに横100縦200として、タップされたら横200縦100に変わっていきました。しかし、変化する最中に横縦は特に指定されていません。

```swift
struct ContentView: View {
    @State var expand = false
    
    var body: some View {
        Ellipse()
            .fill(Color.blue)
            .frame(width: expand ? 100 : 200, height: expand ? 200 : 100)
            .offset(y: expand ? -250 : 0)
            .animation(.easeIn)
            .onTapGesture {
                self.expand.toggle()
            }
    }
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1065841/fbcb2ef8-8b4f-ef7d-5139-ebc836324bfe.gif" width=20%>　　　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1065841/fcb49826-441d-ea99-fbff-a45a00ce0e2c.gif" width=20%>　　　


・実際に前回作ったカードで`matchedGeometryEffect()`を試していきましょう。
・`CourseItem()`は2回呼ばれて、それぞれ初めの状態と終わりの状態を表しています。
　`isSourse`はビューをグループ内の他のビューのジオメトリのソースとして使用する場合にTrueを指定します。
　`show.toggle()`はタップされたら`Bool`が変わります。

```swift:CoursesView.swift
struct CoursesView: View {
    @State var show = false
    @Namespace var namespace
    
    var body: some View {
        ZStack {
            CourseItem()
                .matchedGeometryEffect(
                    id: "Card", in: namespace, isSource: !show
                )
                .frame(width: 335, height: 250)
            if show {
                CourseItem()
                    .matchedGeometryEffect(id: "Card", in: namespace)
                    .transition(.opacity)
                    .zIndex(1)
                    .edgesIgnoringSafeArea(.all)
            }
        }
        .onTapGesture {
            withAnimation(.spring()) {
                show.toggle()
            }
        }
    }
}
```
・この間作った`CourseRow()`を使って、カードがタップされたら`CourseRow()`のリストを出せるようにします。
・状態が終わった後にリストを追加するので、2回目に呼ばれた`CourseItem()`を`ScrollView`に突っ込みます。
　また、全画面にしたくないので、縦を300にします。

```swift:CoursesView.swift
ScrollView {
     CourseItem()
          .matchedGeometryEffect(id: "Card", in: namespace)
          .frame(height: 300)
}
```

・`ForEach`で`CourseRow()`を表示されます。

```swift:CoursesView.swift
ForEach(0 ..< 20) { item in
      CourseRow()
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1065841/ed4b25f7-d847-a09b-f2f5-9ef79a26b14f.gif" width=20%>　　


<a id="#まとめ"></a>
# まとめ
・気づいているかもしれませんが、リストの消えるタイミングが遅くて、次回はこれを解決します。

**ソースコード[Github](https://github.com/wsimple1028/swiftUI_ios14)**

<a id="#reference"></a>
# 参考文献
- [Design Code --- SwiftUI for iOS 14](https://designcode.io/swiftui-ios14)
- https://www.anchorblogs.com/details/5