15-Quartz2D演练

2016-03-29  本文已影响38人  木喳喳的夏天

图片水印

图片裁剪

- (void)clipImage
{
    // 0.加载图片
    UIImage *image = [UIImage imageNamed:@"阿狸头像"];
    
    // 1.开启位图上下文,跟图片尺寸一样大
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
    
    // 2.设置圆形裁剪区域,正切与图片
    // 2.1创建圆形的路径
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    
    // 2.2把路径设置为裁剪区域
    [path addClip];
    
    // 3.绘制图片
    [image drawAtPoint:CGPointZero];
    
    // 4.从上下文中获取图片
    UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
    
    // 5.关闭上下文
    UIGraphicsEndImageContext();
    
    _imageView.image = clipImage;
}
+ (UIImage *)imageWithClipImage:(UIImage *)image borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)color
{
    // 图片的宽度和高度
    CGFloat imageWH = image.size.width;
    
    // 设置圆环的宽度
    CGFloat border = borderWidth;
    
    // 圆形的宽度和高度
    CGFloat ovalWH = imageWH + 2 * border;
    
    // 1.开启上下文
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(ovalWH, ovalWH), NO, 0);
    
    // 2.画大圆
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, ovalWH, ovalWH)];
    
    [color set];
    
    [path fill];
    
    // 3.设置裁剪区域
    UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(border, border, imageWH, imageWH)];
    [clipPath addClip];
    
    // 4.绘制图片
    [image drawAtPoint:CGPointMake(border, border)];
    
    // 5.获取图片
    UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
    
    // 6.关闭上下文
    UIGraphicsEndImageContext();
    
    return clipImage;
    
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // 图片裁剪:把正方形图片重新生产一张圆形的图片
    
    // 图片裁剪
    
    UIImage *image = [UIImage imageWithClipImage:[UIImage imageNamed:@"阿狸头像"] borderWidth:1 borderColor:[UIColor redColor]];
    
    _imageView.image = image;
}

屏幕截屏

+ (UIImage *)imageWithCaputureView:(UIView *)view
{
    // 开启位图上下文
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);
    
    // 获取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    // 把控件上的图层渲染到上下文,layer只能渲染,不能绘制
    [view.layer renderInContext:ctx];
    
    // 生成一张图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    
    // 关闭上下文
    UIGraphicsEndImageContext();
    
    return image;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // 生成一张新的图片
    
    UIImage *image =  [UIImage imageWithCaputureView:self.view];
    
    // image转data
    // compressionQuality: 图片质量 1:最高质量
    
     NSData *data = UIImageJPEGRepresentation(image,1);
    
    [data writeToFile:@"/Users/xiaomage/Desktop/view.png" atomically:YES];
    
}

图片截取

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // 给控制器的view添加一个pan手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
    
    [self.view addGestureRecognizer:pan];
}
- (void)pan:(UIPanGestureRecognizer *)pan
{
    CGPoint endA = CGPointZero;
    
    if (pan.state == UIGestureRecognizerStateBegan) { // 一开始拖动的时候
        
        // 获取一开始触摸点
      _startP = [pan locationInView:self.view];
        
    }else if(pan.state == UIGestureRecognizerStateChanged){ // 一直拖动
        // 获取结束点
         endA = [pan locationInView:self.view];
        
        CGFloat w = endA.x - _startP.x;
        CGFloat h = endA.y - _startP.y;
        
        // 获取截取范围
        CGRect clipRect = CGRectMake(_startP.x, _startP.y, w, h);

        // 生成截屏的view
        self.clipView.frame = clipRect;
        
    }else if (pan.state == UIGestureRecognizerStateEnded){

        // 图片裁剪,生成一张新的图片
        
        // 开启上下文
        // 如果不透明,默认超出裁剪区域会变成黑色,通常都是透明
        UIGraphicsBeginImageContextWithOptions(_imageV.bounds.size, NO, 0);
        
        // 使用贝瑟尔路径,设置裁剪区域
       UIBezierPath *path =  [UIBezierPath bezierPathWithRect:_clipView.frame];
        
        [path addClip];
        
        // 获取上下文
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        
        // 把控件上的内容渲染到上下文
        [_imageV.layer renderInContext:ctx];
        
        // 生成一张新的图片
        _imageV.image = UIGraphicsGetImageFromCurrentImageContext();
        
        // 关闭上下文
        UIGraphicsEndImageContext();
        
        // 先移除
        [_clipView removeFromSuperview];
        // 截取的view设置为nil
        _clipView = nil;
        
    }
    
    // 获取手指的偏移量
    // pan translationInView:(UIView *)
}
- (UIView *)clipView{
    if (_clipView == nil) {
        UIView *view = [[UIView alloc] init];
        _clipView = view;
        
        view.backgroundColor = [UIColor blackColor];
        view.alpha = 0.5;
        
        [self.view addSubview:view];
    }
    
    return _clipView;
}

图片擦除

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
    
    [self.view addGestureRecognizer:pan];
}
- (void)pan:(UIPanGestureRecognizer *)pan
{
    // 获取当前点
    CGPoint curP = [pan locationInView:self.view];
    
    // 获取擦除的矩形范围
    CGFloat wh = 100;
    CGFloat x = curP.x - wh * 0.5;
    CGFloat y = curP.y - wh * 0.5;
    
    CGRect rect = CGRectMake(x, y, wh, wh);
    
    // 开启上下文
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    // 控件的layer渲染上去
    [_imageView.layer renderInContext:ctx];
    
    // 擦除图片
    CGContextClearRect(ctx, rect);
    
    // 生成一张图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    
    _imageView.image = image;
    
    // 关闭上下文
    UIGraphicsEndImageContext();

}

