• Crop area enumeration, marking the crop location tag value
fileprivate enum CropPosition: Int { case leftTop = 100 case rightTop = 101 case leftBottom = 102 case rightBottom = 103 case top = 104 case left = 105  case bottom = 106 case right = 107 }Copy the code
Fileprivate let minCropWith = 100.0 fileprivate let minCropHeight = 100.0 fileprivate lazy var TargetImageView: UIImageView = {let imageView = UIImageView (frame: CGRect (10.0 x: y: 80.0, width: Screenwith-20.0, height: 400.0)) let path = bundle.main. path(forResource: "[email protected]", ofType: nil) ?? "" guard let image = UIImage(contentsOfFile: Path) else {fatalError(" Image not found ")} imageView.image = image imageView.contentMode =.scaletofill imageView.isUserInteractionEnabled = true return imageView }()Copy the code
  • Clipping area View
    // 裁剪区域view
    fileprivate lazy var cropView:UIView = {
        let frame = CGRect(x: 0.0, y: 0.0, width: minCropWith, height: minCropHeight)
        let view = UIView(frame: frame)
        //        view.backgroundColor = .orange
        view.isUserInteractionEnabled = true
        let panGestureRec = UIPanGestureRecognizer(target: self, action: #selector(translation(pan:)))
        view.addGestureRecognizer(panGestureRec)
        
        let leftTopImage = UIImageView(image: UIImage(named: "corner_left_top"))
        leftTopImage.frame = CGRect(x: 0.0, y: 0.0, width: 20.0, height: 20.0)
        leftTopImage.autoresizingMask = [.flexibleBottomMargin,.flexibleRightMargin]
        leftTopImage.tag = CropPosition.leftTop.rawValue
        leftTopImage.isUserInteractionEnabled = true
        leftTopImage.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(moveAction(pan:))))
        view.addSubview(leftTopImage)
        
        let rightTopImage = UIImageView(image: UIImage(named: "corner_right_top"))
        rightTopImage.frame = CGRect(x: frame.maxX-20, y: 0, width: 20, height: 20)
        rightTopImage.autoresizingMask = [.flexibleBottomMargin,.flexibleLeftMargin]
        rightTopImage.tag = CropPosition.rightTop.rawValue
        rightTopImage.isUserInteractionEnabled = true
        rightTopImage.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(moveAction(pan:))))
        view.addSubview(rightTopImage)
        
        let leftBottomImage = UIImageView(image: UIImage(named: "corner_left_bottom"))
        leftBottomImage.frame = CGRect(x: 0, y: frame.maxY-20, width: 20, height: 20)
        leftBottomImage.autoresizingMask = [.flexibleTopMargin,.flexibleRightMargin]
        leftBottomImage.tag = CropPosition.leftBottom.rawValue
        leftBottomImage.isUserInteractionEnabled = true
        leftBottomImage.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(moveAction(pan:))))
        view.addSubview(leftBottomImage)
        
        let rightBottomImage = UIImageView(image: UIImage(named: "corner_right_bottom"))
        rightBottomImage.frame = CGRect(x: frame.maxX-20, y: frame.maxY-20, width: 20, height: 20)
        rightBottomImage.autoresizingMask = [.flexibleTopMargin,.flexibleLeftMargin]
        rightBottomImage.tag = CropPosition.rightBottom.rawValue
        rightBottomImage.isUserInteractionEnabled = true
        rightBottomImage.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(moveAction(pan:))))
        view.addSubview(rightBottomImage)
        
        let topView = UIView(frame: CGRect(x: 20, y: 0, width: frame.width-20*2, height: 20))
        //        topView.backgroundColor = UIColor.green
        topView.tag = CropPosition.top.rawValue
        topView.autoresizingMask = [.flexibleWidth,.flexibleBottomMargin]
        topView.isUserInteractionEnabled = true
        topView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(moveAction(pan:))))
        view.addSubview(topView)
        
        let bottomView = UIView(frame: CGRect(x: 20, y: frame.height-20, width: frame.width-20*2, height: 20))
        //        bottomView.backgroundColor = UIColor.green
        bottomView.tag = CropPosition.bottom.rawValue
        bottomView.autoresizingMask = [.flexibleWidth,.flexibleTopMargin]
        bottomView.isUserInteractionEnabled = true
        bottomView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(moveAction(pan:))))
        view.addSubview(bottomView)
        
        let leftView = UIView(frame: CGRect(x: 0, y: 20, width: 20, height: frame.height-20*2))
        //        leftView.backgroundColor = UIColor.green
        leftView.tag = CropPosition.left.rawValue
        leftView.autoresizingMask = [.flexibleHeight,.flexibleRightMargin]
        leftView.isUserInteractionEnabled = true
        leftView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(moveAction(pan:))))
        view.addSubview(leftView)
        
        let rightView = UIView(frame: CGRect(x: frame.width-20, y: 20, width: 20, height: frame.height-20*2))
        //        rightView.backgroundColor = UIColor.green
        rightView.tag = CropPosition.right.rawValue
        rightView.autoresizingMask = [.flexibleHeight,.flexibleLeftMargin]
        rightView.isUserInteractionEnabled = true
        rightView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(moveAction(pan:))))
        view.addSubview(rightView)
        
        return view
    }()
