找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3016|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

iOS開(kāi)發(fā)之頭像裁剪

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:85764 發(fā)表于 2015-7-18 00:34 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
//

//  CrapPhotoViewController.h
//  StupidFM
//
//  Created by 寒竹子 on 15/6/18.
//  Copyright (c) 2015年 寒竹子. All rights reserved.
//

#import "ParentViewController.h"

@class CrapPhotoViewController;

@protocol CrapPhotoViewControllerDelegate <NSObject>

// 點(diǎn)擊確定完成圖片裁剪的代理方法
- (void)imageCrap:(CrapPhotoViewController *)crapViewController didFinished:(UIImage *)editedImage;
// 點(diǎn)擊取消后的代理方法
- (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();
    // 畫(huà)左邊的line
    CGPathAddRect(path, nil, CGRectMake(0, 0,
                                        self.ratioView.frame.origin.x,
                                        self.overlayView.frame.size.height));
    // 畫(huà)右邊的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));
    // 畫(huà)上邊的line
    CGPathAddRect(path, nil, CGRectMake(0, 0,
                                        self.overlayView.frame.size.width,
                                        self.ratioView.frame.origin.y));
    // 畫(huà)下邊的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  添加縮放手勢(shì) 和 拖動(dòng)手勢(shì)
*
* @param
*
* @return
*/
- (void)addGestureRecognizers
{
    // 添加縮放手勢(shì)
    UIPinchGestureRecognizer * pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchAction:)];
    [self.view addGestureRecognizer:pinch];

    // 添加拖動(dòng)手勢(shì)
    UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
    [self.view addGestureRecognizer:pan];
}

/**
* @brief  縮放手勢(shì)事件
*
* @param
*
* @return
*/
- (void)pinchAction:(UIPinchGestureRecognizer *)pinch
{
    UIView * view = self.showImageView;
    if (pinch.state == UIGestureRecognizerStateBegan || pinch.state == UIGestureRecognizerStateChanged) {
        // 通過(guò)手勢(shì)的縮放系數(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  計(jì)算縮放后的新的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ù)邊框來(lái)設(shè)置frame
*
* @param
*
* @return
*/
- (CGRect)handleBorderOverFlow:(CGRect)newFrame
{
    // x坐標(biāo) 計(jì)算不能超過(guò)裁剪的坐標(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  拖動(dòng)手勢(shì)
*
* @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





分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表