欢迎关注我的新浪微博: @立里童立里
通过Quartz 2D知识点制作了一个移动镜头的小Demo
3. 调节速率,如图所示:(你觉得可能吗,展示不了,请看上图速度调节条)
4. 显示全图,如下图所示(由于图片超过了200K所以改了下尺寸):
5. 隐藏全图,回到镜头画面
6. 裁剪图片(只保留镜头笑下的图片,并保存到本地),如图所示:
7. 截取全图,如图所示:
8. 触摸停止或启动镜头,(无法展示,见谅)
源代码如下所示:
文件截图
FYViewController.m 文件代码
#define FYColor(r, g, b, a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a/1.0] #define FYSaveTruPath [NSString stringWithFormat:@"/Users/tongfangyuan/Desktop/truncation/truncation_image/tru_image_%i.png",self.imageCounts] #import "FYViewController.h" #import "UIImage+FY.h" #import "FYView.h" @interface FYViewController () // 底部工具栏 @property (nonatomic, strong) UIView *BottomView; // 图片 @property (nonatomic, strong) UIImageView *iconView; // 全图按钮 @property (nonatomic, strong) UIButton *wholeBtn; @property (nonatomic, assign, getter = isShowImage) BOOL showImage; // 截图按钮 @property (nonatomic, strong) UIButton *truncationBtn; // 保存截图模式 @property (nonatomic, assign, getter = isTruncation) BOOL truncation; // FYView @property (strong, nonatomic) IBOutlet FYView *searchView; // 截图张数 @property (nonatomic, assign) int imageCounts; @end @implementation FYViewController - (void)viewDidLoad { [super viewDidLoad]; // 设置背景图片 _iconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"luffy"]]; self.view.backgroundColor = [UIColor blackColor]; // 1. 创建底部工具栏View _BottomView = [[UIView alloc]init]; _BottomView.backgroundColor = FYColor(201, 201, 201, 1); _BottomView.frame = CGRectMake(0, FYScreenH - FYDefaultH, FYScreenW, FYDefaultH); [self.view addSubview:_BottomView]; // 2. 创建全图按钮(打开或关闭全图按钮) _wholeBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, FYScreenW / 2, FYDefaultH)]; _wholeBtn.backgroundColor = [UIColor blueColor]; [_wholeBtn setTitle:@"显示全图" forState:UIControlStateNormal]; [_wholeBtn addTarget:self action:@selector(showWholeImage:) forControlEvents:UIControlEventTouchUpInside]; _showImage = YES; [self.BottomView addSubview:_wholeBtn]; // 3. 创建截图按钮 _truncationBtn = [[UIButton alloc] initWithFrame:CGRectMake(FYScreenW / 2, 0, FYScreenW / 2, FYDefaultH)]; [_truncationBtn setTitle:@"裁剪图片" forState:UIControlStateNormal]; [_truncationBtn addTarget:self action:@selector(truncationPicture) forControlEvents:UIControlEventTouchUpInside]; _truncation = NO; [self.BottomView addSubview:_truncationBtn]; } // 截取屏幕 - (void)truncationPicture { if (self.isTruncation) { // 截屏模式 // 截取全图 [self saveFullImage]; } else { // 裁剪模式 // 裁剪镜头下的图片 [self.searchView clipImage]; } } /** * 截取全图 */ - (void)saveFullImage { // 1. 截图 CGSize size = CGSizeMake(FYScreenW, FYScreenH - FYDefaultH); UIImage *newImage = [UIImage imageByTruncationInView:self.view WithSize:size]; // 2. 截屏计数器+1,保存图片 self.imageCounts++; NSData *data = UIImagePNGRepresentation(newImage); [data writeToFile:FYSaveTruPath atomically:YES]; } // 显示或隐藏全图事件 - (void)showWholeImage:(id)sender { if (self.isShowImage) { // 展开全图,停止镜头 // 1. 显示全图 [self showImage]; // 2. 更改两个按钮的主题 [_wholeBtn setTitle:@"隐藏全图" forState:UIControlStateNormal]; [_truncationBtn setTitle:@"截取全图" forState:UIControlStateNormal]; // 3. 更改模式 _showImage = NO; _truncation = YES; } else { // 关闭全图, 移动镜头 // 1. 隐藏全图 [self closeImage]; // 2. 更改两个按钮的主题 [_wholeBtn setTitle:@"显示全图" forState:UIControlStateNormal]; [_truncationBtn setTitle:@"裁剪图片" forState:UIControlStateNormal]; // 3. 更改模式 _showImage =YES; _truncation = NO; } } /** * 显示全图 */ - (void)showImage { // 1. 显示全图 _iconView.frame = CGRectMake(0, 0, 0, FYScreenH - FYDefaultH); [UIView animateWithDuration:1 animations:^{ _iconView.frame = CGRectMake(0, 0, FYScreenW, FYScreenH - FYDefaultH); }]; [self.view addSubview:_iconView]; _iconView.userInteractionEnabled = NO; // 2. 镜头停止滚动 [self.searchView stopScroll:nil]; } /** * 隐藏全图 */ - (void)closeImage { // 1. 隐藏全图 _iconView.frame = CGRectMake(0, 0, FYScreenW, FYScreenH - FYDefaultH); [UIView animateWithDuration:1 animations:^{ _iconView.frame = CGRectMake(FYScreenW, 0, 0, FYScreenH - FYDefaultH); } completion:^(BOOL finished) { [self.searchView stopScroll:nil]; }]; _iconView.userInteractionEnabled = NO; } // 隐藏状态栏 - (BOOL)prefersStatusBarHidden { return YES; } @end
FYView.h 文件代码:
#import <UIKit/UIKit.h> @interface FYView : UIView // 点击控制圆圈移动或停止 - (void)stopScroll:(id)sender; // 裁剪图片 - (void)clipImage; @end
FYView.m 文件代码:
#import "FYView.h" #import "UIImage+FY.h" #define FYImageRect CGRectMake(0, 0, FYScreenW, FYScreenH - FYDefaultH) #define FYSaveClipPath [NSString stringWithFormat:@"/Users/tongfangyuan/Desktop/truncation/clip_Image/clip_image_%i.png",self.imageCounts] @interface FYView () // 保存圆圈坐标,直径, 移动距离 @property (nonatomic, assign) CGFloat centerX; @property (nonatomic, assign) CGFloat centerY; @property (nonatomic, assign) CGFloat diameter; @property (nonatomic, assign) CGFloat moveDis; // 截图张数 @property (nonatomic, assign) int imageCounts; // 保存累加值 @property (nonatomic, assign) int countX; @property (nonatomic, assign) int countY; // 保存计时器状态 @property (nonatomic, assign, getter = isTimerOn) BOOL timerOn; // 创建一个定时器 @property (nonatomic, strong) NSTimer *timer; // 直径滑动条 @property (weak, nonatomic) IBOutlet UISlider *mySlider;; // 速度滑动条 @property (weak, nonatomic) IBOutlet UISlider *SpeedSlider; // 改变直径 - (IBAction)changeMyRadius:(UISlider *)sender; // 改变速度 - (IBAction)changeSpeed:(UISlider *)sender; @end @implementation FYView // moveDis(直径) get方法 - (CGFloat)moveDis { _moveDis = self.SpeedSlider.value; return _moveDis; } // diameter(移动距离) get 方法 - (CGFloat)diameter { _diameter = self.mySlider.value; [self setNeedsDisplay]; return _diameter; } - (void)drawRect:(CGRect)rect { // 获取当前上下文 CGContextRef ref = UIGraphicsGetCurrentContext(); // 创建上下文栈 CGContextSaveGState(ref); CGContextAddEllipseInRect(ref, CGRectMake(self.centerX, self.centerY, self.diameter, self.diameter)); // 裁剪函数 CGContextClip(ref); // 渲染 CGContextStrokePath(ref); // 创建一个图片 UIImage *iconImage = [UIImage imageNamed:@"luffy"]; [iconImage drawInRect:FYImageRect]; // 恢复默认属性 CGContextRestoreGState(ref); // 再一次渲染 CGContextStrokePath(ref); [self addTimer]; [self addTimer]; } /** * 裁剪 */ - (void)clipImage { // 创建图片 UIImage *image = [UIImage imageNamed:@"luffy"]; // 裁剪图片 CGRect rect = CGRectMake(self.centerX, self.centerY, self.diameter, self.diameter); UIImage *newImage = [UIImage imageWithClipImage:image inRect:rect]; // 存入数据 NSData *data = UIImagePNGRepresentation(newImage); self.imageCounts++; [data writeToFile:FYSaveClipPath atomically:YES]; } /** * 移动镜头 */ - (void)searchImage { // 判断X坐标位置 if (self.centerX <= 0) { // 到达最右边,圆圈X坐标减少 _countX = self.moveDis; } else if (self.centerX >= FYScreenW - self.diameter){ // 到达最左边,圆圈X坐标增加 _countX = - self.moveDis; } // 判断Y坐标位置 if (self.centerY <= 0) { // 到达最底部, 圆圈Y坐标减少 _countY = self.moveDis; } else if (self.centerY >= FYScreenH - self.diameter - FYDefaultH){ // 到达最顶部, 圆圈Y坐标增加 _countY = - self.moveDis; } _centerX += _countX; _centerY += _countY; [self setNeedsDisplay]; } /* 触摸启动或停止计时器 */ - (void)stopScroll:(id)sender { if (self.isTimerOn) { [self removeTimer]; } else { self.superview.backgroundColor = [UIColor whiteColor]; [self addTimer]; } } /** * 改变圆的直径 */ - (IBAction)changeMyRadius:(UISlider *)sender { self.diameter = sender.value; } /** * 改变圆移动的速度 */ - (IBAction)changeSpeed:(UISlider *)sender { self.moveDis = sender.value; } /** * 添加计时器 */ - (void)addTimer { self.timer = [NSTimer scheduledTimerWithTimeInterval:0.00025 target:self selector:@selector(searchImage) userInfo:nil repeats:NO]; self.timerOn = YES; } /** * 移除计时器 */ - (void)removeTimer { self.timerOn = NO; [self.timer invalidate]; self.timer = nil; } @end
UIImage+FY.h 文件代码如下:
#import <UIKit/UIKit.h> #define FYScreenW 320 #define FYScreenH 480 #define FYDefaultH 44 #define FYImageRect CGRectMake(0, 0, FYScreenW, FYScreenH - FYDefaultH) @interface UIImage (FY) /** * 裁剪图片 */ + (UIImage *)imageWithClipImage:(UIImage *)image inRect:(CGRect)rect; /** * 截取屏幕 */ + (UIImage *)imageByTruncationInView:(UIView *)view WithSize:(CGSize)size; @end
UIImage+FY.m 文件代码如下:
#import "UIImage+FY.h" @implementation UIImage (FY) /** * 裁剪图片 */ + (UIImage *)imageWithClipImage:(UIImage *)image inRect:(CGRect)rect { // 创建上下文 CGSize size = CGSizeMake(FYScreenW, FYScreenH - FYDefaultH); UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); // 获取当前上下文 CGContextRef ref = UIGraphicsGetCurrentContext(); CGContextAddEllipseInRect(ref, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)); // 执行裁剪 CGContextClip(ref); [image drawInRect:FYImageRect]; // 获取裁剪后的图片 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); // 结束上下文 CGContextStrokePath(ref); return newImage; } /** * 截取屏幕 */ + (UIImage *)imageByTruncationInView:(UIView *)view WithSize:(CGSize)size { // 1. 创建上下文 UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); // 2. 调取方法截屏 [view.layer renderInContext:UIGraphicsGetCurrentContext()]; // 3. 获得截取的图片 UIImage *newIamge = UIGraphicsGetImageFromCurrentImageContext(); // 4. 渲染 UIGraphicsEndImageContext(); return newIamge; } @end
控件连线图:
提示:这个button是一个全透明的铺满屏幕的按钮(用来实现触摸停止或启动镜头功能)其 rect为
CGRectMake(0, 0, 320, 480); // 全透明,铺满屏幕的按钮
----------------------------------------
兴趣驱动iOS开发