//
// CrapPhotoViewController.h // StupidFM // // Created by 寒竹子 on 15/6/18. // Copyright (c) 2015年 寒竹子. All rights reserved. //
#import "ParentViewController.h"
@class CrapPhotoViewController;
@protocol CrapPhotoViewControllerDelegate <NSObject>
// 點擊確定完成圖片裁剪的代理方法 - (void)imageCrap:(CrapPhotoViewController *)crapViewController didFinished:(UIImage *)editedImage; // 點擊取消后的代理方法 - (void)imageCrapDidCancel:(CrapPhotoViewController *)crapViewController;
@end
@interface CrapPhotoViewController : ParentViewController
@property (nonatomic, assign) NSInteger tag; @property (nonatomic, weak) id<CrapPhotoViewControllerDelegate> delegate; @property (nonatomic, assign) CGRect cropFrame;
// 初始化方法 - (instancetype)initWithImage:(UIImage *)orignalImage cropFrame:(CGRect)cropFrame limitScaleRatio:(NSInteger)limitRatio;
@end
// // CrapPhotoViewController.m // StupidFM // // Created by 寒竹子 on 15/6/18. // Copyright (c) 2015年 寒竹子. All rights reserved. //
#import "CrapPhotoViewController.h"
#define Scale_Y 100.0f #define Boundce_Duration .3f
@interface CrapPhotoViewController ()
@property (nonatomic, strong) UIImage * orignalImage; @property (nonatomic, strong) UIImage * editedImage; @property (nonatomic, strong) UIImageView * showImageView; @property (nonatomic, strong) UIView * overlayView; @property (nonatomic, strong) UIView * ratioView;
@property (nonatomic, assign) CGRect oldFrame; @property (nonatomic, assign) CGRect largeFrame; @property (nonatomic, assign) CGFloat limitRatio;
@property (nonatomic, assign) CGRect lastFrame;
@end
@implementation CrapPhotoViewController
- (instancetype)initWithImage:(UIImage *)orignalImage cropFrame:(CGRect)cropFrame limitScaleRatio:(NSInteger)limitRatio { if (self = [super init]) { self.cropFrame = cropFrame; self.limitRatio = limitRatio; self.orignalImage = orignalImage; }
return self; }
/** * @brief 初始化View * * @param * * @return */ - (void)initialView { self.showImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.width, self.height)]; [self.showImageView setMultipleTouchEnabled:YES]; [self.showImageView setUserInteractionEnabled:YES]; [self.showImageView setImage:self.orignalImage];
// 縮放適應(yīng)屏幕 CGFloat oriWidth = self.cropFrame.size.width; CGFloat oriHeight = self.orignalImage.size.height * (oriWidth / self.orignalImage.size.width); CGFloat oriX = self.cropFrame.origin.x + (self.cropFrame.size.width - oriWidth) / 2.0f; CGFloat oriY = self.cropFrame.origin.y + (self.cropFrame.size.height - oriHeight) / 2.0f; self.oldFrame = CGRectMake(oriX, oriY, oriWidth, oriHeight); self.lastFrame = self.oldFrame; self.showImageView.frame = self.oldFrame; self.largeFrame = CGRectMake(0, 0, self.limitRatio * self.oldFrame.size.width, self.limitRatio * self.oldFrame.size.height);
[self addGestureRecognizers]; [self.view addSubview:self.showImageView];
self.overlayView = [[UIView alloc] initWithFrame:self.view.bounds]; self.overlayView.alpha = .3f; self.overlayView.backgroundColor = [UIColor blackColor]; self.overlayView.userInteractionEnabled = NO; self.overlayView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; [self.view addSubview:self.overlayView];
self.ratioView = [[UIView alloc] initWithFrame:self.cropFrame]; self.ratioView.layer.borderColor = [UIColor redColor].CGColor; self.ratioView.layer.borderWidth = 2.0f; self.ratioView.autoresizingMask = UIViewAutoresizingNone; [self.view addSubview:self.ratioView];
[self overlayClipping]; }
- (void)initControlBtn { UIButton *cancelBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 50.0f, 100, 50)]; cancelBtn.backgroundColor = [UIColor clearColor]; cancelBtn.titleLabel.textColor = [UIColor whiteColor]; [cancelBtn setTitle:@"取消" forState:UIControlStateNormal]; [cancelBtn.titleLabel setFont:[UIFont fontWithName:@"Arial Unicode MS" size:16.0f]]; [cancelBtn.titleLabel setTextAlignment:NSTextAlignmentCenter]; [cancelBtn.titleLabel setLineBreakMode:NSLineBreakByWordWrapping]; [cancelBtn setTitleEdgeInsets:UIEdgeInsetsMake(5.0f, 5.0f, 5.0f, 5.0f)]; [cancelBtn addTarget:self action:@selector(cancelAction:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:cancelBtn];
// 完成 UIButton *confirmBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width - 100.0f, self.view.frame.size.height - 50.0f, 100, 50)]; confirmBtn.backgroundColor = [UIColor clearColor]; confirmBtn.titleLabel.textColor = [UIColor whiteColor]; [confirmBtn setTitle:@"確定" forState:UIControlStateNormal]; [confirmBtn.titleLabel setFont:[UIFont fontWithName:@"Arial Unicode MS" size:16.0f]]; [confirmBtn.titleLabel setTextAlignment:NSTextAlignmentCenter]; confirmBtn.titleLabel.textColor = [UIColor whiteColor]; [confirmBtn.titleLabel setLineBreakMode:NSLineBreakByWordWrapping]; [confirmBtn.titleLabel setNumberOfLines:0]; [confirmBtn setTitleEdgeInsets:UIEdgeInsetsMake(5.0f, 5.0f, 5.0f, 5.0f)]; [confirmBtn addTarget:self action:@selector(sureAction:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:confirmBtn]; }
// 取消 - (void)cancelAction:(UIButton *)btn { if ([self.delegate respondsToSelector:@selector(imageCrapDidCancel:)]) { [self.delegate imageCrapDidCancel:self]; } }
// 確定 - (void)sureAction:(UIButton *)btn { if ([self.delegate respondsToSelector:@selector(imageCrap:didFinished:)]) { [self.delegate imageCrap:self didFinished:self.editedImage]; } }
/** * @brief 圖片裁剪 * * @param * * @return */ - (void)overlayClipping { CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; CGMutablePathRef path = CGPathCreateMutable(); // 畫左邊的line CGPathAddRect(path, nil, CGRectMake(0, 0, self.ratioView.frame.origin.x, self.overlayView.frame.size.height)); // 畫右邊的line CGPathAddRect(path, nil, CGRectMake( self.ratioView.frame.origin.x + self.ratioView.frame.size.width, 0, self.overlayView.frame.size.width - self.ratioView.frame.origin.x - self.ratioView.frame.size.width, self.overlayView.frame.size.height)); // 畫上邊的line CGPathAddRect(path, nil, CGRectMake(0, 0, self.overlayView.frame.size.width, self.ratioView.frame.origin.y)); // 畫下邊的line CGPathAddRect(path, nil, CGRectMake(0, self.ratioView.frame.origin.y + self.ratioView.frame.size.height, self.overlayView.frame.size.width, self.overlayView.frame.size.height - self.ratioView.frame.origin.y + self.ratioView.frame.size.height)); maskLayer.path = path; self.overlayView.layer.mask = maskLayer; CGPathRelease(path); }
/** * @brief 添加縮放手勢 和 拖動手勢 * * @param * * @return */ - (void)addGestureRecognizers { // 添加縮放手勢 UIPinchGestureRecognizer * pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchAction:)]; [self.view addGestureRecognizer:pinch];
// 添加拖動手勢 UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)]; [self.view addGestureRecognizer:pan]; }
/** * @brief 縮放手勢事件 * * @param * * @return */ - (void)pinchAction:(UIPinchGestureRecognizer *)pinch { UIView * view = self.showImageView; if (pinch.state == UIGestureRecognizerStateBegan || pinch.state == UIGestureRecognizerStateChanged) { // 通過手勢的縮放系數(shù)改變view的transform view.transform = CGAffineTransformScale(view.transform, pinch.scale, pinch.scale); // 然后將縮放系數(shù)置為1 pinch.scale = 1.0f; }else if (pinch.state == UIGestureRecognizerStateEnded) { // 縮放結(jié)束 CGRect newFrame = self.showImageView.frame; newFrame = [self hanleScaleOverFrame:newFrame]; newFrame = [self handleBorderOverFlow:newFrame];
[UIView animateWithDuration:Boundce_Duration animations:^{ self.showImageView.frame = newFrame; self.lastFrame = newFrame; }]; } }
/** * @brief 計算縮放后的新的frame * * @param * * @return */ - (CGRect)hanleScaleOverFrame:(CGRect)newFrame { CGPoint oriCenter = CGPointMake(newFrame.origin.x + newFrame.size.width / 2.0f, newFrame.origin.y + newFrame.size.height / 2.0f); if (newFrame.size.width < self.oldFrame.size.width) { // 設(shè)置原始frame newFrame = self.oldFrame; }
if (newFrame.size.width > self.largeFrame.size.width) { // 超出范圍 newFrame = self.largeFrame; }
newFrame.origin.x = oriCenter.x - newFrame.size.width / 2.0f; newFrame.origin.y = oriCenter.y - newFrame.size.height / 2.0f;
return newFrame; }
/** * @brief 根據(jù)邊框來設(shè)置frame * * @param * * @return */ - (CGRect)handleBorderOverFlow:(CGRect)newFrame { // x坐標(biāo) 計算不能超過裁剪的坐標(biāo)x if (newFrame.origin.x > self.cropFrame.origin.x) { newFrame.origin.x = self.cropFrame.origin.x; }
if (CGRectGetMaxX(newFrame) < self.cropFrame.size.width) { newFrame.origin.x = self.cropFrame.size.width - newFrame.size.width; }
// y坐標(biāo) if (newFrame.origin.y > self.cropFrame.origin.y) { newFrame.origin.y = self.cropFrame.origin.y; }
if (CGRectGetMaxY(newFrame) < self.cropFrame.origin.y + self.cropFrame.size.height) { newFrame.origin.y = self.cropFrame.origin.y + self.cropFrame.size.height - newFrame.size.height; }
if (self.showImageView.frame.size.width > self.showImageView.frame.size.height && newFrame.size.height <= self.cropFrame.size.height) { newFrame.origin.y = self.cropFrame.origin.y + (self.cropFrame.size.height - newFrame.size.height) / 2.0f; }
return newFrame; }
/** * @brief 拖動手勢 * * @param * * @return */ - (void)panAction:(UIPanGestureRecognizer *)pan { UIView * view = self.showImageView;
if (pan.state == UIGestureRecognizerStateBegan || pan.state == UIGestureRecognizerStateChanged) { CGFloat absCenterX = self.cropFrame.origin.x + self.cropFrame.size.width / 2.0f; CGFloat absCenterY = self.cropFrame.origin.y + self.cropFrame.size.height / 2.0f;
CGFloat scaleRatio = self.showImageView.frame.size.width / self.cropFrame.size.width; CGFloat acceleratorX = 1 - ABS(absCenterX - view.center.x) / (scaleRatio * absCenterX); CGFloat acceleratorY = 1 - ABS(absCenterY - view.center.y) / (scaleRatio * absCenterY); CGPoint translation = [pan translationInView:view.superview]; [view setCenter:(CGPoint){view.center.x + translation.x * acceleratorX, view.center.y + translation.y * acceleratorY}]; [pan setTranslation:CGPointZero inView:view.superview]; [view setCenter:(CGPoint){view.center.x + translation.x * acceleratorX, view.center.y + translation.y * acceleratorY}]; [pan setTranslation:CGPointZero inView:view.superview]; }else if (pan.state == UIGestureRecognizerStateEnded){ CGRect newFrame = self.showImageView.frame; newFrame = [self handleBorderOverFlow:newFrame]; [UIView animateWithDuration:Boundce_Duration animations:^{ self.showImageView.frame = newFrame; self.lastFrame = newFrame; }]; } }
// 得到裁剪后的小圖片 -(UIImage *)getSubImage{ CGRect squareFrame = self.cropFrame; CGFloat scaleRatio = self.lastFrame.size.width / self.orignalImage.size.width; CGFloat x = (squareFrame.origin.x - self.lastFrame.origin.x) / scaleRatio; CGFloat y = (squareFrame.origin.y - self.lastFrame.origin.y) / scaleRatio; CGFloat w = squareFrame.size.width / scaleRatio; CGFloat h = squareFrame.size.width / scaleRatio; if (self.lastFrame.size.width < self.cropFrame.size.width) { CGFloat newW = self.orignalImage.size.width; CGFloat newH = newW * (self.cropFrame.size.height / self.cropFrame.size.width); x = 0; y = y + (h - newH) / 2; w = newH; h = newH; } if (self.lastFrame.size.height < self.cropFrame.size.height) { CGFloat newH = self.orignalImage.size.height; CGFloat newW = newH * (self.cropFrame.size.width / self.cropFrame.size.height); x = x + (w - newW) / 2; y = 0; w = newH; h = newH; } CGRect myImageRect = CGRectMake(x, y, w, h); CGImageRef imageRef = self.orignalImage.CGImage; CGImageRef subImageRef = CGImageCreateWithImageInRect(imageRef, myImageRect); CGSize size; size.width = myImageRect.size.width; size.height = myImageRect.size.height; UIGraphicsBeginImageContext(size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextDrawImage(context, myImageRect, subImageRef); UIImage* smallImage = [UIImage imageWithCGImage:subImageRef]; UIGraphicsEndImageContext();
return smallImage; }
- (void)viewDidLoad { [super viewDidLoad];
[self initialView]; [self initControlBtn]; }
@end
|