Copy the code
Override func viewDidLoad () {super viewDidLoad () the self. The title = "image cutting" is the self. The backgroundColor =. White self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(cropAction)) self.view.addSubview(self.targetImageView) self.targetImageView.addSubview(self.cropView) cropView.center = targetImageView.center self.resetCropMask() }Copy the code
  • The mask layer
func resetCropMask() { let path = UIBezierPath(rect: targetImageView.bounds) let clearPath = UIBezierPath(rect: cropView.frame) path.append(clearPath) let layer = CAShapeLayer() layer.frame = targetImageView.bounds layer.fillColor =  UIColor(red: 0, green: 0, blue: 0, alpha: CgColor layer.strokecolor = uicolor.clear. CgColor layer.fillrule =.evenodd layer.path = path.cgPath for item in targetImageView.layer.sublayers ?? [] { if item is CAShapeLayer { item.removeFromSuperlayer() } } targetImageView.layer.addSublayer(layer) }Copy the code
  • tailoring
@objc func cropAction() {let frame = cropView.frame guard let image = targetimageView.image else {fatalError(" Image data is wrong ")  } let scale = image.size.width/ScreenWith guard let cropImage = image.cropping(to: CGRect(x: frame.origin.x*scale, y: frame.origin.y*scale, width: frame.width*scale, height: Frame. Height *scale) else {fatalError(" error ")} debugPrint(cropImage) PHPhotoLibrary.shared().performChanges { let result = PHAssetChangeRequest.creationRequestForAsset(from: cropImage) let assetPlaceholder = result.placeholderForCreatedAsset localID = assetPlaceholder?.localIdentifier ?? "" // Save save identifier} completionHandler: { (success, Error) in if success == true {debugPrint(" save successfully ") // Let assetResult = PHAsset.fetchAssets(withLocalIdentifiers: [localID], options: nil) let asset = assetResult.firstObject let options = PHContentEditingInputRequestOptions() options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) - > Bool in return true} / / access to save the image path asset?. RequestContentEditingInput (with: options, completionHandler: { (contentEditingInput, Info) in let uri = contentEditingInput?. FullSizeImageURL?. AbsoluteString?? "" debugPrint(" Saved image path = \(URI)")})} else \(String(describing: error?.localizedDescription))")}}}Copy the code
  • Move the entire clipping area
@objc func translation(pan:UIPanGestureRecognizer) { var point = pan.location(in: targetImageView) if point.x < 0 {point.x = 0} if point.x > targetImageView.frame.width {point.x = targetImageView.frame.width} if point.y < 0 {point.y = 0} if point.y > targetImageView.frame.height {point.y = TargetImageView. Frame. Height} if pan. State = =. Changed {var frame = cropView. Frame let minX: CGFloat = 0.0 let minY: CGFloat = 0.0 let maxX = targetImageView. Frame. The width - frame. Width let maxY = targetImageView. Frame. The height - frame. Height var x = point.x-frame.width/2 if x < minX { x = minX } if x > maxX { x = maxX } var y = point.y-frame.height/2 if y < minY { y = minY } if y > maxY { y = maxY } frame.origin.x = x frame.origin.y = y cropView.frame = frame resetCropMask() }}Copy the code
  • Jump clipped region border
@objc func moveAction(pan:UIPanGestureRecognizer) { guard let panView = pan.view else { return } var point = pan.location(in: targetImageView) if point.x < 0 {point.x = 0} if point.x > targetImageView.frame.width {point.x = targetImageView.frame.width} if point.y < 0 {point.y = 0} if point.y > targetImageView.frame.height {point.y = targetImageView.frame.height} if pan.state == .changed { if panView.tag == CropPosition.leftTop.rawValue { var frame = Cropview. frame let minX: CGFloat = 0.0 let minY: CGFloat = 0.0 let maxX = frame.maxx - CGFloat(minCropWith) let maxY = frame.maxy - CGFloat(minCropHeight) var x = point.x if x < minX { x = minX } if x > maxX { x = maxX } var y = point.y if y < minY { y = minY } if y > maxY { y = maxY } frame = CGRect(x: x, y: y, width: (frame.origin.x-x)+frame.width, height: (frame.origin.y-y)+frame.height) cropView.frame = frame resetCropMask() } else if panView.tag == CropPosition.left.rawValue { var frame = cropView.frame let minX: CGFloat = 0.0 let maxX = frame.maxx - CGFloat(minCropWith) var x = point.x if x < minX {x = minX} if x > maxX {x = maxX } frame = CGRect(x: x, y: frame.origin.y, width: (frame.origin.x-x)+frame.width, height: frame.height) cropView.frame = frame resetCropMask() } else if panView.tag == CropPosition.leftBottom.rawValue { var Frame = cropView.frame let minX: CGFloat = 0.0 let minY: CGFloat = frame.minY+CGFloat(minCropHeight) let maxX = frame.maxX-CGFloat(minCropWith) let maxY = targetImageView.frame.height var x = point.x if x < minX { x = minX } if x > maxX { x = maxX } var y = point.y if y < minY { y = minY } if y > maxY { y = maxY } frame = CGRect(x: x, y: frame.origin.y, width: (frame.origin.x-x)+frame.width, height: y-frame.origin.y) cropView.frame = frame resetCropMask() } else if panView.tag == CropPosition.top.rawValue { var frame = cropView.frame let minY: CGFloat = 0.0 let maxY = frame.maxy -CGFloat(minCropHeight) var y = point.y if y < minY {y = minY} if y > maxY {y = maxY } frame = CGRect(x: frame.origin.x, y: y, width: frame.width, height: (frame.origin.y-y)+frame.height) cropView.frame = frame resetCropMask() } else if panView.tag == CropPosition.rightTop.rawValue { var frame = cropView.frame let minX: CGFloat = frame.minX+CGFloat(minCropWith) let minY: CGFloat = 0.0 let maxX = targetImageView. Frame. Width let maxY. = frame maxY - CGFloat (minCropHeight) var x = point. If x x <  minX { x = minX } if x > maxX { x = maxX } var y = point.y if y < minY { y = minY } if y > maxY { y = maxY } frame = CGRect(x: frame.origin.x, y: y, width: x-frame.origin.x, height: (frame.origin.y-y)+frame.height) cropView.frame = frame resetCropMask() } else if panView.tag == CropPosition.right.rawValue { var frame = cropView.frame let minX: CGFloat = frame.minX+CGFloat(minCropWith) let maxX = targetImageView.frame.width var x = point.x if x < minX { x = minX } if x > maxX { x = maxX } frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: x-frame.origin.x, height: frame.height) cropView.frame = frame resetCropMask() } else if panView.tag == CropPosition.rightBottom.rawValue { var frame = cropView.frame let minX: CGFloat = frame.minX+CGFloat(minCropWith) let minY: CGFloat = frame.minY+CGFloat(minCropWith) let maxX = targetImageView.frame.width let maxY = targetImageView.frame.height  var x = point.x if x < minX { x = minX } if x > maxX { x = maxX } var y = point.y if y < minY { y = minY } if y > maxY { y = maxY } frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: x-frame.origin.x, height: y-frame.origin.y) cropView.frame = frame resetCropMask() } else if panView.tag == CropPosition.bottom.rawValue { var frame = cropView.frame let minY: CGFloat = frame.minY+CGFloat(minCropHeight) let maxY = targetImageView.frame.height var y = point.y if y < minY { y = minY } if y > maxY { y = maxY } frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.width, height: y-frame.origin.y) cropView.frame = frame resetCropMask() } } }Copy the code
  • UIImage Extension
Public puff (to rect: CGRect) -> UIImage? { guard self.size.width > rect.origin.x else { return nil } guard self.size.height > rect.origin.y else { return nil } let scaleRect = CGRect(x: rect.origin.x*self.scale, y: rect.origin.y*self.scale, width: rect.width*self.scale, height: rect.height*self.scale) if let cgImage = self.cgImage? .cropping(to: scaleRect) { let cropImage = UIImage(cgImage: cgImage, scale: self.scale, orientation: .up) return cropImage } else { return nil } } }Copy the code
  • Finger slide screenshot
