Reputation: 15
I'm working on a SwiftUI project where I have one rectangle that I want to be draggable within an active area. However, I'm facing an issue where the rectangle can go outside the active area during the drag gesture. I want to constrain the position of the rectangle so that it stays within the active area during the drag gesture. How can I achieve this? Any insights or suggestions would be greatly appreciated. Thank you in advance!
Here's a simplified version of my code:
struct ContentView: View {
@State var position = CGSize.zero
@State var lastPosition = CGSize.zero
var body: some View {
ZStack {
Rectangle()
.fill(Color(red: 0.5450980392156862, green: 0.5450980392156862, blue: 0.5450980392156862))
.aspectRatio(0.75, contentMode: .fit)
.frame(height: 550)
.cornerRadius(30)
.offset(x: position.width, y: position.height)
.animation(.spring(response: 0.4, dampingFraction: 0.4, blendDuration: 0.4))
.gesture(
DragGesture()
.onChanged({ value in
position = CGSize(width: lastPosition.width + value.translation.width, height: lastPosition.height + value.translation.height)
})
.onEnded({ value in
lastPosition = position
})
)
.padding()
}
}
}
Upvotes: 1
Views: 516
Reputation: 1342
Does something like this match what you are looking for?
struct ContentView: View {
@State var position = CGSize.zero
@State private var rectangleSize = CGRect.zero
var body: some View {
GeometryReader { geometry in
ZStack {
Rectangle()
.fill(Color(red: 0.5450980392156862, green: 0.5450980392156862, blue: 0.5450980392156862))
.aspectRatio(0.75, contentMode: .fit)
.frame(width: 20, height: 50)
.overlay(
GeometryReader { geo in
Color.clear
.onAppear{
rectangleSize = geo.frame(in: .global)
}
})
.cornerRadius(30)
.offset(position)
.animation(.spring(response: 0.4, dampingFraction: 0.4, blendDuration: 0.4))
.gesture(
DragGesture()
.onChanged({ value in
let xLoc = max(min(value.location.x, geometry.size.width - 1 * rectangleSize.width),0)
let yLoc = max(min(value.location.y, geometry.size.height - 1 * rectangleSize.height),0)
position = CGSize(width: xLoc, height: yLoc)
})
)
}
}
}
}
The main things that were changed are using the drag location instead of the translation and calculating the offset so that the width and heights have values greater than 0 but less than the screen width
Upvotes: 0