首页 > 代码库 > 源码0308-画板

源码0308-画板

 

////  DrawView.m//  08-画板#import "DrawView.h"@interface DrawView ()@property (nonatomic, strong) UIBezierPath *path;@property (nonatomic, strong) NSMutableArray *paths;@end@implementation DrawView- (NSMutableArray *)paths{    if (_paths == nil) {        _paths = [NSMutableArray array];    }    return _paths;}// 仅仅是加载xib的时候调用- (void)awakeFromNib{    [self setUp];}- (instancetype)initWithFrame:(CGRect)frame{    if (self = [super initWithFrame:frame]) {        [self setUp];    }    return self;}// 初始化设置- (void)setUp{    // 添加pan手势    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];        [self addGestureRecognizer:pan];}// 当手指拖动的时候调用- (void)pan:(UIPanGestureRecognizer *)pan{        // 获取当前手指触摸点   CGPoint curP = [pan locationInView:self];        // 获取开始点    if (pan.state == UIGestureRecognizerStateBegan) {        // 创建贝瑟尔路径      _path = [UIBezierPath bezierPath];                // 设置路径的起点        [_path moveToPoint:curP];                // 保存描述好的路径        [self.paths addObject:_path];            }        // 手指一直在拖动    // 添加线到当前触摸点    [_path addLineToPoint:curP];        // 重绘    [self setNeedsDisplay];    }// 绘制图形// 只要调用drawRect方法就会把之前的内容全部清空- (void)drawRect:(CGRect)rect{    for (UIBezierPath *path in self.paths) {        [path stroke];    }}@end

09-画板(小功能)

技术分享

 

//  ViewController.m//  08-画板#import "ViewController.h"#import "DrawView.h"@interface ViewController ()<UINavigationControllerDelegate,UIImagePickerControllerDelegate>@property (weak, nonatomic) IBOutlet DrawView *drawView;@end@implementation ViewController#pragma mark - 清屏- (IBAction)clear:(id)sender {    [_drawView clear];}#pragma mark - 撤销- (IBAction)undo:(id)sender {    [_drawView undo];}#pragma mark - 橡皮擦- (IBAction)eraser:(id)sender {    _drawView.pathColor = [UIColor whiteColor];}#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(@"保存图片成功");}- (void)savePhoto{   }- (IBAction)colorChange:(UIButton *)sender {        // 给画板传递颜色    _drawView.pathColor = sender.backgroundColor;    }- (IBAction)valueChange:(UISlider *)sender {        // 给画板传递线宽    _drawView.lineWidth = sender.value;    }- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}@end

 

 

////  DrawView.h//  08-画板#import <UIKit/UIKit.h>@interface DrawView : UIView@property (nonatomic, strong) UIColor *pathColor;@property (nonatomic, assign) NSInteger lineWidth;@property (nonatomic, strong) UIImage *image;// 清屏- (void)clear;// 撤销- (void)undo;@end
////  DrawView.m//  08-画板#import "DrawView.h"#import "DrawPath.h"@interface DrawView ()@property (nonatomic, strong) DrawPath *path;@property (nonatomic, strong) NSMutableArray *paths;@end@implementation DrawView- (void)setImage:(UIImage *)image{    _image = image;        [self.paths addObject:_image];        // 重绘    [self setNeedsDisplay];}- (void)clear{    [self.paths removeAllObjects];        [self setNeedsDisplay];}- (void)undo{    [self.paths removeLastObject];        [self setNeedsDisplay];}- (NSMutableArray *)paths{    if (_paths == nil) {        _paths = [NSMutableArray array];    }    return _paths;}// 仅仅是加载xib的时候调用- (void)awakeFromNib{    [self setUp];}- (instancetype)initWithFrame:(CGRect)frame{    if (self = [super initWithFrame:frame]) {        [self setUp];    }    return self;}// 初始化设置- (void)setUp{    // 添加pan手势    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];        [self addGestureRecognizer:pan];        _lineWidth = 1;    _pathColor = [UIColor blackColor];}// 当手指拖动的时候调用- (void)pan:(UIPanGestureRecognizer *)pan{        // 获取当前手指触摸点   CGPoint curP = [pan locationInView:self];        // 获取开始点    if (pan.state == UIGestureRecognizerStateBegan) {        // 创建贝瑟尔路径      _path = [[DrawPath alloc] init];                // 设置线宽        _path.lineWidth = _lineWidth;                // 给路径设置颜色        _path.pathColor = _pathColor;                // 设置路径的起点        [_path moveToPoint:curP];                // 保存描述好的路径        [self.paths addObject:_path];            }        // 手指一直在拖动    // 添加线到当前触摸点    [_path addLineToPoint:curP];        // 重绘    [self setNeedsDisplay];    }// 绘制图形// 只要调用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];        }            }}@end

 

////  DrawPath.h//  08-画板#import <UIKit/UIKit.h>@interface DrawPath : UIBezierPath@property (nonatomic, strong) UIColor *pathColor;@end
////  DrawPath.m//  08-画板#import "DrawPath.h"@implementation DrawPath@end

 01-画板(图片处理)

 

