123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- //
- // CropViewController.swift
- // CropViewController
- //
- // Created by Guilherme Moura on 2/25/16.
- // Copyright © 2016 Reefactor, Inc. All rights reserved.
- // Credit https://github.com/sprint84/PhotoCropEditor
- import UIKit
- public protocol CropViewControllerDelegate: class {
- func cropViewController(_ controller: CropViewController, didFinishCroppingImage image: UIImage, transform: CGAffineTransform, cropRect: CGRect)
- func cropViewControllerDidCancel(_ controller: CropViewController)
- }
- open class CropViewController: UIViewController {
- open weak var delegate: CropViewControllerDelegate?
- open var image: UIImage? {
- didSet {
- cropView?.image = image
- }
- }
- open var keepAspectRatio = false {
- didSet {
- cropView?.keepAspectRatio = keepAspectRatio
- }
- }
- open var cropAspectRatio: CGFloat = 0.0 {
- didSet {
- cropView?.cropAspectRatio = cropAspectRatio
- }
- }
- open var cropRect = CGRect.zero {
- didSet {
- adjustCropRect()
- }
- }
- open var imageCropRect = CGRect.zero {
- didSet {
- cropView?.imageCropRect = imageCropRect
- }
- }
- open var toolbarHidden = false
- open var rotationEnabled = false {
- didSet {
- cropView?.rotationGestureRecognizer.isEnabled = rotationEnabled
- }
- }
- open var rotationTransform: CGAffineTransform {
- return cropView!.rotation
- }
- open var zoomedCropRect: CGRect {
- return cropView!.zoomedCropRect()
- }
- fileprivate var cropView: CropView?
-
- public required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- initialize()
- }
-
- public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
- super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
- initialize()
- }
-
- fileprivate func initialize() {
- rotationEnabled = true
- }
-
- open override func loadView() {
- let contentView = UIView()
- contentView.autoresizingMask = .flexibleWidth
- contentView.backgroundColor = UIColor.black
- view = contentView
-
- // Add CropView
- cropView = CropView(frame: contentView.bounds)
- contentView.addSubview(cropView!)
-
- }
- open override func viewDidLoad() {
- super.viewDidLoad()
- navigationController?.navigationBar.isTranslucent = false
- navigationController?.toolbar.isTranslucent = false
- navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(CropViewController.cancel(_:)))
- navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(CropViewController.done(_:)))
-
- if self.toolbarItems == nil {
- let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
- let constrainButton = UIBarButtonItem(title: "Constrain", style: .plain, target: self, action: #selector(CropViewController.constrain(_:)))
- toolbarItems = [flexibleSpace, constrainButton, flexibleSpace]
- }
-
- navigationController?.isToolbarHidden = toolbarHidden
-
- cropView?.image = image
- cropView?.rotationGestureRecognizer.isEnabled = rotationEnabled
- }
-
- open override func viewDidAppear(_ animated: Bool) {
- super.viewDidAppear(animated)
-
- if cropAspectRatio != 0 {
- cropView?.cropAspectRatio = cropAspectRatio
- }
-
- if !cropRect.equalTo(CGRect.zero) {
- adjustCropRect()
- }
-
- if !imageCropRect.equalTo(CGRect.zero) {
- cropView?.imageCropRect = imageCropRect
- }
-
- cropView?.keepAspectRatio = keepAspectRatio
- }
-
- open func resetCropRect() {
- cropView?.resetCropRect()
- }
-
- open func resetCropRectAnimated(_ animated: Bool) {
- cropView?.resetCropRectAnimated(animated)
- }
-
- @objc func cancel(_ sender: UIBarButtonItem) {
- delegate?.cropViewControllerDidCancel(self)
- }
-
- @objc func done(_ sender: UIBarButtonItem) {
- if let image = cropView?.croppedImage {
- guard let rotation = cropView?.rotation else {
- return
- }
- guard let rect = cropView?.zoomedCropRect() else {
- return
- }
- delegate?.cropViewController(self, didFinishCroppingImage: image, transform: rotation, cropRect: rect)
- }
- }
-
- @objc func constrain(_ sender: UIBarButtonItem) {
- let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
- let original = UIAlertAction(title: "Original", style: .default) { [unowned self] action in
- guard let image = self.cropView?.image else {
- return
- }
- guard var cropRect = self.cropView?.cropRect else {
- return
- }
- let width = image.size.width
- let height = image.size.height
- let ratio: CGFloat
- if width < height {
- ratio = width / height
- cropRect.size = CGSize(width: cropRect.height * ratio, height: cropRect.height)
- } else {
- ratio = height / width
- cropRect.size = CGSize(width: cropRect.width, height: cropRect.width * ratio)
- }
- self.cropView?.cropRect = cropRect
- }
- actionSheet.addAction(original)
- let square = UIAlertAction(title: "Square", style: .default) { [unowned self] action in
- let ratio: CGFloat = 1.0
- // self.cropView?.cropAspectRatio = ratio
- if var cropRect = self.cropView?.cropRect {
- let width = cropRect.width
- cropRect.size = CGSize(width: width, height: width * ratio)
- self.cropView?.cropRect = cropRect
- }
- }
- actionSheet.addAction(square)
- let threeByTwo = UIAlertAction(title: "3 x 2", style: .default) { [unowned self] action in
- self.cropView?.cropAspectRatio = 2.0 / 3.0
- }
- actionSheet.addAction(threeByTwo)
- let threeByFive = UIAlertAction(title: "3 x 5", style: .default) { [unowned self] action in
- self.cropView?.cropAspectRatio = 3.0 / 5.0
- }
- actionSheet.addAction(threeByFive)
- let fourByThree = UIAlertAction(title: "4 x 3", style: .default) { [unowned self] action in
- let ratio: CGFloat = 3.0 / 4.0
- if var cropRect = self.cropView?.cropRect {
- let width = cropRect.width
- cropRect.size = CGSize(width: width, height: width * ratio)
- self.cropView?.cropRect = cropRect
- }
- }
- actionSheet.addAction(fourByThree)
- let fourBySix = UIAlertAction(title: "4 x 6", style: .default) { [unowned self] action in
- self.cropView?.cropAspectRatio = 4.0 / 6.0
- }
- actionSheet.addAction(fourBySix)
- let fiveBySeven = UIAlertAction(title: "5 x 7", style: .default) { [unowned self] action in
- self.cropView?.cropAspectRatio = 5.0 / 7.0
- }
- actionSheet.addAction(fiveBySeven)
- let eightByTen = UIAlertAction(title: "8 x 10", style: .default) { [unowned self] action in
- self.cropView?.cropAspectRatio = 8.0 / 10.0
- }
- actionSheet.addAction(eightByTen)
- let widescreen = UIAlertAction(title: "16 x 9", style: .default) { [unowned self] action in
- let ratio: CGFloat = 9.0 / 16.0
- if var cropRect = self.cropView?.cropRect {
- let width = cropRect.width
- cropRect.size = CGSize(width: width, height: width * ratio)
- self.cropView?.cropRect = cropRect
- }
- }
- actionSheet.addAction(widescreen)
- let cancel = UIAlertAction(title: "Cancel", style: .default) { [unowned self] action in
- self.dismiss(animated: true, completion: nil)
- }
- actionSheet.addAction(cancel)
-
- if let popoverController = actionSheet.popoverPresentationController {
- popoverController.barButtonItem = sender
- }
-
- present(actionSheet, animated: true, completion: nil)
- }
- // MARK: - Private methods
- fileprivate func adjustCropRect() {
- imageCropRect = CGRect.zero
-
- guard var cropViewCropRect = cropView?.cropRect else {
- return
- }
- cropViewCropRect.origin.x += cropRect.origin.x
- cropViewCropRect.origin.y += cropRect.origin.y
-
- let minWidth = min(cropViewCropRect.maxX - cropViewCropRect.minX, cropRect.width)
- let minHeight = min(cropViewCropRect.maxY - cropViewCropRect.minY, cropRect.height)
- let size = CGSize(width: minWidth, height: minHeight)
- cropViewCropRect.size = size
- cropView?.cropRect = cropViewCropRect
- }
-
-
- }
|