• iOS开发之头像裁剪


    iOS开发之头像裁剪
    图片 //

    //  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:selfaction:@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

     
  • 相关阅读:
    12个非常不错的javascript类库
    CSS中单位em和rem的区别
    CSS中box-sizing属性的作用
    网页设计中的默认字体样式详解
    jQuery遍历Table表格的行和列
    css常用解决方案
    JS判断字符串小括号是否成对合法
    Less编码规范
    React九宫格抽奖
    n个有序数组,取出k个最大值
  • 原文地址:https://www.cnblogs.com/hanzhuzi/p/4594043.html
Copyright © 2020-2023  润新知