iPhone/iPad高级应用与手游开发学习笔记:多点触摸与手势检测(三:UIPinchGestureRecognizer和UIRotationGestureRecognizer)

先说一件不幸的事情,本人中午打篮球,不慎脚拐了......悲催啊,愚人节,但是这件事情绝不愚人。

言归正传,上一篇学习了捏合手势,这一篇中我们学习旋转手势,并且使用旋转和捏合做一个操作图片的例子

使用UIRotationGestureRecognizer处理旋转手势的步骤与使用其他手势处理器的步骤完全相同,UIRotationGestureRecognizer定义了如下两个属性来获取旋转相关信息:

rotation:获取旋转角度

velocity: 获取旋转速度

例子:

一.创建一个带有xib或者storyboard的simple view application

二,给storyboard后者xib中拖一个UIImage视图

三,创建一个category,代码如下:

类别头文件:

#import <UIKit/UIKit.h>

@interface UIImage (FKCategory)
//对指定UI控件进行截图
+(UIImage *) captureView:(UIView *) targetView;
+(UIImage *) captureScreen;
//定义一个方法用于挖取图片的指定区域
-(UIImage *) imageAtRect:(CGRect) rect;
//保持图片纵横比缩放,最短边必须撇配targetSize的大小
//可能有一条边的长度会超过targetSize指定的大小
-(UIImage *) imageByScalingAspectToMinSize:(CGSize) targetSize;
//保持图片纵横比缩放,最长边匹配targetSize的大小
//可能有一条边的长度会小于targetSize指定的大小
-(UIImage *) imageByScalingAspectToMaxSize:(CGSize) targetSize;
//不保持图片纵横比缩放
-(UIImage *) imageByScalingToSize:(CGSize) targetSize;
//对图片按弧度执行旋转
-(UIImage *) imageRotatedByRadians:(CGFloat) radians;
//对图片按角度执行旋转
-(UIImage *) imageRotatedByDegress:(CGFloat) degrees;

-(void) saveToDocuments:(NSString *) fileName;
@end

实现类:

#import "UIImage+FKCategory.h"

#import <QuartzCore/QuartzCore.h>

@implementation UIImage (FKCategory)


+(UIImage *) captureScreen

{

    //需要先声明该外部函数

    extern CGImageRef UIGetScreenImage();

    //调用UIGetScreenImage()函数执行截屏

    CGImageRef screen = UIGetScreenImage();

    //获取截屏得到的图片

    UIImage *newImage = [UIImage imageWithCGImage:screen];

    return newImage;

}


+(UIImage *) captureView:(UIView *) targetView

{

    //获取目标UIView的所在区域

    CGRect rect = targetView.frame;

    //开始绘图

    UIGraphicsBeginImageContext(rect.size);

    //获取当前的绘图context

    CGContextRef context = UIGraphicsGetCurrentContext();

    //调用CALayer的方法将当前控件绘制到绘图context

    [targetView.layer renderInContext:context];

    //获取该绘图context中得图片

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;

}


-(UIImage *) imageAtRect:(CGRect) rect

{

    //获取UIImage图片对应的CGImageRef对象

    CGImageRef srcImage = [self CGImage];

    //srcImage中挖取rect区域

    CGImageRef imageRef = CGImageCreateWithImageInRect(srcImage, rect);

    //将挖取出来的CGImageRef转换为UIImage对象

    UIImage *subImage = [UIImage imageWithCGImage:imageRef];

    CGImageRelease(srcImage);

    CGImageRelease(imageRef);

    return subImage;

    

}


-(UIImage *) imageByScalingAspectToMinSize:(CGSize)targetSize

