๐Ÿ‘†Drag

SwiftUI โŸฉ Gestures โŸฉ Drag โŸฉ

โฌ†๏ธ ้œ€่ฆ๏ผš Vector2D

๐Ÿ“— ๅƒ่€ƒ๏ผšMastering SwiftUI, Ch. 17: Using Gestures (p.374)

import SwiftUI

struct StarView: View {
    
    // โญ๏ธ `@GestureState`: tracks gesture's state
    // โ€ข will reset to original value when gesture endsโ—
    // โ€ข need another @State property to save final stateโ—
    typealias DragState = (offset: CGSize, isDragging: Bool)
    @GestureState private var dragState: DragState = (.zero, false)
    
    // โญ๏ธ save final drag state
    @State private var viewOffset = CGSize.zero
    
    // view body
    var body: some View {
        Image(systemName: "star.circle.fill") 
            .font(.system(size: 100))
            .border(.secondary)
            .overlay(overlay)
            .offset(totalOffset)    // โญ๏ธ apply offset
            .foregroundColor(dragState.isDragging ? .pink : .yellow)
            .gesture(drag)          // โญ๏ธ drag gesture
    }
    
    /// โญ๏ธ drag gesture
    var drag: some Gesture {
        DragGesture() 
            // โญ๏ธ update @GestureState property
            // โ€ข value: DragGesture.Value (current drag gesture's value)
            // โ€ข state: @GestureState property
            // โ€ข transaction: Transaction (ignored)
            .updating($dragState) { value, state, _ in
                // โญ๏ธ update `dragState`
                state.offset = value.translation
                state.isDragging = true
            }
            .onEnded { value in
                // โญ๏ธ when drag ends, `dragState` will reset.
                // โญ๏ธ save final drag total translation to `viewOffset`
                viewOffset += value.translation    // ๐Ÿ…ฟ๏ธ Vector2D
            }
    }
    
    /// view's offset + drag's offset
    var totalOffset: CGSize {
        viewOffset + dragState.offset    // ๐Ÿ…ฟ๏ธ Vector2D
    }
    
    /// overlay text
    var overlay: some View {
        VStack(alignment: .leading) {
            Text(verbatim: "drag: \(dragState.offset)")
                .fixedSize()
            Text(verbatim: "view: \(viewOffset)")
                .fixedSize()
            Text(verbatim: "drag + view: \(totalOffset)")
                .fixedSize()
        }
        .foregroundColor(.secondary)
        .offset(y: -110)
    }
}

Last updated