效果图


实现思路
-
拖拽裁切
这种实现比较简单,在imageView上添加一个拖拽手势,当手势开始的时候记录起点,当手势改变的时候修改view的frame。当手势结束的时候裁切图片
裁切图片的代码
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
}
}
}
-
裁切框
裁切款要稍微复杂一点,首先是要做一个周围黑色背景中间镂空的效果,而且镂空可以放大、缩小、平移。这个通过在imageView上加layer实现了,放大缩小平移等操作是通过新生成layer替换之前的layer实现的
func resetCropMask() -> Void {
let path = UIBezierPath(rect: self.backImageView.bounds)
let clearPath = UIBezierPath(rect: self.cropView.frame)
path.append(clearPath)
let layer = CAShapeLayer()
layer.frame = self.backImageView.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 backImageView.layer.sublayers ?? [] {
if item is CAShapeLayer {
item.removeFromSuperlayer()
}
}
self.backImageView.layer.addSublayer(layer)
}
layer没有touch事件,所以添加了一个和layer镂空区域一致的透明view,这个view主要用来添加拖拽手势,处理裁剪框的放大缩小平移。
在这个view上,添加了四角四边总共八个view,对每个view的拖拽事件分别做了处理,这里其实并不难,比较容易出错。
代码详见demo
代码
注意
裁切的图片必须要正常显示且显示完整,不能拉伸图片或者显示不全,因为最后裁切的时候是用裁切view相对于imageView的坐标计算的,如果图片没有正常显示,那么最后生成的图片会不正确
网友评论