{

    //获取源图片的宽和高

    CGSize imageSize = self.size;

    CGFloat width = imageSize.width;

    CGFloat height = imageSize.height;

    //获取图片缩放目标大小的宽和高

    CGFloat targetWidth = targetSize.width;

    CGFloat targetHeight = targetSize.height;

    //定义图片缩放后的宽度

    CGFloat scaledWidth = targetWidth;

    //定义图片缩放后的高度

    CGFloat scaledHeight = targetHeight;

    CGPoint anchorPoint = CGPointZero;

    //如果源图片的大小与缩放的目标大小不相等

    if(!CGSizeEqualToSize(imageSize, targetSize)) {

        //计算水平方向上的缩放因子

        CGFloat xFactor = targetWidth/width;

        CGFloat yFactor = targetHeight/height;

        //定义缩放因子scaleFactor,为两个缩放因子中较大的一个

        CGFloat scaleFactor = xFactor > yFactor?xFactor:yFactor;

        //根据缩放因子计算图片缩放后的宽度和高度

        scaledWidth = width * scaleFactor;

        scaledHeight = height * scaleFactor;

        //如果横向上德缩放因子大于纵向上的缩放因子,那么图片在纵向上需要裁切

        if(xFactor > yFactor) {

            anchorPoint.y = (targetHeight - scaledHeight) * 0.5;

        } else//如果横向上德缩放因子小于纵向上德缩放因子,那么图片在横向上需要裁切

            anchorPoint.x = (targetWidth -scaledWidth) * 0.5;

        }

    }

    //开始绘图

    UIGraphicsBeginImageContext(targetSize);

    //定义图片缩放后的区域

    CGRect anchorRect = CGRectZero;

    anchorRect.origin = anchorPoint;

    anchorRect.size.width = scaledWidth;

    anchorRect.size.height = scaledHeight;

    //将图片本身绘制到anchorRect区域中

    [self drawInRect:anchorRect];

    //获取绘制后生成的图片

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    //返回新图片

    return newImage;

    

}


-(UIImage *) imageByScalingAspectToMaxSize:(CGSize)targetSize

{

    //获取源图片的宽和高

    CGSize imageSize = self.size;

    CGFloat width = imageSize.width;

    CGFloat height = imageSize.height;

    //获取图片缩放目标大小的宽和高

    CGFloat targetWidth = targetSize.width;

    CGFloat targetHeight = targetSize.height;

    //定义图片缩放后的实际的宽和高度

    CGFloat scaledWidth = targetWidth;

    CGFloat scaledHeight = targetHeight;

    CGPoint anchorPoint = CGPointZero;

    

    //如果源图片的大小与缩放的目标大小不相等

    if(!CGSizeEqualToSize(imageSize, targetSize)) {

        CGFloat xFactor = targetWidth/width;

        CGFloat yFactor = targetHeight/height;

        //定义缩放因子scaleFactor为两个缩放因子中较小的一个

        CGFloat scaleFactor = xFactor < yFactor?xFactor:yFactor;

        //根据缩放因子计算图片缩放后的宽度和高度

        scaledWidth = width * scaleFactor;

        scaledHeight = height * scaleFactor;

        //如果横向的缩放因子小于纵向的缩放因子,图片在上面、下面有空白

        //那么图片在纵向上需要下移一段距离,保持图片在中间

        if(xFactor < yFactor) {

            anchorPoint.y = (targetHeight - scaledHeight) * 0.5;

        } else if(xFactor > yFactor) {

            anchorPoint.x = (targetWidth - scaledWidth) * 0.5;

        }

    }

    //开始绘图

    UIGraphicsBeginImageContext(targetSize);

    //定义图片缩放后的区域

    CGRect anchorRect = CGRectZero;

    anchorRect.origin = anchorPoint;

    anchorRect.size.width = scaledWidth;

    anchorRect.size.height = scaledHeight;

    

    //将图片本身绘制到anchorRect区域中

    [self drawInRect:anchorRect];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;

}


-(UIImage *) imageByScalingToSize:(CGSize)targetSize

{

    //开始绘图

    UIGraphicsBeginImageContext(targetSize);

    //定义图片缩放后的区域,因此无需保持纵横比,所以直接缩放

    CGRect anchorRect = CGRectZero;

    anchorRect.origin = CGPointZero;

    anchorRect.size = targetSize;

    //将图片本身绘制到anchorRect区域中

    [self drawInRect:anchorRect];

    //获取绘制后生成的图片

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;

}


//图片旋转角度

-(UIImage *) imageRotatedByRadians:(CGFloat)radians