/ / been cropped picture fileprivate lazy var targetImageView: UIImageView = {let imageView = UIImageView (frame: CGRect (10.0 x: y: 80.0, width: screenwith-20.0, height: 400.0)) let path = bundle.main. path(forResource: "[email protected]", ofType: nil) ?? "" guard let image = UIImage(contentsOfFile: Path) else {fatalError(" Image not found ")} imageView.image = image imageView.contentMode =.scaletofill imageView.isUserInteractionEnabled = true imageView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(crop(pan:)))) return imageView }()Copy the code
    lazy var startPoint = CGPoint(x: 0, y: 0)
    
    @objc func crop(pan:UIPanGestureRecognizer) {
        let point = pan.location(in: targetImageView)
        if pan.state == .began {
            startPoint = point
        } else if pan.state == .changed {
            let newOrigin = CGPoint(x: min(point.x, startPoint.x), y: min(point.y, startPoint.y))
            let newSize = CGSize(width: abs(point.x-startPoint.x), height: abs(point.y-startPoint.y))
            let frame = CGRect(origin: newOrigin, size: newSize)
            cropView.frame = frame
        } else if pan.state == .ended {
            let frame = cropView.frame
            if let image = targetImageView.image {
                let scale = image.size.width/ScreenWith
                let cropImage = image.cropping(to: CGRect(x: frame.origin.x*scale, y: frame.origin.y*scale, width: frame.width*scale, height: frame.height*scale))
                debugPrint(cropImage!)
            }
            
            cropView.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
        }
    }
Copy the code