iOS中实现动态区域裁剪图片功能实例

2020-01-21 02:34:44王振洲

可以看到,我们进行了两步判断,从而获得合适的宽高值,然后将图片进行布局,在自动布局时将图片中心与裁剪区域中心重合,最后我们会得到下面的效果图

ios,裁剪屏幕指定区域,裁剪图片指定区域,图片裁剪

支持移动和缩放图片

正如上面所讲,由于图片在裁剪区域内是以类似 UIViewContentModeScaleAspectFill 的方式放置的,很可能出现部分内容溢出裁剪区域,因此我们要让图片能支持动态移动和缩放,从而使用户能灵活地裁剪图片的内容。

具体实现上,我们其实是在 cropview 上加上手势,间接操作图片的尺寸和位置,这样有助于后面我们实现动态改变裁剪区域的实现。

缩放功能

这里实现缩放的原理实际是对放置图片的 UIImageView 的 frame 进行修改,首先我们要记录下最初的 UIImageView 的 frame


self.originalFrame = CGRectMake(self.cropAreaX - (tempWidth - self.cropAreaWidth)/2, self.cropAreaY - (tempHeight - self.cropAreaHeight)/2, tempWidth, tempHeight);

然后为 cropView 添加手势


 // 捏合手势
 UIPinchGestureRecognizer *pinGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleCenterPinGesture:)];
 [self.view addGestureRecognizer:pinGesture];

然后是手势处理函数


-(void)handleCenterPinGesture:(UIPinchGestureRecognizer *)pinGesture
{
 CGFloat scaleRation = 3;
 UIView * view = self.bigImageView;
 
 // 缩放开始与缩放中
 if (pinGesture.state == UIGestureRecognizerStateBegan || pinGesture.state == UIGestureRecognizerStateChanged) {
 // 移动缩放中心到手指中心
 CGPoint pinchCenter = [pinGesture locationInView:view.superview];
 CGFloat distanceX = view.frame.origin.x - pinchCenter.x;
 CGFloat distanceY = view.frame.origin.y - pinchCenter.y;
 CGFloat scaledDistanceX = distanceX * pinGesture.scale;
 CGFloat scaledDistanceY = distanceY * pinGesture.scale;
 CGRect newFrame = CGRectMake(view.frame.origin.x + scaledDistanceX - distanceX, view.frame.origin.y + scaledDistanceY - distanceY, view.frame.size.width * pinGesture.scale, view.frame.size.height * pinGesture.scale);
 view.frame = newFrame;
 pinGesture.scale = 1;
 }
 
 // 缩放结束
 if (pinGesture.state == UIGestureRecognizerStateEnded) {
 CGFloat ration = view.frame.size.width / self.originalFrame.size.width;
 
 // 缩放过大
 if (ration > 5) {
 CGRect newFrame = CGRectMake(0, 0, self.originalFrame.size.width * scaleRation, self.originalFrame.size.height * scaleRation);
 view.frame = newFrame;
 }
 
 // 缩放过小
 if (ration < 0.25) {
 view.frame = self.originalFrame;
 }
 // 对图片进行位置修正
 CGRect resetPosition = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height);
 
 if (resetPosition.origin.x >= self.cropAreaX) {
 resetPosition.origin.x = self.cropAreaX;
 }
 if (resetPosition.origin.y >= self.cropAreaY) {
 resetPosition.origin.y = self.cropAreaY;
 }
 if (resetPosition.size.width + resetPosition.origin.x < self.cropAreaX + self.cropAreaWidth) {
 CGFloat movedLeftX = fabs(resetPosition.size.width + resetPosition.origin.x - (self.cropAreaX + self.cropAreaWidth));
 resetPosition.origin.x += movedLeftX;
 }
 if (resetPosition.size.height + resetPosition.origin.y < self.cropAreaY + self.cropAreaHeight) {
 CGFloat moveUpY = fabs(resetPosition.size.height + resetPosition.origin.y - (self.cropAreaY + self.cropAreaHeight));
 resetPosition.origin.y += moveUpY;
 }
 view.frame = resetPosition;
 
 // 对图片缩放进行比例修正,防止过小
 if (self.cropAreaX < self.bigImageView.frame.origin.x
 || ((self.cropAreaX + self.cropAreaWidth) > self.bigImageView.frame.origin.x + self.bigImageView.frame.size.width)
 || self.cropAreaY < self.bigImageView.frame.origin.y
 || ((self.cropAreaY + self.cropAreaHeight) > self.bigImageView.frame.origin.y + self.bigImageView.frame.size.height)) {
 view.frame = self.originalFrame;
 }
 }
}