See the comment in the code below.
struct ContentView: View {
@State private var offset = CGSize.zero
var body: some View {
VStack {
Circle()
.fill(.blue)
.frame(width: 200, height: 200)
Circle()
.fill(.red)
.frame(width: 100, height: 100)
.offset(offset)
.gesture(
DragGesture()
.onChanged { gesture in
offset = gesture.translation
}
.onEnded { _ in
//how to check if the small red circle is more than halfway into the large blue circle???
}
)
}
}
}
Or more generally, how can you check for view intersection/overlapping in SwiftUI?
You can use a GeometryReader
in the background of each shape to find their frames in the global coordinate space.
To determine if the red circle is more than half inside the blue circle, you can test whether the mid-point of the red frame is enclosed within the path of the blue circle.
To have the offset reset automatically, I changed the state variable to a GestureState
.
struct ContentView: View {
@GestureState private var offset = CGSize.zero
@State private var bluePath: Path?
@State private var isMoreThanHalfInside = false
var body: some View {
VStack {
Circle()
.fill(.blue)
.frame(width: 200, height: 200)
.background(
GeometryReader { proxy in
let frame = proxy.frame(in: .global)
Color.clear
.onAppear {
bluePath = Circle().path(in: frame)
}
}
)
Circle()
.fill(isMoreThanHalfInside ? .yellow : .red)
.opacity(offset == .zero ? 1 : 0.9)
.overlay(Image(systemName: "plus").fontWeight(.thin))
.frame(width: 100, height: 100)
.background(
GeometryReader { proxy in
let frame = proxy.frame(in: .global)
let midPoint = CGPoint(x: frame.midX, y: frame.midY)
Color.clear
.onChange(of: midPoint) { oldVal, newVal in
isMoreThanHalfInside = bluePath?.contains(newVal) ?? false
}
}
)
.offset(offset)
.gesture(
DragGesture(minimumDistance: 0)
.updating($offset) { val, state, trans in
state = val.translation
}
)
}
}
}