Skip to content

Commit

Permalink
add rotation buttons (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
daveddm authored Oct 7, 2024
1 parent 6ee0b98 commit b15fb96
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 14 deletions.
18 changes: 11 additions & 7 deletions Demo/SwiftyCropDemo/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct ContentView: View {
@State private var selectedShape: MaskShape = .square
@State private var rectAspectRatio: PresetAspectRatios = .fourToThree
@State private var cropImageCircular: Bool
@State private var rotateImage: Bool
@State private var rotation: Rotation
@State private var maxMagnificationScale: CGFloat
@State private var maskRadius: CGFloat
@State private var zoomSensitivity: CGFloat
Expand All @@ -31,7 +31,7 @@ struct ContentView: View {
init() {
let defaultConfiguration = SwiftyCropConfiguration()
_cropImageCircular = State(initialValue: defaultConfiguration.cropImageCircular)
_rotateImage = State(initialValue: defaultConfiguration.rotateImage)
_rotation = State(initialValue: defaultConfiguration.rotation)
_maxMagnificationScale = State(initialValue: defaultConfiguration.maxMagnificationScale)
_maskRadius = State(initialValue: defaultConfiguration.maskRadius)
_zoomSensitivity = State(initialValue: defaultConfiguration.zoomSensitivity)
Expand Down Expand Up @@ -92,15 +92,19 @@ struct ContentView: View {
ForEach(PresetAspectRatios.allCases, id: \.self) { aspectRatio in
Text(aspectRatio.rawValue)
}

}
.pickerStyle(.segmented)
}
}

Toggle("Crop image to circle", isOn: $cropImageCircular)

Toggle("Rotate image", isOn: $rotateImage)
Picker("Rotation", selection: $rotation) {
ForEach(Rotation.allCases, id: \.self) { rotation in
Text(String(describing: rotation))
}
}
.pickerStyle(.segmented)

HStack {
Text("Max magnification")
Expand Down Expand Up @@ -159,7 +163,7 @@ struct ContentView: View {
maxMagnificationScale: maxMagnificationScale,
maskRadius: maskRadius,
cropImageCircular: cropImageCircular,
rotateImage: rotateImage,
rotation: rotation,
zoomSensitivity: zoomSensitivity,
rectAspectRatio: rectAspectRatio.getValue()
)
Expand All @@ -179,8 +183,8 @@ struct ContentView: View {

// Example function for downloading an image
private func downloadExampleImage() async -> UIImage? {
let portraitUrlString = "https://picsum.photos/1000/1200"
let landscapeUrlString = "https://picsum.photos/2000/1000"
let portraitUrlString = "https://picsum.photos/1000/1200.jpg"
let landscapeUrlString = "https://picsum.photos/2000/1000.jpg"
let urlString = Int.random(in: 0...1) == 0 ? portraitUrlString : landscapeUrlString
guard let url = URL(string: urlString),
let (data, _) = try? await URLSession.shared.data(from: url),
Expand Down
5 changes: 5 additions & 0 deletions Sources/SwiftyCrop/Models/Rotation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Foundation

public enum Rotation: CaseIterable {
case none, gesture, buttons
}
10 changes: 5 additions & 5 deletions Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public struct SwiftyCropConfiguration {
public let maxMagnificationScale: CGFloat
public let maskRadius: CGFloat
public let cropImageCircular: Bool
public let rotateImage: Bool
public let rotation: Rotation
public let zoomSensitivity: CGFloat
public let rectAspectRatio: CGFloat

Expand All @@ -18,23 +18,23 @@ public struct SwiftyCropConfiguration {
/// Defaults to `130`.
/// - cropImageCircular: Option to enable circular crop.
/// Defaults to `false`.
/// - rotateImage: Option to rotate image.
/// Defaults to `false`.
/// - rotation: Controls how the image can be rotated. Options are `.gesture`, `.buttons`, and `.none`.
/// Defaults to `.none`.
/// - zoomSensitivity: Sensitivity when zooming. Default is `1.0`. Decrease to increase sensitivity.
///
/// - rectAspectRatio: The aspect ratio to use when a `.rectangle` mask shape is used. Defaults to `4:3`.
public init(
maxMagnificationScale: CGFloat = 4.0,
maskRadius: CGFloat = 130,
cropImageCircular: Bool = false,
rotateImage: Bool = false,
rotation: Rotation = .none,
zoomSensitivity: CGFloat = 1,
rectAspectRatio: CGFloat = 4/3
) {
self.maxMagnificationScale = maxMagnificationScale
self.maskRadius = maskRadius
self.cropImageCircular = cropImageCircular
self.rotateImage = rotateImage
self.rotation = rotation
self.zoomSensitivity = zoomSensitivity
self.rectAspectRatio = rectAspectRatio
}
Expand Down
27 changes: 25 additions & 2 deletions Sources/SwiftyCrop/View/CropView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ struct CropView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity)
.simultaneousGesture(magnificationGesture)
.simultaneousGesture(dragGesture)
.simultaneousGesture(configuration.rotateImage ? rotationGesture : nil)
.simultaneousGesture(configuration.rotation == .gesture ? rotationGesture : nil)

HStack {
Button {
Expand All @@ -121,6 +121,29 @@ struct CropView: View {
.foregroundColor(.white)

Spacer()

if configuration.rotation == .buttons {
HStack(spacing: 16) {
Button {
viewModel.lastAngle = Angle(degrees: viewModel.lastAngle.degrees - 90)
} label: {
Image(systemName: "rotate.left")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(.white)
}

Button {
viewModel.lastAngle = Angle(degrees: viewModel.lastAngle.degrees + 90)
} label: {
Image(systemName: "rotate.right")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(.white)
}
}
Spacer()
}

Button {
onComplete(cropImage())
Expand All @@ -146,7 +169,7 @@ struct CropView: View {

private func cropImage() -> UIImage? {
var editedImage: UIImage = image
if configuration.rotateImage {
if configuration.rotation != .none {
if let rotatedImage: UIImage = viewModel.rotate(
editedImage,
viewModel.lastAngle
Expand Down

0 comments on commit b15fb96

Please sign in to comment.