iOS 画板、涂鸦

来源:互联网 发布:知乎一句话个人介绍 编辑:程序博客网 时间:2024/05/17 17:14

Demo下载地址:http://download.csdn.net/download/u010981736/9950247

功能:iOS画板涂鸦,支持横竖屏适配,涂鸦的内容可以保存为图片,也可以把已有的图片添加到画板去修改,然后再保存为新的图片到相册。

效果图:

竖屏:
这里写图片描述

横屏:
这里写图片描述

这里写图片描述

核心代码:

界面使用XIB脱线完成的,做了横竖屏的适配;

ViewController文件

////  HandleImageView.h//  画板涂鸦////  Created by llkj on 2017/8/25.//  Copyright © 2017年 LayneCheung. All rights reserved.//#import <UIKit/UIKit.h>@class HandleImageView;@protocol HandleImageViewDelegate <NSObject>- (void)handleImageView:(HandleImageView *)handleImageView newImage:(UIImage *)newImage;@end@interface HandleImageView : UIView@property (nonatomic, weak) UIImage *image;@property (nonatomic, weak) id<HandleImageViewDelegate> delegate;@end
////  ViewController.m//  画板涂鸦////  Created by llkj on 2017/8/24.//  Copyright © 2017年 LayneCheung. All rights reserved.//#import "ViewController.h"#import "DrawView.h"#import "HandleImageView.h"@interface ViewController ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate, HandleImageViewDelegate>@property (weak, nonatomic) IBOutlet DrawView *drawView;@end@implementation ViewController//清屏- (IBAction)clear:(id)sender {    [self.drawView clear];}// 撤销- (IBAction)undo:(id)sender {    [self.drawView undo];}//橡皮擦- (IBAction)eraser:(id)sender {    [self.drawView erase];}//设置线的宽度- (IBAction)setLineWidth:(UISlider *)sender {    [self.drawView setLineWith:sender.value];}//设置线的颜色- (IBAction)setLineColor:(UIButton *)sender {    [self.drawView setLineColor:sender.backgroundColor];}//照片- (IBAction)photo:(id)sender {//    从系统相册中选择图片//    1.弹出相册    UIImagePickerController *vc = [[UIImagePickerController alloc] init];//    设置照片来源    vc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;    vc.delegate = self;//    modal出来相册    [self presentViewController:vc animated:YES completion:nil];}//保存- (IBAction)save:(id)sender {    //生成图片保存到系统相册    //1.绘制上下文    UIGraphicsBeginImageContextWithOptions(self.drawView.bounds.size, NO, 1);    //2.把画板上的内容渲染到上下文中    CGContextRef ref = UIGraphicsGetCurrentContext();    [self.drawView.layer renderInContext:ref];    //3.从上下文中取出一张图片    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();    //4.关闭上下文    UIGraphicsEndImageContext();    //图片写入到系统相册    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);}//当选择某一个照片会调用-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{    UIImage *image = info[UIImagePickerControllerOriginalImage];    HandleImageView *handleImgV = [[HandleImageView alloc] initWithFrame:self.drawView.frame];    handleImgV.backgroundColor = [UIColor clearColor];    handleImgV.delegate = self;    dispatch_async(dispatch_get_main_queue(), ^{        handleImgV.image = image;    });//    handleImgV.image = image;    [self.view addSubview:handleImgV];    [self dismissViewControllerAnimated:YES completion:nil];}- (void)handleImageView:(HandleImageView *)handleImageView newImage:(UIImage *)newImage{    self.drawView.image = newImage;}- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{    NSLog(@"保存成功");}- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.}- (BOOL)prefersStatusBarHidden{    return YES;}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}@end

HandleImageView文件

////  HandleImageView.h//  画板涂鸦////  Created by llkj on 2017/8/25.//  Copyright © 2017年 LayneCheung. All rights reserved.//#import <UIKit/UIKit.h>@class HandleImageView;@protocol HandleImageViewDelegate <NSObject>- (void)handleImageView:(HandleImageView *)handleImageView newImage:(UIImage *)newImage;@end@interface HandleImageView : UIView@property (nonatomic, weak) UIImage *image;@property (nonatomic, weak) id<HandleImageViewDelegate> delegate;@end
////  HandleImageView.m//  画板涂鸦////  Created by llkj on 2017/8/25.//  Copyright © 2017年 LayneCheung. All rights reserved.//#import "HandleImageView.h"@interface HandleImageView ()<UIGestureRecognizerDelegate>@property (nonatomic, strong) UIImageView *imageV;@end@implementation HandleImageView-(UIImageView *)imageV {    if (_imageV == nil) {        UIImageView *imageV = [[UIImageView alloc] init];        imageV.frame = self.bounds;        imageV.userInteractionEnabled = YES;        [self addSubview:imageV];        _imageV = imageV;        //添加手势        [self addGes];    }    return _imageV;}-(void)setImage:(UIImage *)image {    _image = image;    NSLog(@"%@",self.imageV);    self.imageV.image = image;}//添加手势-(void)addGes{    // pan    // 拖拽手势    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]                                   initWithTarget:self action:@selector(pan:)];    [self.imageV addGestureRecognizer:pan];    // pinch    // 捏合    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];    pinch.delegate = self;    [self.imageV addGestureRecognizer:pinch];    //添加旋转    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];    rotation.delegate = self;    [self.imageV addGestureRecognizer:rotation];    // 长按手势    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];    [self.imageV addGestureRecognizer:longPress];}//捏合的时候调用.- (void)pinch:(UIPinchGestureRecognizer *)pinch{    pinch.view.transform = CGAffineTransformScale( pinch.view.transform, pinch.scale, pinch.scale);    // 复位    pinch.scale = 1;}//旋转的时候调用- (void)rotation:(UIRotationGestureRecognizer *)rotation{    // 旋转图片    rotation.view.transform = CGAffineTransformRotate(rotation.view.transform, rotation.rotation);    // 复位,只要想相对于上一次旋转就复位    rotation.rotation = 0;}//长按的时候调用// 什么时候调用:长按的时候调用,而且只要手指不离开,拖动的时候会一直调用,手指抬起的时候也会调用- (void)longPress:(UILongPressGestureRecognizer *)longPress{    if (longPress.state == UIGestureRecognizerStateBegan) {        [UIView animateWithDuration:0.25 animations:^{            //设置为透明            self.imageV.alpha = 0;        }completion:^(BOOL finished) {            [UIView animateWithDuration:0.25 animations:^{                self.imageV.alpha = 1;                //把当前的View做一个截屏                UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);                //获取上下文                CGContextRef ctx = UIGraphicsGetCurrentContext();                [self.layer renderInContext:ctx];                UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();                //关闭上下文.                UIGraphicsEndImageContext();                //调用代理方法                if([self.delegate respondsToSelector:@selector(handleImageView:newImage:)]) {                    [self.delegate handleImageView:self newImage:newImage];                }                //从父控件当中移除                [self removeFromSuperview];            }];        }];    }}//拖动的时候调用- (void)pan:(UIPanGestureRecognizer *)pan{    CGPoint transP = [pan translationInView:pan.view];    pan.view.transform = CGAffineTransformTranslate(pan.view.transform, transP.x, transP.y);    //复位    [pan setTranslation:CGPointZero inView:pan.view];}//能够同时支持多个手势-(BOOL)gestureRecognizer:(nonnull UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(nonnull UIGestureRecognizer *)otherGestureRecognizer{    return YES;}@end

