[SwiftUI] SideMenuViewを作りたい

## はじめに
こんにちは!
アプリ開発が好きで、Swiftの勉強をしている大学生です。
夏休みに入ったので、アウトプット頑張っていきたいと思っています。
温かい目で見ていただけると幸いです。

## やりたいこと
以下のように、あるボタンを押したらサイドバーが現れるようにしたいです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119753/ff2aa9a2-749e-06c1-19f8-150431bf5b16.gif" width="250"> 

## 実装イメージ
1. HogeViewとSideMenuView(サイドーバーのViewのこと)の２つのViewを用意します
1. 上記二つのViewをHStackで囲み、そのOffsetを変更する

イメージはこんな感じです。

## 実装
まずはHogeViewを用意します。
```swift
public struct HogeView: View {
    // sideMenuViewを表示・非表示を決めるフラグ
    @Binding var isSideMenu: Bool
    
    public init(isSideMenu: Binding<Bool>) {
        self._isSideMenu = isSideMenu
    }
    // 今回は簡易的なViewだけを用意
    public var body: some View {
        VStack {
            Button {
                // ボタンのタップに応じてtoggleします
                isSideMenu.toggle()
            } label: {
                Text("open SideMenu")
            }
        }
        .frame(maxHeight: .infinity)
    }
}

```
次にSideMenuViewを用意します。
```swift

public struct SideMenuView: View {
    // HogeViewと同様のフラグ
    @Binding var isSideMenu: Bool
    
    public init(isSideMenu: Binding<Bool>) {
        self._isSideMenu = isSideMenu
    }

    // 簡易的なViewを用意
    public var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            ScrollView {
                VStack(spacing: 15) {
                    Text("HogeHoge~~~")
                        .font(.system(size: 24).bold())
                    
                    Text("Side Menu")
                }
                .padding(.top, 20)
            }
        }
        // 画面の約5/4まで表示したいのでoffsetをframeをいじります
        .frame(width: getScreenWidth() - 90)
        .background {
            Color.primary
                .opacity(0.04)
                .ignoresSafeArea(.container, edges: .vertical)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
    }
}
```
上記の`getScreenWidth()`ですが下記のようなextensionで画面の幅を取得しています
```swift
public extension View {
    func getScreenWidth() -> CGFloat {
        return UIScreen.main.bounds.width
    }
}
```
最後にこのHogeViewとSideMenuViewを繋げるConnecterView(もっといい命名ありそう)というものを作ります。
```Swift

public struct ConnecterView: View {
    @State private var isSideMenu = false
    @State private var offset: CGFloat = 0

    public init() {}
    
    public var body: some View {
        let sideBarWidth = getScreenWidth() - 90
        HStack(spacing: 0) {
            SideMenuView(isSideMenu: $isSideMenu)
            
            HogeView(isSideMenu: $isSideMenu)
                .frame(width: getScreenWidth())
                .overlay {
                    Rectangle()
                        .fill(
                            Color.primary
                                .opacity(Double((offset / sideBarWidth) / 5))
                        )
                        .ignoresSafeArea(.container, edges: .vertical)
                        .onTapGesture {
                            isSideMenu.toggle()
                        }
                }
        }
        // これでHStackを大きな一つのViewとして捉え、offsetを動かす
        .frame(width: getScreenWidth() + sideBarWidth)
        .offset(x: -sideBarWidth / 2)
        .offset(x: offset)
        .onChange(of: isSideMenu) { _ in
            // 下記条件に応じてoffsetをいじる
            if isSideMenu && offset == 0 {
                withAnimation {
                    offset = sideBarWidth
                }
            }
            
            if !isSideMenu && offset == sideBarWidth {
                withAnimation {
                    offset = 0
                }
            }
        }
    }
}
```

これで実装できました

### Tip: これだけでは物足りない
現状のコードだけでは下記のような機能がなく物足りないです。

- Dragに応じてSideMenuViewを表示する
- SideMenuViewからNavigationLink等で画面遷移した時に、遷移先のViewがSideMenuViewの幅のまま表示されています。

後ほど、これも解決していきたいと思います。


## 終わりに
誰かの役に立つことができていれば幸いです。
アウトプットを頑張ろうと思っているので温かい目で見ていただけると嬉しいです。