手势解锁的界面布局

// 加载完xib的时候调用
- (void)awakeFromNib
{
    // 创建9个按钮
    for ( int i = 0; i < 9; i++) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        
        [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
        
        [btn setImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
        
        [self addSubview:btn];
    }
}
// 为什么要在这个方法布局子控件,因为只要一调用这个方法,就表示父控件的尺寸确定
- (void)layoutSubviews
{
    [super layoutSubviews];
    
    NSUInteger count = self.subviews.count;
    int cols = 3;
    CGFloat x = 0;
    CGFloat y = 0;
    CGFloat w = 74;
    CGFloat h = 74;
    CGFloat margin = (self.bounds.size.width - cols * w) / (cols + 1);
    
    CGFloat col = 0;
    CGFloat row = 0;
    for (NSUInteger i = 0; i < count; i++) {
        UIButton *btn = self.subviews[i];
        // 获取当前按钮的列数
        col = i % cols;
        row = i / cols;
        x = margin + col * (margin + w);
        y = row * (margin + w);
        
        btn.frame = CGRectMake(x, y, w, h);
        
    }
    
}

手势解锁的业务逻辑实现

@property (nonatomic, strong) NSMutableArray *selectedsBtn;

// 重写get方法,对数组进行懒加载
- (NSMutableArray *)selectedsBtn
{
    if (_selectedsBtn == nil) {
        _selectedsBtn = [NSMutableArray array];
    }
    
    return _selectedsBtn;
}
- (IBAction)pan:(UIPanGestureRecognizer *)pan
{
    // 获取触摸点
    _curP = [pan locationInView:self];
    
    // 判断触摸点在不在按钮上
    for (UIButton *btn in self.subviews) {
        // 点在不在某个范围内,并且按钮没有被选中
        if (CGRectContainsPoint(btn.frame, _curP) && btn.selected == NO) {
            // 点在按钮上
            btn.selected = YES;
            
            // 保存到数组中
            [self.selectedsBtn addObject:btn];
            
        }
        
    }
    
    // 重绘
    [self setNeedsDisplay];
    
    
    if (pan.state == UIGestureRecognizerStateEnded) {
        
        // 创建可变字符串
        NSMutableString *strM = [NSMutableString string];
         // 保存输入密码
        for (UIButton *btn in self.selectedsBtn) {
            
            [strM appendFormat:@"%ld",btn.tag];
            
        }
        NSLog(@"%@",strM);
        
        // 还原界面
        
        // 取消所有按钮的选中
        [self.selectedsBtn makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];
        
        // 清除画线,把选中按钮清空
        [self.selectedsBtn removeAllObjects];
    }
    
}
// 只要调用这个方法,就会把之前绘制的东西全部清掉,重新绘制
- (void)drawRect:(CGRect)rect
{
    // 没有选中按钮,不需要连线
    if (self.selectedsBtn.count == 0) return;
    
    // 把所有选中按钮中心点连线
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    NSUInteger count = self.selectedsBtn.count;
    // 把所有选中按钮之间都连好线
    for (int i = 0; i < count; i++) {
        UIButton *btn = self.selectedsBtn[i];
        if (i == 0) {
            // 设置起点
            [path moveToPoint:btn.center];
        }else{
            [path addLineToPoint:btn.center];
        }
        
    }
    
    // 连线到手指的触摸点
    [path addLineToPoint:_curP];
    
    [[UIColor greenColor] set];
    path.lineWidth = 10;
    path.lineJoinStyle = kCGLineJoinRound;
    [path stroke];
    
}

画板

// 绘制图形
// 只要调用drawRect方法就会把之前的内容全部清空
- (void)drawRect:(CGRect)rect
{
    for (DrawPath *path in self.paths) {
        
        if ([path isKindOfClass:[UIImage class]]) {
            // 绘制图片
            UIImage *image = (UIImage *)path;
            
            [image drawInRect:rect];
        }else{
            
            // 画线
            [path.pathColor set];
            
            [path stroke];
        }
        
    }
}
#pragma mark - 选择照片
- (IBAction)pickerPhoto:(id)sender {
    // 弹出系统的相册
    // 选择控制器(系统相册)
    UIImagePickerController *picekerVc = [[UIImagePickerController alloc] init];
    
    // 设置选择控制器的来源
    // UIImagePickerControllerSourceTypePhotoLibrary 相册集
    // UIImagePickerControllerSourceTypeSavedPhotosAlbum:照片库
    picekerVc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
    
    // 设置代理
    picekerVc.delegate = self;
    
    // modal
    [self presentViewController:picekerVc animated:YES completion:nil];
    
}

#pragma mark - UIImagePickerControllerDelegate
// 当用户选择一张图片的时候调用
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // 获取选中的照片
    UIImage *image = info[UIImagePickerControllerOriginalImage];

    // 把选中的照片画到画板上
    
    _drawView.image = image;
    
    // dismiss
    [self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - 保存
- (IBAction)save:(id)sender {
    
    // 截屏
    // 开启上下文
    UIGraphicsBeginImageContextWithOptions(_drawView.bounds.size, NO, 0);
    
    // 获取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    // 渲染图层
    [_drawView.layer renderInContext:ctx];
    
    // 获取上下文中的图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    
    // 关闭上下文
    UIGraphicsEndImageContext();
    
    // 保存画板的内容放入相册
    // image:写入的图片
    // completionTarget图片保存监听者
    // 注意:以后写入相册方法中,想要监听图片有没有保存完成,保存完成的方法不能随意乱写
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    
}

// 监听保存完成,必须实现这个方法
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
     NSLog(@"保存图片成功");
}
上一篇 下一篇

猜你喜欢

热点阅读