From edc6a5c17b5fb85ceb00eecf5241b4c33a4c75c9 Mon Sep 17 00:00:00 2001 From: Shibo Lyu Date: Thu, 10 Aug 2023 17:20:38 +0800 Subject: [PATCH] feat: Initial image size. --- Sources/CropImage/CropImageView.swift | 24 ++++++++++++++++++--- Sources/CropImage/UnderlyingImageView.swift | 10 +++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Sources/CropImage/CropImageView.swift b/Sources/CropImage/CropImageView.swift index e0eb368..9f9256b 100644 --- a/Sources/CropImage/CropImageView.swift +++ b/Sources/CropImage/CropImageView.swift @@ -37,6 +37,8 @@ public struct CropImageView: View { /// The image to crop. public var image: PlatformImage + /// The region in which the image is initially fitted in, in points. + public var initialImageSize: CGSize /// The intended size of the cropped image, in points. public var targetSize: CGSize /// The intended scale of the cropped image. @@ -56,12 +58,14 @@ public struct CropImageView: View { /// Create a ``CropImageView`` with a custom ``controls`` view. public init( image: PlatformImage, + initialImageSize: CGSize, targetSize: CGSize, targetScale: CGFloat = 1, onCrop: @escaping (Result) -> Void, @ViewBuilder controls: @escaping ControlClosure ) { self.image = image + self.initialImageSize = initialImageSize self.targetSize = targetSize self.targetScale = targetScale self.onCrop = onCrop @@ -72,11 +76,13 @@ public struct CropImageView: View { /// The default ``controls`` view is a simple overlay with a checkmark icon on the bottom-trailing corner to trigger crop action. public init( image: PlatformImage, + initialImageSize: CGSize, targetSize: CGSize, targetScale: CGFloat = 1, onCrop: @escaping (Result) -> Void ) where Controls == DefaultControlsView { self.image = image + self.initialImageSize = initialImageSize self.targetSize = targetSize self.targetScale = targetScale self.onCrop = onCrop @@ -95,7 +101,8 @@ public struct CropImageView: View { offset: $offset, scale: $scale, rotation: $rotation, - image: image + image: image, + initialImageSize: initialImageSize ) .frame(width: targetSize.width, height: targetSize.height) if #available(iOS 16.0, macOS 13.0, *) { @@ -143,7 +150,8 @@ public struct CropImageView: View { offset: $offset, scale: $scale, rotation: $rotation, - image: image + image: image, + initialImageSize: initialImageSize ) RectHoleShape(size: targetSize) .fill(style: FillStyle(eoFill: true)) @@ -163,6 +171,7 @@ public struct CropImageView: View { struct CropImageView_Previews: PreviewProvider { struct PreviewView: View { + @State private var initialImageSize: CGSize = .init(width: 200, height: 200) @State private var targetSize: CGSize = .init(width: 100, height: 100) @State private var result: Result? = nil @@ -170,9 +179,17 @@ struct CropImageView_Previews: PreviewProvider { VStack { CropImageView( image: .init(contentsOfFile: "/Users/laosb/Downloads/png.png")!, + initialImageSize: initialImageSize, targetSize: targetSize ) { result = $0 } Form { + Section { + TextField("Width", value: $initialImageSize.width, formatter: NumberFormatter()) + TextField("Height", value: $initialImageSize.height, formatter: NumberFormatter()) + } header: { + Text("Initial Image Size") + Text("The image will be fitted into this region.") + } Section { TextField("Width", value: $targetSize.width, formatter: NumberFormatter()) TextField("Height", value: $targetSize.height, formatter: NumberFormatter()) @@ -205,7 +222,8 @@ struct CropImageView_Previews: PreviewProvider { static var previews: some View { PreviewView() #if os(macOS) - .frame(minHeight: 750) + .frame(width: 500) + .frame(minHeight: 770) #endif } } diff --git a/Sources/CropImage/UnderlyingImageView.swift b/Sources/CropImage/UnderlyingImageView.swift index 1d30b96..4d0a4be 100644 --- a/Sources/CropImage/UnderlyingImageView.swift +++ b/Sources/CropImage/UnderlyingImageView.swift @@ -18,6 +18,7 @@ struct UnderlyingImageView: View { @Binding var scale: CGFloat @Binding var rotation: Angle var image: PlatformImage + var initialImageSize: CGSize @State private var tempOffset: CGSize = .zero @State private var tempScale: CGFloat = 1 @@ -34,6 +35,10 @@ struct UnderlyingImageView: View { var body: some View { ZStack { imageView + .resizable() + .scaledToFit() + .frame(width: initialImageSize.width, height: initialImageSize.height) + .animation(.default, value: initialImageSize) .scaleEffect(scale * tempScale) .offset(offset + tempOffset) .rotationEffect(rotation + tempRotation) @@ -54,7 +59,7 @@ struct UnderlyingImageView: View { tempScale = value } .onEnded { value in - scale = scale * tempScale + scale = max(scale * tempScale, 0.01) tempScale = 1 } ) @@ -83,7 +88,8 @@ struct MoveAndScalableImageView_Previews: PreviewProvider { offset: $offset, scale: $scale, rotation: $rotation, - image: .init(contentsOfFile: "/Users/laosb/Downloads/png.png")! + image: .init(contentsOfFile: "/Users/laosb/Downloads/png.png")!, + initialImageSize: .init(width: 200, height: 200) ) } }