////  ViewController.m//  08-画板#import "ViewController.h"#import "ImageHandleView.h"#import "DrawView.h"@interface ViewController ()<UINavigationControllerDelegate,UIImagePickerControllerDelegate>@property (weak, nonatomic) IBOutlet DrawView *drawView;@end@implementation ViewController#pragma mark - 清屏- (IBAction)clear:(id)sender {    [_drawView clear];}#pragma mark - 撤销- (IBAction)undo:(id)sender {    [_drawView undo];}#pragma mark - 橡皮擦- (IBAction)eraser:(id)sender {    _drawView.pathColor = [UIColor whiteColor];}#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];        // 创建一个图片处理的View    ImageHandleView *imageHandleV = [[ImageHandleView alloc] initWithFrame:self.drawView.bounds];    imageHandleV.handleCompletionBlock = ^(UIImage *image){        self.drawView.image = image;    };    imageHandleV.handleBeginBlock = ^{              self.drawView.userInteractionEnabled = NO;    };        [self.drawView addSubview:imageHandleV];        // 做图片的处理    imageHandleV.image = image;    //    // 把选中的照片画到画板上//    _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(@"保存图片成功");}- (IBAction)colorChange:(UIButton *)sender {        // 给画板传递颜色    _drawView.pathColor = sender.backgroundColor;    }- (IBAction)valueChange:(UISlider *)sender {        // 给画板传递线宽    _drawView.lineWidth = sender.value;    }- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}@end

 

////  DrawView.h//  08-画板#import <UIKit/UIKit.h>@interface DrawView : UIView@property (nonatomic, strong) UIColor *pathColor;@property (nonatomic, assign) NSInteger lineWidth;@property (nonatomic, strong) UIImage *image;// 清屏- (void)clear;// 撤销- (void)undo;@end
////  DrawView.m//  08-画板#import "DrawView.h"#import "DrawPath.h"@interface DrawView ()@property (nonatomic, strong) DrawPath *path;@property (nonatomic, strong) NSMutableArray *paths;@end@implementation DrawView- (void)setImage:(UIImage *)image{    _image = image;        [self.paths addObject:_image];        // 重绘    [self setNeedsDisplay];}- (void)clear{    [self.paths removeAllObjects];        [self setNeedsDisplay];}- (void)undo{    [self.paths removeLastObject];        [self setNeedsDisplay];}- (NSMutableArray *)paths{    if (_paths == nil) {        _paths = [NSMutableArray array];    }    return _paths;}// 仅仅是加载xib的时候调用- (void)awakeFromNib{    [self setUp];}- (instancetype)initWithFrame:(CGRect)frame{    if (self = [super initWithFrame:frame]) {        [self setUp];    }    return self;}// 初始化设置- (void)setUp{    // 添加pan手势    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];        [self addGestureRecognizer:pan];        _lineWidth = 1;    _pathColor = [UIColor blackColor];}// 当手指拖动的时候调用- (void)pan:(UIPanGestureRecognizer *)pan{        // 获取当前手指触摸点   CGPoint curP = [pan locationInView:self];        // 获取开始点    if (pan.state == UIGestureRecognizerStateBegan) {        // 创建贝瑟尔路径      _path = [[DrawPath alloc] init];                // 设置线宽        _path.lineWidth = _lineWidth;                // 给路径设置颜色        _path.pathColor = _pathColor;                // 设置路径的起点        [_path moveToPoint:curP];                // 保存描述好的路径        [self.paths addObject:_path];            }        // 手指一直在拖动    // 添加线到当前触摸点    [_path addLineToPoint:curP];        // 重绘    [self setNeedsDisplay];    }// 绘制图形// 只要调用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];        }            }}@end

 

////  DrawPath.h//  08-画板#import <UIKit/UIKit.h>@interface DrawPath : UIBezierPath@property (nonatomic, strong) UIColor *pathColor;@end
////  DrawPath.m//  08-画板#import "DrawPath.h"@implementation DrawPath@end

 

