iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)


欢迎关注我的新浪微博: @立里童立里


   通过Quartz 2D知识点制作了一个移动镜头的小Demo

  • 实现的功能:

  • 1. 移动镜头,如下图所示:


  • iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)












  • 2. 调节镜头大小,如下图所示:


  • iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)












  • 3. 调节速率,如图所示:(你觉得可能吗,展示不了,请看上图速度调节条)

  • 4. 显示全图,如下图所示(由于图片超过了200K所以改了下尺寸):

iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)

  • 5. 隐藏全图,回到镜头画面

iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)

  • 6. 裁剪图片(只保留镜头笑下的图片,并保存到本地),如图所示:

iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)

  • 7. 截取全图,如图所示:

        iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)

  • 8. 触摸停止或启动镜头,(无法展示,见谅)


源代码如下所示:

  • 文件截图

  • iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)




  • 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

  • 控件连线图:

iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)

提示:这个button是一个全透明的铺满屏幕的按钮(用来实现触摸停止或启动镜头功能)其 rect为 

CGRectMake(0, 0, 320, 480); // 全透明,铺满屏幕的按钮

  iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)

iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)


----------------------------------------

兴趣驱动iOS开发

你可能感兴趣的:(quartz,oc,ios开发,截图,2d,移动镜头)