# .draggable()

[SwiftUI](https://lochiwei.gitbook.io/ios/swiftui) ⟩ [Gestures](https://lochiwei.gitbook.io/ios/swiftui/gestures) ⟩ [Drag](https://lochiwei.gitbook.io/ios/swiftui/gestures/drag) ⟩ .draggable()

{% tabs %}
{% tab title="🌀 View+ .draggable()" %}

```swift
import SwiftUI

// 👔 Draggable
struct Draggable: ViewModifier {
    
    // 🔸 此變數目前沒什麼用，但在其他狀況下，也許可派上用場。
    @State var isDragging = false
    
    // 🔸 拖曳時，offset 會隨時更新，但 dragOffset 保持不變。
    //    沒拖曳時，兩者是一樣的。
    @State private var offset = CGSize.zero        // current offset
    @State private var dragOffset = CGSize.zero    // prev accumulative offset
    
    // ⭐️ optional event handlers
    typealias OffsetHandler = (CGSize) -> Void
    var onChanged: OffsetHandler?
    var onEnded  : OffsetHandler?
    
    func body(content: Content) -> some View {
        content
            .offset(offset)        // ⭐️ apply offset
            .gesture(
                DragGesture()
                    .onChanged { value in
                        isDragging = true
                        // update offset
                        offset = dragOffset + value.translation
                        // event handler
                        onChanged?(offset)
                    }
                    .onEnded { value in
                        isDragging = false
                        // update offset
                        offset = dragOffset + value.translation
                        // ⭐️ save accumulative offset
                        dragOffset = offset
                        // event handler
                        onEnded?(offset)
                    }
            )
    }
}

// 🌀 View+ .draggable()
extension View {
    /// `view.draggable(onChanged:onEnded:)`
    func draggable(
        onChanged: Draggable.OffsetHandler? = nil, 
        onEnded  : Draggable.OffsetHandler? = nil
    ) -> some View {
        modifier(Draggable(onChanged: onChanged, onEnded: onEnded))
    }
}
```

{% endtab %}

{% tab title="👁️ 預覽" %}
{% embed url="<https://youtu.be/fcNPtYRCsAA>" %}

⬆️ 需要： [ext](https://lochiwei.gitbook.io/ios/swiftui/view/layout/frame/ext "mention"), [handlepoint](https://lochiwei.gitbook.io/ios/swiftui/gestures/drag/.draggable/handlepoint "mention")

```swift
import SwiftUI

struct TestDraggable: View {
    var body: some View {
        VStack {
            Group {
                HandlePoint()       // 🖼 HandlePoint
                Color.pink
                    .frame(50)      // 🌀 View+ .frame()
                    .draggable()    // 👔 Draggable
                Capsule()
                    .frame(200, 50) // 🌀 View+ .frame()
                    .foregroundColor(.blue)
                    .draggable()    // 👔 Draggable
            }
            .border(.secondary)
        }
    }
}

struct TestDraggable_Previews: PreviewProvider {
    static var previews: some View {
        TestDraggable()
    }
}
```

{% endtab %}

{% tab title="📗 參考" %}

* Vasilis Akoinoglou ⟩ [Making a Bézier Curve Editor in SwiftUI](https://alladinian.hashnode.dev/making-a-bezier-curve-editor-in-swiftui) ⭐️
  {% endtab %}

{% tab title="⬇️ 應用" %}

* [handlepoint](https://lochiwei.gitbook.io/ios/swiftui/gestures/drag/.draggable/handlepoint "mention") - draggable point.
  {% endtab %}

{% tab title="👥 相關" %}

* is [viewmodifier](https://lochiwei.gitbook.io/ios/swiftui/view/modifier/viewmodifier "mention").
  {% endtab %}
  {% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/ios/swiftui/gestures/drag/.draggable.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
