History
Loading...
Loading...
October 2, 2025
.scaleEffect() combined with MagnificationGesture() to create smooth zoom interactions. Pro tip: Store the final scale in @GestureState and apply it cumulatively with a separate @State variable to prevent jarring resets when the gesture ends.This pattern separates temporary gesture state from persistent scale state, applies zoom boundaries during both gesture and final states, and provides smooth visual feedback without jarring transitions when gestures end.
@State private var finalScale: CGFloat = 1.0
@GestureState private var gestureScale: CGFloat = 1.0
var body: some View {
Image("photo")
.scaleEffect(finalScale * gestureScale)
.gesture(
MagnificationGesture()
.updating($gestureScale) { value, state, _ in
let bounded = min(max(value, 0.5), 3.0)
state = bounded
}
.onEnded { value in
let newScale = finalScale * value
finalScale = min(max(newScale, 0.5), 3.0)
}
)
}Using @GestureState ensures automatic cleanup when gestures are cancelled, while bounded scaling prevents users from zooming to unusable extremes. The cumulative approach with separate state variables maintains smooth UX and prevents the common issue of content snapping back to original size mid-gesture.