- 裁剪区域枚举,标记裁剪位置tag值
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
}
复制代码
// 最小裁剪宽高
fileprivate let minCropWith = 100.0
fileprivate let minCropHeight = 100.0
// 被裁剪的图片
fileprivate lazy var targetImageView:UIImageView = {
let imageView = UIImageView(frame: CGRect(x: 10.0, y: 80.0, width: ScreenWith - 20.0, height: 400.0))
let path = Bundle.main.path(forResource: "cropImage@2x.jpg", ofType: nil) ?? ""
guard let image = UIImage(contentsOfFile: path) else {
fatalError("图片没有找到")
}
imageView.image = image
imageView.contentMode = .scaleToFill
imageView.isUserInteractionEnabled = true
return imageView
}()
复制代码
- 裁剪区域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
}()
复制代码
override func viewDidLoad() {
super.viewDidLoad()
self.title = "图片裁剪"
self.view.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()
}
复制代码
- 遮罩层
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: 0.5).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)
}
复制代码
- 裁剪
@objc func cropAction() {
let frame = cropView.frame
guard let image = targetImageView.image else {
fatalError("图片数据有误")
}
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("图片剪裁出错")
}
debugPrint(cropImage)
// 保存到相册
var localID = ""
PHPhotoLibrary.shared().performChanges {
let result = PHAssetChangeRequest.creationRequestForAsset(from: cropImage)
let assetPlaceholder = result.placeholderForCreatedAsset
localID = assetPlaceholder?.localIdentifier ?? "" // 保存保存标志符
} completionHandler: { (success, error) in
if success == true {
debugPrint("保存成功")
//通过标志符获取对应的资源
let assetResult = PHAsset.fetchAssets(withLocalIdentifiers: [localID], options: nil)
let asset = assetResult.firstObject
let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
return true
}
//获取保存的图片路径
asset?.requestContentEditingInput(with: options, completionHandler: { (contentEditingInput, info) in
let uri = contentEditingInput?.fullSizeImageURL?.absoluteString ?? ""
debugPrint("保存的图片路径 = \(uri)")
})
} else {
NSLog("保存失败: \(String(describing: error?.localizedDescription))")
}
}
}
复制代码
- 移动整个裁剪区域
@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.width-frame.width
let maxY = targetImageView.frame.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()
}
}
复制代码
- 跳转裁剪区域边框
@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.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: 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()
}
}
}
复制代码
- UIImage Extension
extension UIImage {
//裁剪image,rect是相对于image.size大小
public func cropping(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
}
}
}
复制代码
- 手指滑动截图
// 被裁剪的图片
fileprivate lazy var targetImageView:UIImageView = {
let imageView = UIImageView(frame: CGRect(x: 10.0, y: 80.0, width: ScreenWith - 20.0, height: 400.0))
let path = Bundle.main.path(forResource: "cropImage@2x.jpg", ofType: nil) ?? ""
guard let image = UIImage(contentsOfFile: path) else {
fatalError("图片没有找到")
}
imageView.image = image
imageView.contentMode = .scaleToFill
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(crop(pan:))))
return imageView
}()
复制代码
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)
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END