標(biāo)題: iOS開發(fā)之頭像裁剪 [打印本頁]
作者: niujia 時間: 2015-7-18 00:34
標(biāo)題: iOS開發(fā)之頭像裁剪
//
// 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
歡迎光臨 (http://www.torrancerestoration.com/bbs/) |
Powered by Discuz! X3.1 |