feat: Initial image size.

This commit is contained in:
Shibo Lyu 2023-08-10 17:20:38 +08:00
parent b42b532ddb
commit edc6a5c17b
2 changed files with 29 additions and 5 deletions

View file

@ -37,6 +37,8 @@ public struct CropImageView<Controls: View>: View {
/// The image to crop. /// The image to crop.
public var image: PlatformImage 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. /// The intended size of the cropped image, in points.
public var targetSize: CGSize public var targetSize: CGSize
/// The intended scale of the cropped image. /// The intended scale of the cropped image.
@ -56,12 +58,14 @@ public struct CropImageView<Controls: View>: View {
/// Create a ``CropImageView`` with a custom ``controls`` view. /// Create a ``CropImageView`` with a custom ``controls`` view.
public init( public init(
image: PlatformImage, image: PlatformImage,
initialImageSize: CGSize,
targetSize: CGSize, targetSize: CGSize,
targetScale: CGFloat = 1, targetScale: CGFloat = 1,
onCrop: @escaping (Result<PlatformImage, Error>) -> Void, onCrop: @escaping (Result<PlatformImage, Error>) -> Void,
@ViewBuilder controls: @escaping ControlClosure<Controls> @ViewBuilder controls: @escaping ControlClosure<Controls>
) { ) {
self.image = image self.image = image
self.initialImageSize = initialImageSize
self.targetSize = targetSize self.targetSize = targetSize
self.targetScale = targetScale self.targetScale = targetScale
self.onCrop = onCrop self.onCrop = onCrop
@ -72,11 +76,13 @@ public struct CropImageView<Controls: View>: View {
/// The default ``controls`` view is a simple overlay with a checkmark icon on the bottom-trailing corner to trigger crop action. /// The default ``controls`` view is a simple overlay with a checkmark icon on the bottom-trailing corner to trigger crop action.
public init( public init(
image: PlatformImage, image: PlatformImage,
initialImageSize: CGSize,
targetSize: CGSize, targetSize: CGSize,
targetScale: CGFloat = 1, targetScale: CGFloat = 1,
onCrop: @escaping (Result<PlatformImage, Error>) -> Void onCrop: @escaping (Result<PlatformImage, Error>) -> Void
) where Controls == DefaultControlsView { ) where Controls == DefaultControlsView {
self.image = image self.image = image
self.initialImageSize = initialImageSize
self.targetSize = targetSize self.targetSize = targetSize
self.targetScale = targetScale self.targetScale = targetScale
self.onCrop = onCrop self.onCrop = onCrop
@ -95,7 +101,8 @@ public struct CropImageView<Controls: View>: View {
offset: $offset, offset: $offset,
scale: $scale, scale: $scale,
rotation: $rotation, rotation: $rotation,
image: image image: image,
initialImageSize: initialImageSize
) )
.frame(width: targetSize.width, height: targetSize.height) .frame(width: targetSize.width, height: targetSize.height)
if #available(iOS 16.0, macOS 13.0, *) { if #available(iOS 16.0, macOS 13.0, *) {
@ -143,7 +150,8 @@ public struct CropImageView<Controls: View>: View {
offset: $offset, offset: $offset,
scale: $scale, scale: $scale,
rotation: $rotation, rotation: $rotation,
image: image image: image,
initialImageSize: initialImageSize
) )
RectHoleShape(size: targetSize) RectHoleShape(size: targetSize)
.fill(style: FillStyle(eoFill: true)) .fill(style: FillStyle(eoFill: true))
@ -163,6 +171,7 @@ public struct CropImageView<Controls: View>: View {
struct CropImageView_Previews: PreviewProvider { struct CropImageView_Previews: PreviewProvider {
struct PreviewView: View { 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 targetSize: CGSize = .init(width: 100, height: 100)
@State private var result: Result<PlatformImage, Error>? = nil @State private var result: Result<PlatformImage, Error>? = nil
@ -170,9 +179,17 @@ struct CropImageView_Previews: PreviewProvider {
VStack { VStack {
CropImageView( CropImageView(
image: .init(contentsOfFile: "/Users/laosb/Downloads/png.png")!, image: .init(contentsOfFile: "/Users/laosb/Downloads/png.png")!,
initialImageSize: initialImageSize,
targetSize: targetSize targetSize: targetSize
) { result = $0 } ) { result = $0 }
Form { 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 { Section {
TextField("Width", value: $targetSize.width, formatter: NumberFormatter()) TextField("Width", value: $targetSize.width, formatter: NumberFormatter())
TextField("Height", value: $targetSize.height, formatter: NumberFormatter()) TextField("Height", value: $targetSize.height, formatter: NumberFormatter())
@ -205,7 +222,8 @@ struct CropImageView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
PreviewView() PreviewView()
#if os(macOS) #if os(macOS)
.frame(minHeight: 750) .frame(width: 500)
.frame(minHeight: 770)
#endif #endif
} }
} }

View file

@ -18,6 +18,7 @@ struct UnderlyingImageView: View {
@Binding var scale: CGFloat @Binding var scale: CGFloat
@Binding var rotation: Angle @Binding var rotation: Angle
var image: PlatformImage var image: PlatformImage
var initialImageSize: CGSize
@State private var tempOffset: CGSize = .zero @State private var tempOffset: CGSize = .zero
@State private var tempScale: CGFloat = 1 @State private var tempScale: CGFloat = 1
@ -34,6 +35,10 @@ struct UnderlyingImageView: View {
var body: some View { var body: some View {
ZStack { ZStack {
imageView imageView
.resizable()
.scaledToFit()
.frame(width: initialImageSize.width, height: initialImageSize.height)
.animation(.default, value: initialImageSize)
.scaleEffect(scale * tempScale) .scaleEffect(scale * tempScale)
.offset(offset + tempOffset) .offset(offset + tempOffset)
.rotationEffect(rotation + tempRotation) .rotationEffect(rotation + tempRotation)
@ -54,7 +59,7 @@ struct UnderlyingImageView: View {
tempScale = value tempScale = value
} }
.onEnded { value in .onEnded { value in
scale = scale * tempScale scale = max(scale * tempScale, 0.01)
tempScale = 1 tempScale = 1
} }
) )
@ -83,7 +88,8 @@ struct MoveAndScalableImageView_Previews: PreviewProvider {
offset: $offset, offset: $offset,
scale: $scale, scale: $scale,
rotation: $rotation, rotation: $rotation,
image: .init(contentsOfFile: "/Users/laosb/Downloads/png.png")! image: .init(contentsOfFile: "/Users/laosb/Downloads/png.png")!,
initialImageSize: .init(width: 200, height: 200)
) )
} }
} }