SwiftUI modifier that adds smooth pinch‑to‑zoom, panning, and double‑tap zoom with sensible clamping and optional haptics (iOS 17+). Includes a lightweight logging hook and programmatic centering support.
- iOS 16.0+ / macOS 11.0+
- Swift 5.9+
- In Xcode: File → Add Package Dependencies…
- Enter the repo URL for this package.
- Add the
ZoomableViewlibrary to your target.
Wrap your content in a GeometryReader to supply the container size, then apply .zoomable(...):
import SwiftUI
import ZoomableView
struct ContentView: View {
var body: some View {
GeometryReader { proxy in
Image(.images)
.resizable()
.zoomable(
containerSize: proxy.size,
logger: ConsoleLogger() // optional
)
}
}
}
struct ConsoleLogger: Logger {
func log(_ message: String, level: LogLevel, file: String, function: String, line: Int) {
print("[\(level.rawValue.uppercased())] \(message)")
}
}Pass a binding to focusPoint (in content coordinates). Setting it will center that point in the container; the value is cleared automatically.
@State private var focus: CGPoint?
GeometryReader { proxy in
Image(.images)
.resizable()
.zoomable(
containerSize: proxy.size,
focusPoint: $focus,
minZoomScale: 1,
maxZoomScale: 4
)
}
// Example: center on the middle of the image later
focus = CGPoint(x: imageSize.width / 2, y: imageSize.height / 2)Double tap toggles between 1.0 scale and doubleTapZoomScale (default 2.0) anchored at the tap location. On iOS 17+ it emits selection haptics.
containerSize: Required. Size of the viewport that should clamp panning.focusPoint: Optional binding for programmatic centering (cleared after use).minZoomScale/maxZoomScale: Clamps pinch zooming.doubleTapZoomScale: Target scale when toggling from the base scale.animationDuration: Duration for double-tap zoom and clamping animations.logger: OptionalLoggerto observe transforms and clamping.
Provide any Logger implementation to receive debug messages from gesture end and clamping logic. The protocol supplies debug, info, warning, and error helpers.
- Content is clamped to stay within the container; if the scaled content is smaller than the container, it recenters automatically.
- On macOS, gesture support depends on available input devices; pinch and double-tap behavior mirror iOS where supported.