{

    //定义一个执行旋转的CGAffineTransform结构体

    CGAffineTransform t = CGAffineTransformMakeRotation(radians);

    //对图片的原始区域执行旋转,获取旋转后的区域

    CGRect rotatedRect = CGRectApplyAffineTransform(CGRectMake(0.0, 0.0, self.size.width, self.size.height), t);

    //获取图片旋转后的大小

    CGSize rotatedSize = rotatedRect.size;

    //创建绘制位图的上下文

    UIGraphicsBeginImageContext(rotatedSize);

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    //指定坐标变换,将坐标中心平移到图片的中心

    CGContextTranslateCTM(ctx, rotatedSize.width/2, rotatedSize.height/2);

    //执行坐标变换,旋转过radians弧度

    CGContextRotateCTM(ctx, radians);

    //执行坐标变换,执行缩放

    CGContextScaleCTM(ctx, 1.0, -1.0);

    //绘制图片

    CGContextDrawImage(ctx, CGRectMake(-self.size.width/2, -self.size.height/2, self.size.width, self.size.height), self.CGImage);

    //获取绘制后生成的新图片

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;

}


-(UIImage *) imageRotatedByDegress:(CGFloat)degrees

{

    return [self imageRotatedByRadians:degrees*M_PI/180];

}


-(void) saveToDocuments:(NSString *)fileName

{

    //获取当前应用路径下得Documents目录下的指定文件名对应的文件路径

    NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:fileName];

    //保存PNG图片

    [UIImagePNGRepresentation(self) writeToFile:path atomically:YES];

}


@end

四,完成之后再在项目自动生成的视图控制器的头文件中加入你拖进去的UIImageView属性,注意,应该是IBOutlet的。然后在实现类中得代码如下:

#import "ViewController.h"

#import "UIImage+FKCategory.h"

@interface ViewController ()


@end


@implementation ViewController


UIImage *srcImage;

CGFloat currentScale;

CGFloat currentRotation;


- (void)viewDidLoad

{

    [super viewDidLoad];

    [UIApplication sharedApplication].statusBarHidden = YES;

    srcImage = [UIImage imageNamed:@"seashore.png"];

    //设置图片直接显示在中间

    self.view.contentMode = UIViewContentModeCenter;

    //设置imageView初始显示图片

    self.imageView.image = srcImage;

    //设置初始的缩放比例

    currentScale = 1;

    currentRotation = 0;

    //设置imageView允许用户交互,支持多点触碰

    self.imageView.userInteractionEnabled = YES;

    self.imageView.multipleTouchEnabled = YES;

    //创建UIPinchGestureRecognizer手势处理器,该手势处理器激发scaleImage方法

    UIPinchGestureRecognizer *gesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(scaleImage:)];

    //imageView添加手势处理器

    [self.imageView addGestureRecognizer:gesture];

    //创建UIRotationGestureRecognizer手势处理器,该手势处理器激发rotateImage

    UIRotationGestureRecognizer *rotateGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateImage:)];

    [self.imageView addGestureRecognizer:rotateGesture];

}


- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


-(void) scaleImage:(UIPinchGestureRecognizer *) gesture

{

    CGFloat scale = gesture.scale;

// 根据手势处理器的缩放比计算图片缩放后的目标大小

CGSize targetSize = CGSizeMake(srcImage.size.width * scale * currentScale,

                                   srcImage.size.height * scale * currentScale);

// 对图片进行缩放、旋转

self.imageView.image = [[srcImage imageByScalingToSize:targetSize]

                            imageRotatedByRadians:currentRotation];

// 如果手势结束

if(gesture.state == UIGestureRecognizerStateEnded)

{

// 计算结束时候图片的缩放比

currentScale = scale * currentScale;

}


}


-(void) rotateImage:(UIRotationGestureRecognizer *) gesture

{

    // 获取手势旋转的弧度

CGFloat rotation = gesture.rotation;

// 根据当前缩放比计算图片缩放后的目标大小

CGSize targetSize = CGSizeMake(srcImage.size.width * currentScale,

  srcImage.size.height * currentScale);

// 对图片进行缩放、旋转

self.imageView.image = [[srcImage imageByScalingToSize:targetSize]

                            imageRotatedByRadians:currentRotation + rotation];

// 如果旋转手势结束

if(gesture.state == UIGestureRecognizerStateEnded)

{

currentRotation = currentRotation + rotation;

}


}


@end

五,最后别忘记在xib或者storyboard中给UIImageView的属性连线

最后效果如下图:




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值