diff --git a/Example/EmbeddedCropViewController.swift b/Example/EmbeddedCropViewController.swift index c8e253da..2cf6fb64 100644 --- a/Example/EmbeddedCropViewController.swift +++ b/Example/EmbeddedCropViewController.swift @@ -68,7 +68,7 @@ class EmbeddedCropViewController: UIViewController { return } - cropViewController?.update(image.addFilter(filter: .Mono)) + cropViewController?.update(image.addFilter(filter: .mono)) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { @@ -185,28 +185,28 @@ extension EmbeddedCropViewController: CropViewControllerDelegate { } } -enum FilterType : String { - case Chrome = "CIPhotoEffectChrome" - case Fade = "CIPhotoEffectFade" - case Instant = "CIPhotoEffectInstant" - case Mono = "CIPhotoEffectMono" - case Noir = "CIPhotoEffectNoir" - case Process = "CIPhotoEffectProcess" - case Tonal = "CIPhotoEffectTonal" - case Transfer = "CIPhotoEffectTransfer" +enum FilterType: String { + case chrome = "CIPhotoEffectChrome" + case fade = "CIPhotoEffectFade" + case instant = "CIPhotoEffectInstant" + case mono = "CIPhotoEffectMono" + case noir = "CIPhotoEffectNoir" + case process = "CIPhotoEffectProcess" + case tonal = "CIPhotoEffectTonal" + case transfer = "CIPhotoEffectTransfer" } extension UIImage { - func addFilter(filter : FilterType) -> UIImage { + func addFilter(filter: FilterType) -> UIImage { let filter = CIFilter(name: filter.rawValue) - // convert UIImage to CIImage and set as input + // Convert UIImage to CIImage and set as input let ciInput = CIImage(image: self) filter?.setValue(ciInput, forKey: "inputImage") - // get output CIImage, render as CGImage first to retain proper UIImage scale + // Get output CIImage, render as CGImage first to retain proper UIImage scale let ciOutput = filter?.outputImage let ciContext = CIContext() let cgImage = ciContext.createCGImage(ciOutput!, from: (ciOutput?.extent)!) - //Return the image + // Return the image return UIImage(cgImage: cgImage!) } } diff --git a/Example/zh-Hans.lproj/Main.storyboard b/Example/zh-Hans.lproj/Main.storyboard index 13dc7967..fcf35d2b 100644 --- a/Example/zh-Hans.lproj/Main.storyboard +++ b/Example/zh-Hans.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -181,21 +181,6 @@ - - - - - - - - - - - - - - - diff --git a/Mantis.xcodeproj/project.pbxproj b/Mantis.xcodeproj/project.pbxproj index 6a3f234c..688a7a27 100644 --- a/Mantis.xcodeproj/project.pbxproj +++ b/Mantis.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ F24DCFE829AB0A7000D8E8C1 /* CropAuxiliaryIndicatorViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24DCFE729AB0A7000D8E8C1 /* CropAuxiliaryIndicatorViewTests.swift */; }; F24DCFEC29AF2A6000D8E8C1 /* CropAuxiliaryIndicatorView+Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24DCFEB29AF2A6000D8E8C1 /* CropAuxiliaryIndicatorView+Accessibility.swift */; }; F251B36E299B9A52006325B0 /* CropWorkbenchViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F251B36D299B9A52006325B0 /* CropWorkbenchViewTests.swift */; }; + F28FF64A2C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = F28FF6492C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift */; }; F2AD53412A46DB8B00AE9C87 /* ImageAutoAdjustHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2AD53402A46DB8B00AE9C87 /* ImageAutoAdjustHelper.swift */; }; F2B4FDA42A3B661B00667F22 /* SlideDial.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2B4FDA32A3B661B00667F22 /* SlideDial.swift */; }; F2B4FDA72A3B69B600667F22 /* SlideRulerPositionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2B4FDA52A3B69B600667F22 /* SlideRulerPositionHelper.swift */; }; @@ -211,6 +212,7 @@ F24DCFE729AB0A7000D8E8C1 /* CropAuxiliaryIndicatorViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CropAuxiliaryIndicatorViewTests.swift; sourceTree = ""; }; F24DCFEB29AF2A6000D8E8C1 /* CropAuxiliaryIndicatorView+Accessibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CropAuxiliaryIndicatorView+Accessibility.swift"; sourceTree = ""; }; F251B36D299B9A52006325B0 /* CropWorkbenchViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CropWorkbenchViewTests.swift; sourceTree = ""; }; + F28FF6492C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CropAuxiliaryIndicatorConfig.swift; sourceTree = ""; }; F2AD53402A46DB8B00AE9C87 /* ImageAutoAdjustHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageAutoAdjustHelper.swift; sourceTree = ""; }; F2B4FDA32A3B661B00667F22 /* SlideDial.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlideDial.swift; sourceTree = ""; }; F2B4FDA52A3B69B600667F22 /* SlideRulerPositionHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlideRulerPositionHelper.swift; sourceTree = ""; }; @@ -507,6 +509,7 @@ OBJ_36 /* Mantis.swift */, 6659429C2877DAE80096A5DB /* Config.swift */, 663FCF3728866DDA003D3B9E /* CropViewConfig.swift */, + F28FF6492C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift */, 663FCF3828866DDA003D3B9E /* CropToolbarConfig.swift */, 6659429E2877DC8A0096A5DB /* Enum.swift */, 665942A02877DD1C0096A5DB /* CropData.swift */, @@ -795,6 +798,7 @@ FEDAAD8625205CC300D95667 /* RatioSelector.swift in Sources */, OBJ_93 /* CropVisualEffectView.swift in Sources */, 269AF94227437EE400F7FAF6 /* RotationDialConfig.swift in Sources */, + F28FF64A2C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift in Sources */, OBJ_94 /* RatioOptions.swift in Sources */, OBJ_95 /* Angle.swift in Sources */, OBJ_97 /* RotationCalculator.swift in Sources */, diff --git a/Sources/Mantis/CropAuxiliaryIndicatorConfig.swift b/Sources/Mantis/CropAuxiliaryIndicatorConfig.swift new file mode 100644 index 00000000..f42ce3a3 --- /dev/null +++ b/Sources/Mantis/CropAuxiliaryIndicatorConfig.swift @@ -0,0 +1,41 @@ +// +// CropAuxiliaryIndicatorConfig.swift +// Mantis +// +// Created by Yingtao Guo on 7/19/24. +// + +import UIKit + +public struct CropAuxiliaryIndicatorConfig { + /** + This value is for how easy to drag crop box. The bigger, the easier. + */ + public var cropBoxHotAreaUnit: CGFloat = 32 { + didSet { + assert(cropBoxHotAreaUnit > 0) + } + } + + public var disableCropBoxDeformation = false + public var style: CropAuxiliaryIndicatorStyleType = .normal + + public var borderNormalColor = UIColor.white + + /** + The color of the border when showing which border is touched currently. + */ + public var borderHintColor = UIColor.white + + public var cornerHandleColor = UIColor.white + public var edgeLineHandleColor = UIColor.white + + public var gridMainColor = UIColor.white + + /** + This property is only used when rotating the image + */ + public var gridSecondaryColor = UIColor.lightGray + + public init() {} +} diff --git a/Sources/Mantis/CropView/CropAuxiliaryIndicatorView.swift b/Sources/Mantis/CropView/CropAuxiliaryIndicatorView.swift index c9aa06aa..2b7e12f4 100644 --- a/Sources/Mantis/CropView/CropAuxiliaryIndicatorView.swift +++ b/Sources/Mantis/CropView/CropAuxiliaryIndicatorView.swift @@ -9,8 +9,10 @@ import UIKit final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol { - private var boarderNormalColor = UIColor.white - private var boarderHintColor = UIColor.white + private var borderNormalColor = UIColor.white + private var borderHintColor = UIColor.white + private var cornerHandleColor = UIColor.white + private var edgeLineHandleColor = UIColor.white private let cornerHandleLength = CGFloat(20.0) private let edgeLineHandleLength = CGFloat(30.0) private let handleThickness = CGFloat(3.0) @@ -49,16 +51,22 @@ final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtoc } } - init(frame: CGRect, - cropBoxHotAreaUnit: CGFloat, - disableCropBoxDeformation: Bool = false, - style: CropAuxiliaryIndicatorStyleType = .normal) { + init(frame: CGRect, config: CropAuxiliaryIndicatorConfig = CropAuxiliaryIndicatorConfig()) { super.init(frame: frame) clipsToBounds = false backgroundColor = .clear - self.cropBoxHotAreaUnit = cropBoxHotAreaUnit - self.disableCropBoxDeformation = disableCropBoxDeformation - self.style = style + + cropBoxHotAreaUnit = config.cropBoxHotAreaUnit + disableCropBoxDeformation = config.disableCropBoxDeformation + style = config.style + + borderNormalColor = config.borderNormalColor + borderHintColor = config.borderHintColor + cornerHandleColor = config.cornerHandleColor + edgeLineHandleColor = config.edgeLineHandleColor + gridMainColor = config.gridMainColor + gridSecondaryColor = config.gridSecondaryColor + setup() } @@ -67,15 +75,18 @@ final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtoc backgroundColor = .clear } - private func createNewLine() -> UIView { + private func createNewLine(withNormalColor normalColor: UIColor = .white) -> UIView { let view = UIView() view.frame = .zero + if style == .normal { - view.backgroundColor = .white + view.backgroundColor = normalColor } else { view.backgroundColor = .clear } + addSubview(view) + return view } @@ -85,19 +96,19 @@ final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtoc borderLine.layer.borderWidth = borderThickness if style == .normal { - borderLine.layer.borderColor = boarderNormalColor.cgColor - hintLine.backgroundColor = boarderHintColor + borderLine.layer.borderColor = borderNormalColor.cgColor + hintLine.backgroundColor = borderHintColor } else { borderLine.layer.borderColor = UIColor.clear.cgColor hintLine.backgroundColor = .clear } for _ in 0..<8 { - cornerHandles.append(createNewLine()) + cornerHandles.append(createNewLine(withNormalColor: cornerHandleColor)) } for _ in 0..<4 { - edgeLineHandles.append(createNewLine()) + edgeLineHandles.append(createNewLine(withNormalColor: edgeLineHandleColor)) } setupAccessibilityHelperViews() @@ -177,7 +188,7 @@ final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtoc borderLine.layer.backgroundColor = UIColor.clear.cgColor borderLine.layer.borderWidth = borderThickness if style == .normal { - borderLine.layer.borderColor = boarderNormalColor.cgColor + borderLine.layer.borderColor = borderNormalColor.cgColor } else { borderLine.layer.borderColor = UIColor.clear.cgColor } diff --git a/Sources/Mantis/CropView/CropView+Touches.swift b/Sources/Mantis/CropView/CropView+Touches.swift index 9f26d5e1..e1c3db68 100644 --- a/Sources/Mantis/CropView/CropView+Touches.swift +++ b/Sources/Mantis/CropView/CropView+Touches.swift @@ -17,7 +17,7 @@ extension CropView { return rotationControlView.getTouchTarget(with: pointInRotationControlView) } - if !cropViewConfig.disableCropBoxDeformation && isHitGridOverlayView(by: newPoint) { + if !cropViewConfig.cropAuxiliaryIndicatorConfig.disableCropBoxDeformation && isHitGridOverlayView(by: newPoint) { return self } @@ -29,7 +29,7 @@ extension CropView { } private func isHitGridOverlayView(by touchPoint: CGPoint) -> Bool { - let hotAreaUnit = cropViewConfig.cropBoxHotAreaUnit + let hotAreaUnit = cropViewConfig.cropAuxiliaryIndicatorConfig.cropBoxHotAreaUnit return cropAuxiliaryIndicatorView.frame.insetBy(dx: -hotAreaUnit/2, dy: -hotAreaUnit/2).contains(touchPoint) && !cropAuxiliaryIndicatorView.frame.insetBy(dx: hotAreaUnit/2, dy: hotAreaUnit/2).contains(touchPoint) diff --git a/Sources/Mantis/CropView/CropView+UIScrollViewDelegate.swift b/Sources/Mantis/CropView/CropView+UIScrollViewDelegate.swift index e932c64b..99d8c88a 100644 --- a/Sources/Mantis/CropView/CropView+UIScrollViewDelegate.swift +++ b/Sources/Mantis/CropView/CropView+UIScrollViewDelegate.swift @@ -25,7 +25,7 @@ extension CropView: UIScrollViewDelegate { } func scrollViewDidZoom(_ scrollView: UIScrollView) { - guard scrollView.subviews.count > 0 else { + guard !scrollView.subviews.isEmpty else { return } @@ -34,7 +34,7 @@ extension CropView: UIScrollViewDelegate { let offsetX: CGFloat = max((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0) let offsetY: CGFloat = max((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0) - subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, scrollView.contentSize.height * 0.5 + offsetY) + subView.center = CGPoint(x: scrollView.contentSize.width * 0.5 + offsetX, y: scrollView.contentSize.height * 0.5 + offsetY) } func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { diff --git a/Sources/Mantis/CropViewConfig.swift b/Sources/Mantis/CropViewConfig.swift index 464d8a10..9622ecae 100644 --- a/Sources/Mantis/CropViewConfig.swift +++ b/Sources/Mantis/CropViewConfig.swift @@ -4,12 +4,38 @@ public struct CropViewConfig { /** This value is for how easy to drag crop box. The bigger, the easier. */ - public var cropBoxHotAreaUnit: CGFloat = 32 { - didSet { - assert(cropBoxHotAreaUnit > 0) + @available(*, deprecated, message: "Use cropAuxiliaryIndicatorStyle.cropBoxHotAreaUnit instead") + public var cropBoxHotAreaUnit: CGFloat { + get { + cropAuxiliaryIndicatorConfig.cropBoxHotAreaUnit + } + set { + cropAuxiliaryIndicatorConfig.cropBoxHotAreaUnit = newValue + } + } + + @available(*, deprecated, message: "Use cropAuxiliaryIndicatorStyle.disableCropBoxDeformation instead") + public var disableCropBoxDeformation: Bool { + get { + cropAuxiliaryIndicatorConfig.disableCropBoxDeformation + } + set { + cropAuxiliaryIndicatorConfig.disableCropBoxDeformation = newValue + } + } + + @available(*, deprecated, message: "Use cropAuxiliaryIndicatorConfig.style instead") + public var cropAuxiliaryIndicatorStyle: CropAuxiliaryIndicatorStyleType { + get { + cropAuxiliaryIndicatorConfig.style + } + set { + cropAuxiliaryIndicatorConfig.style = newValue } } + public var cropAuxiliaryIndicatorConfig = CropAuxiliaryIndicatorConfig() + public var cropShapeType: CropShapeType = .rect public var cropBorderWidth: CGFloat = 0 { @@ -31,8 +57,6 @@ public struct CropViewConfig { public var cropMaskVisualEffectType: CropMaskVisualEffectType = .blurDark - public var cropAuxiliaryIndicatorStyle: CropAuxiliaryIndicatorStyleType = .normal - public var presetTransformationType: PresetTransformationType = .none public var minimumZoomScale: CGFloat = 1 { @@ -66,9 +90,11 @@ public struct CropViewConfig { public var rotateCropBoxFor90DegreeRotation = true - var minimumCropBoxSize: CGFloat = 42 - - public var disableCropBoxDeformation = false + public var minimumCropBoxSize: CGFloat = 42 { + didSet { + assert(minimumCropBoxSize >= 4) + } + } public enum BuiltInRotationControlViewType { case rotationDial(config: RotationDialConfig = .init()) diff --git a/Sources/Mantis/Mantis.swift b/Sources/Mantis/Mantis.swift index 26062944..cbf0b923 100644 --- a/Sources/Mantis/Mantis.swift +++ b/Sources/Mantis/Mantis.swift @@ -97,9 +97,7 @@ private func buildCropView(withImage image: UIImage, config cropViewConfig: CropViewConfig, rotationControlView: RotationControlViewProtocol?) -> CropViewProtocol { let cropAuxiliaryIndicatorView = CropAuxiliaryIndicatorView(frame: .zero, - cropBoxHotAreaUnit: cropViewConfig.cropBoxHotAreaUnit, - disableCropBoxDeformation: cropViewConfig.disableCropBoxDeformation, - style: cropViewConfig.cropAuxiliaryIndicatorStyle) + config: cropViewConfig.cropAuxiliaryIndicatorConfig) let imageContainer = ImageContainer(image: image) let cropView = CropView(image: image, cropViewConfig: cropViewConfig, @@ -116,7 +114,7 @@ private func buildCropView(withImage image: UIImage, private func buildCropViewModel(with cropViewConfig: CropViewConfig) -> CropViewModelProtocol { CropViewModel( cropViewPadding: cropViewConfig.padding, - hotAreaUnit: cropViewConfig.cropBoxHotAreaUnit + hotAreaUnit: cropViewConfig.cropAuxiliaryIndicatorConfig.cropBoxHotAreaUnit ) } diff --git a/Sources/Mantis/MaskBackground/CropMaskProtocal.swift b/Sources/Mantis/MaskBackground/CropMaskProtocal.swift index bd200308..f03dc7b5 100644 --- a/Sources/Mantis/MaskBackground/CropMaskProtocal.swift +++ b/Sources/Mantis/MaskBackground/CropMaskProtocal.swift @@ -8,7 +8,7 @@ import UIKit -private let minOverLayerUnit: CGFloat = 30 +private let minOverLayerUnit: CGFloat = 4 private let initialFrameLength: CGFloat = 1000 protocol CropMaskProtocol: UIView {