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

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

在手势处理时,要注意,为了能跟随用户捏合手势的中心进行缩放,我们要在手势过程中移动缩放中心到手指中心,这里我们判断了 pinGesture 的 state 来确定手势开始、进行中和结束阶段。


 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;
 }

pinchCenter 就是捏合手势的中心,我们获取到当前图片 view 的 frame,然后计算当前 view 与手势中心的 x、y 坐标差,再根据手势缩放值 scale,创建出新的 frame


 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);

这个 frame 的中心坐标就在缩放手势的中心,将新的 frame 赋值给图片 view,从而实现依据手势中心进行缩放的效果。

而在手势结束阶段,我们要对图片缩放进行边界保护,既不能放大过大,也不能缩小过小。


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;