找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3006|回复: 0
打印 上一主题 下一主题
收起左侧

iOS开发之头像裁剪

[复制链接]
跳转到指定楼层
楼主
ID:85764 发表于 2015-7-18 00:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//

//  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];

    // 缩放适应屏幕
    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) {
        // 通过手势的缩放系数改变view的transform
        view.transform = CGAffineTransformScale(view.transform, pinch.scale, pinch.scale);
        // 然后将缩放系数置为1
        pinch.scale = 1.0f;
    }else if (pinch.state == UIGestureRecognizerStateEnded) {
        // 缩放结束
        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) {
        // 设置原始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  根据边框来设置frame
*
* @param
*
* @return
*/
- (CGRect)handleBorderOverFlow:(CGRect)newFrame
{
    // x坐标 计算不能超过裁剪的坐标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坐标
    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





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表