DrawView文件

////  DrawView.h//  画板涂鸦////  Created by llkj on 2017/8/24.//  Copyright © 2017年 LayneCheung. All rights reserved.//#import <UIKit/UIKit.h>@interface DrawView : UIView//清屏- (void)clear;//撤销- (void)undo;//橡皮擦- (void)erase;//设置线的宽度- (void)setLineWith:(CGFloat)lineWidth;//设置线的颜色- (void)setLineColor:(UIColor *)color;/** 要绘制的图片 */@property (nonatomic, strong) UIImage * image;@end
////  DrawView.m//  画板涂鸦////  Created by llkj on 2017/8/24.//  Copyright © 2017年 LayneCheung. All rights reserved.//#import "DrawView.h"#import "MyBezierPath.h"@interface DrawView()/** 当前绘制的路径 */@property (nonatomic, strong) UIBezierPath *path;//保存当前绘制的所有路径@property (nonatomic, strong) NSMutableArray *allPathArray;//当前路径的线宽@property (nonatomic, assign) CGFloat width;//当前路径的颜色@property (nonatomic, strong) UIColor *color;@end@implementation DrawView- (NSMutableArray *)allPathArray {    if (_allPathArray == nil) {        _allPathArray = [NSMutableArray array];    }    return _allPathArray;}- (void)awakeFromNib {    [super awakeFromNib];    //添加手势    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];    [self addGestureRecognizer:pan];    self.width = 1;    self.color = [UIColor blackColor];}-(void)setImage:(UIImage *)image {    _image = image;    //添加图片添加到数组当中    [self.allPathArray addObject:image];    //重绘    [self setNeedsDisplay];}//清屏- (void)clear {    //清空所有的路径    [self.allPathArray removeAllObjects];    //重绘    [self setNeedsDisplay];}//撤销- (void)undo {    //删除最后一个路径    [self.allPathArray removeLastObject];    //重绘    [self setNeedsDisplay];}//橡皮擦- (void)erase {    [self setLineColor:[UIColor whiteColor]];}//设置线的宽度- (void)setLineWith:(CGFloat)lineWidth {    self.width = lineWidth;}//设置线的颜色- (void)setLineColor:(UIColor *)color {    self.color = color;}- (void)pan:(UIPanGestureRecognizer *)pan {    //获取的当前手指的点    CGPoint curP = [pan locationInView:self];    //判断手势的状态    if(pan.state == UIGestureRecognizerStateBegan) {        //创建路径        //UIBezierPath *path = [UIBezierPath bezierPath];        MyBezierPath *path = [[MyBezierPath alloc] init];        self.path = path;        //设置起点        [path moveToPoint:curP];        //设置线的宽度        [path setLineWidth:self.width];        //设置线的颜色        //什么情况下自定义类:当发现系统原始的功能,没有办法瞒足自己需求时,这个时候,要自定义类.继承系统原来的东西.再去添加属性自己的东西.        path.color = self.color;        [self.allPathArray addObject:path];    } else if(pan.state == UIGestureRecognizerStateChanged) {        //绘制一根线到当前手指所在的点        [self.path addLineToPoint:curP];        //重绘        [self setNeedsDisplay];    }}-(void)drawRect:(CGRect)rect {    //绘制保存的所有路径    for (MyBezierPath *path in self.allPathArray) {        //判断取出的路径真实类型        if([path isKindOfClass:[UIImage class]]) {            UIImage *image = (UIImage *)path;            [image drawInRect:rect];        }else {            [path.color set];            [path stroke];        }    }}@end

MyBezierPath文件

////  MyBezierPath.h//  画板涂鸦////  Created by llkj on 2017/8/24.//  Copyright © 2017年 LayneCheung. All rights reserved.//#import <UIKit/UIKit.h>@interface MyBezierPath : UIBezierPath//当前路径的颜色@property (nonatomic, strong) UIColor *color;@end
#import "MyBezierPath.h"@implementation MyBezierPath@end
原创粉丝点击