////  ImageHandleView.h//  08-画板#import <UIKit/UIKit.h>@interface ImageHandleView : UIView@property (nonatomic, strong) UIImage *image;@property (nonatomic, strong) void(^handleCompletionBlock)(UIImage *image);@property (nonatomic, strong) void(^handleBeginBlock)();@end
////  ImageHandleView.m//  08-画板#import "ImageHandleView.h"@interface ImageHandleView ()<UIGestureRecognizerDelegate>@property (nonatomic, weak) UIImageView *imageV;@end@implementation ImageHandleView- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{    // 如果点在UIImageView,    return self.imageV;}- (UIImageView *)imageV{    if (_imageV == nil) {                UIImageView *imageV = [[UIImageView alloc] initWithFrame:self.bounds];                imageV.userInteractionEnabled = YES;                _imageV = imageV;        // 添加手势        [self setUpGestureRecognizer];                [self addSubview:imageV];            }        return _imageV;}#pragma mark - 添加手势- (void)setUpGestureRecognizer{        // 平移    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];    [_imageV addGestureRecognizer:pan];        // 旋转    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];    rotation.delegate = self;    [_imageV addGestureRecognizer:rotation];        // 缩放    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];    pinch.delegate = self;    [_imageV addGestureRecognizer:pinch];        // 长按    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];    [_imageV addGestureRecognizer:longPress];}- (void)pan:(UIPanGestureRecognizer *)pan{    // 获取手指的偏移量   CGPoint transP = [pan translationInView:self.imageV];        // 设置UIImageView的形变    self.imageV.transform = CGAffineTransformTranslate(self.imageV.transform, transP.x, transP.y);        // 复位:只要想要相对于上一次就必须复位    [pan setTranslation:CGPointZero inView:self.imageV];}- (void)rotation:(UIRotationGestureRecognizer *)rotation{    self.imageV.transform = CGAffineTransformRotate(self.imageV.transform, rotation.rotation);        rotation.rotation = 0;}- (void)pinch:(UIPinchGestureRecognizer *)pinch{    self.imageV.transform = CGAffineTransformScale(self.imageV.transform, pinch.scale, pinch.scale);        pinch.scale = 1;}- (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;            } completion:^(BOOL finished) {               // 高亮完成的时候                                // 把处理的图片生成一张新的图片,截屏                                // 开启位图上下文                UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);                                // 获取位图上下文                CGContextRef ctx = UIGraphicsGetCurrentContext();                                // 把控件的图层渲染到上下文                [self.layer renderInContext:ctx];                                // 获取图片                UIImage *image = UIGraphicsGetImageFromCurrentImageContext();                                // 关闭上下文                UIGraphicsEndImageContext();                                // 调用Block                if (_handleCompletionBlock) {                    _handleCompletionBlock(image);                }                                // 移除父控件                [self removeFromSuperview];                            }];                    }];    }}- (void)setImage:(UIImage *)image{    _image = image;        // 展示UIImageView    self.imageV.image = image;}#pragma mark - 手势代理方法// 是否同时支持多个手势- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{    return YES;}@end

 

02-画板(图片处理bug)

 

////  ImageHandleView.m//  08-画板#import "ImageHandleView.h"@interface ImageHandleView ()<UIGestureRecognizerDelegate>@property (nonatomic, weak) UIImageView *imageV;@end@implementation ImageHandleView//- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{//        NSLog(@"%s",__func__);//}//- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event//{//    // 如果点在UIImageView,//    return self.imageV;//}- (UIImageView *)imageV{    if (_imageV == nil) {                UIImageView *imageV = [[UIImageView alloc] initWithFrame:self.bounds];                imageV.userInteractionEnabled = YES;                _imageV = imageV;        // 添加手势        [self setUpGestureRecognizer];                [self addSubview:imageV];            }        return _imageV;}#pragma mark - 拦截拖动手势- (void)panHandle{    NSLog(@"%s",__func__);}#pragma mark - 添加手势- (void)setUpGestureRecognizer{       // 添加拖动手势给ImageHandleView    UIPanGestureRecognizer *panHandle = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panHandle)];    [self addGestureRecognizer:panHandle];        // 平移    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];    [_imageV addGestureRecognizer:pan];        // 旋转    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];    rotation.delegate = self;    [_imageV addGestureRecognizer:rotation];        // 缩放    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];    pinch.delegate = self;    [_imageV addGestureRecognizer:pinch];        // 长按    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];    [_imageV addGestureRecognizer:longPress];}- (void)pan:(UIPanGestureRecognizer *)pan{    // 获取手指的偏移量   CGPoint transP = [pan translationInView:self.imageV];        // 设置UIImageView的形变    self.imageV.transform = CGAffineTransformTranslate(self.imageV.transform, transP.x, transP.y);        // 复位:只要想要相对于上一次就必须复位    [pan setTranslation:CGPointZero inView:self.imageV];}- (void)rotation:(UIRotationGestureRecognizer *)rotation{    self.imageV.transform = CGAffineTransformRotate(self.imageV.transform, rotation.rotation);        rotation.rotation = 0;}- (void)pinch:(UIPinchGestureRecognizer *)pinch{    self.imageV.transform = CGAffineTransformScale(self.imageV.transform, pinch.scale, pinch.scale);        pinch.scale = 1;}- (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;            } completion:^(BOOL finished) {               // 高亮完成的时候                                // 把处理的图片生成一张新的图片,截屏                                // 开启位图上下文                UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);                                // 获取位图上下文                CGContextRef ctx = UIGraphicsGetCurrentContext();                                // 把控件的图层渲染到上下文                [self.layer renderInContext:ctx];                                // 获取图片                UIImage *image = UIGraphicsGetImageFromCurrentImageContext();                                // 关闭上下文                UIGraphicsEndImageContext();                                // 调用Block                if (_handleCompletionBlock) {                    _handleCompletionBlock(image);                }                                // 移除父控件                [self removeFromSuperview];                            }];                    }];    }}- (void)setImage:(UIImage *)image{    _image = image;        // 展示UIImageView    self.imageV.image = image;}#pragma mark - 手势代理方法// 是否同时支持多个手势- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{    return YES;}@end

 

源码0308-画板