Quartz2D复习(三) --- 涂鸦

和上一篇手势解锁不一样,手势解锁只画了一条路径,从触摸开始--》触摸移动--》触摸结束 ,然后路径完成了,渲染出来就是手势解锁了;

这次涂鸦想做到的效果是可以画很多次线段或弧,每次又可以设置不同的宽度和颜色,然后还要有撤销、清屏、橡皮擦的功能,那就需要画很多条路径了,然后每条路径有自己的颜色和宽度,那么

UIBezierPath类也实现不了,需要自定义一个类,继承自UIBezierPath,然后再增加自己的颜色和宽度属性。

效果截图:

Quartz2D复习(三) --- 涂鸦  涂鸦了 Quartz2D复习(三) --- 涂鸦  橡皮擦擦除 Quartz2D复习(三) --- 涂鸦 

保存到相册Quartz2D复习(三) --- 涂鸦

 

代码:

1、自定义PaintingBezierPath类继承自UIBezierPath类,增加一个自定义路径颜色的属性;自定义构造函数,设置颜色和路径宽度

PaintingBezierPath.h文件代码:

#import <UIKit/UIKit.h>



@interface PaintingBezierPath : UIBezierPath



@property (nonatomic, retain) UIColor *color; //线段的颜色



- (instancetype)initWithColor: (UIColor *)color WithWidth: (CGFloat)width WithStartPoint: (CGPoint)startPoint;



@end

PaintingBezierPath.m文件代码:

Quartz2D复习(三) --- 涂鸦
 1 //

 2 //  PaintingBezierPath.m

 3 //  tan_iosTwo

 4 //

 5 //  Created by xiaom on 15/7/22.

 6 //

 7 //  为了自定义每个轨迹的宽度和颜色,需要增加一个自定义方法

 8 

 9 #import "PaintingBezierPath.h"

10 

11 @implementation PaintingBezierPath

12 

13 - (instancetype)initWithColor:(UIColor *)color WithWidth:(CGFloat)width WithStartPoint:(CGPoint)startPoint{

14     if (self = [super init]){

15         self.color = color;

16         self.lineWidth = width;

17         self.lineJoinStyle = kCGLineJoinRound;

18         self.lineCapStyle = kCGLineCapRound;

19         [self moveToPoint:startPoint];

20     }

21     return self;

22 }

23 

24 @end
View Code

 

2、自定义view, 用来展示涂鸦,名称为:PaintingView

PaintingView.h文件代码:

#import <UIKit/UIKit.h>



@interface PaintingView : UIView



@property (nonatomic, assign) CGFloat lineWidth; //涂鸦的线段宽度

@property (nonatomic, strong) UIColor *lineColor; //涂鸦的线段颜色



- (void)cancelPainting; //撤销涂鸦

- (void)clearScreen; //清屏

- (void)saveImgToAlbum; //保存相片到到手机相册里



@end

PaintingView.m文件代码:

Quartz2D复习(三) --- 涂鸦
  1 //  绘画, 涂鸦

  2 

  3 #import "PaintingView.h"

  4 #import "PaintingBezierPath.h"

  5 

  6 @interface PaintingView()

  7 

  8 @property (nonatomic, retain) NSMutableArray *paths; //涂鸦路径数组

  9 @property (nonatomic, retain) PaintingBezierPath *currentPath; //当前正在绘制的path

 10 

 11 @end

 12 

 13 @implementation PaintingView

 14 

 15 //代码创建对象会调用: 使用

 16 - (instancetype)initWithFrame:(CGRect)frame{

 17     if (self = [super initWithFrame:frame]){

 18         //NSLog(@"frame...%s", __func__);

 19     }

 20     return self;

 21 }

 22 

 23 //xib创建会调用

 24 - (instancetype)initWithCoder:(NSCoder *)aDecoder{

 25     if (self = [super initWithCoder:aDecoder]){

 26         //NSLog(@"coder.. %s", __func__);

 27     }

 28     return self;

 29 }

 30 

 31 //监听触摸开始 ,方法继承自UIResponder

 32 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

 33     PaintingBezierPath *path = [[PaintingBezierPath alloc] initWithColor:self.lineColor WithWidth:self.lineWidth WithStartPoint:[self currentPoint:touches]];

 34     

 35     [self.paths addObject:path]; //将路径记录到数组中

 36     self.currentPath = path;

 37     

 38     [self setNeedsDisplay];  //调用方法,重新绘制

 39 }

 40 

 41 //监听触摸移动中

 42 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

 43     //追踪每次路径的移动过程

 44     [self.currentPath addLineToPoint:[self currentPoint:touches]];

 45     

 46     [self setNeedsDisplay]; //调用方法,重新绘制

 47 }

 48 

 49 //获取view对象中的当前位置

 50 - (CGPoint)currentPoint: (NSSet *)touches{

 51     UITouch *touch = [touches anyObject];

 52     return [touch locationInView:self];

 53 }

 54 

 55 //次方法是UIView的分类@interface UIView(UIViewRendering)中添加的方法

 56 //setNeedsDisplay方法也是此分类中的方法

 57 - (void)drawRect:(CGRect)rect{

 58     for (int i = 0; i < self.paths.count; i++) {

 59         PaintingBezierPath *path = [self.paths objectAtIndex:i];

 60         [path.color set];

 61         [path stroke];  //渲染

 62     }

 63 }

 64 

 65 #pragma mark - 自定义方法实现

 66 //撤销

 67 - (void)cancelPainting{

 68     [self.paths removeLastObject]; //移除最后一个路径对象

 69     [self setNeedsDisplay]; //重新绘制

 70 }

 71 

 72 //清屏

 73 - (void)clearScreen{

 74     [self.paths removeAllObjects]; //移除所有路径

 75     self.lineColor = nil; //颜色赋空

 76     [self setNeedsDisplay]; //重新绘制

 77 }

 78 

 79 //保存图片到相册

 80 - (void)saveImgToAlbum{

 81     //1、开启图形上下文

 82     UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);

 83     //2、获取当前上下文

 84     CGContextRef ctr = UIGraphicsGetCurrentContext();

 85     //3、渲染当前View的图层到上下文中

 86     [self.layer renderInContext:ctr];

 87     //4、获取新图片

 88     UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();

 89     //5、关闭图形上下文

 90     UIGraphicsEndImageContext();

 91     //6、保存图片到相册中

 92     UIImageWriteToSavedPhotosAlbum(newImg, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

 93 }

 94 

 95 //保存图片到相册完成之后的处理

 96 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{

 97     UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(60, 150, 200, 100)];

 98     [lbl setBackgroundColor:[UIColor blackColor]];

 99     lbl.textAlignment = NSTextAlignmentCenter;

100     lbl.textColor = [UIColor yellowColor];

101     

102     if (error){ //保存失败

103         lbl.text = @"保存失败";

104     }

105     else{ //保存成功

106         lbl.text = @"保存成功";

107     }

108     [self addSubview:lbl];

109     

110     [UIView animateWithDuration:2.0 animations:^{

111         lbl.alpha = 0.1;

112     } completion:^(BOOL finished) {

113         [lbl removeFromSuperview];

114     }];

115 }

116 

117 //设置对象默认属性值

118 - (CGFloat)lineWidth{

119     if (_lineWidth < 1){

120         _lineWidth = 1;

121     }

122     return _lineWidth;

123 }

124 

125 - (UIColor *)lineColor{

126     if (_lineColor == nil){

127         _lineColor = [UIColor blackColor];

128     }

129     return _lineColor;

130 }

131 

132 - (NSMutableArray *)paths{

133     if (_paths == nil){

134         _paths = [[NSMutableArray alloc] init];

135     }

136     return _paths;

137 }

138 

139 /*

140 // Only override drawRect: if you perform custom drawing.

141 // An empty implementation adversely affects performance during animation.

142 - (void)drawRect:(CGRect)rect {

143     // Drawing code

144 }

145 */

146 

147 @end
View Code

3、自定义控制器展示PaintingView

DoodleViewController.h文件:

#import <UIKit/UIKit.h>



@interface DoodleViewController : UIViewController



@end

DoodleViewController.m

Quartz2D复习(三) --- 涂鸦
  1 //  信手涂鸦

  2 

  3 #import "DoodleViewController.h"

  4 #import "PaintingView.h"

  5 

  6 @interface DoodleViewController ()

  7 

  8 @property (nonatomic, retain) PaintingView *paintV; //涂鸦的画板

  9 

 10 @end

 11 

 12 @implementation DoodleViewController

 13 

 14 - (void)viewDidLoad {

 15     [super viewDidLoad];

 16     // Do any additional setup after loading the view.

 17     [self.view setBackgroundColor:[UIColor whiteColor]];

 18     

 19     //自定义View涂鸦

 20     PaintingView *v = [[PaintingView alloc] initWithFrame:CGRectMake(0, 80, 320, 450)];

 21     [v setBackgroundColor:[UIColor grayColor]];

 22     [v setAlpha:0.6];

 23     [self.view addSubview:v];

 24     self.paintV = v;

 25     

 26     [self addReturnBtn];    //添加返回按钮

 27     [self addDoodleSetWidthAndColor]; //增加设置涂鸦的宽度和颜色设置

 28 }

 29 

 30 //添加返回按钮

 31 - (void)addReturnBtn{

 32     UIButton *returnBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 20, 50, 30)];

 33     [returnBtn setTitle:@"返回" forState:UIControlStateNormal];

 34     [returnBtn addTarget:self action:@selector(returnPrePage) forControlEvents:UIControlEventTouchUpInside];

 35     [returnBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

 36     [self.view addSubview:returnBtn];

 37 }

 38 

 39 //添加涂鸦宽度设置和颜色设置

 40 - (void)addDoodleSetWidthAndColor{

 41     //1、增加UISlider用来设置可调节宽度

 42     UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(50, 20, 80, 30)];

 43     slider.maximumValue = 15.0f; //最大值

 44     slider.value = 3.0f;    //默认为1

 45     self.paintV.lineWidth = slider.value;

 46     [slider addTarget:self action:@selector(setLineWidth:) forControlEvents:UIControlEventValueChanged]; //绑定值改变事件

 47     [self.view addSubview:slider];

 48     

 49     //2、添加颜色选择按钮

 50     NSArray *colors = @[[UIColor redColor], [UIColor yellowColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor], [UIColor brownColor]];

 51     for (int i = 0; i < colors.count; i++) {

 52         CGFloat x =  140 + 30 * i;

 53         UIButton *colorBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, 25, 20, 20)];

 54         [colorBtn setBackgroundColor:[colors objectAtIndex:i]];

 55         [colorBtn addTarget:self action:@selector(setLineColor:) forControlEvents:UIControlEventTouchUpInside];

 56         [self.view addSubview:colorBtn];

 57     }

 58     

 59    

 60     //第二行

 61     //3、添加撤销按钮

 62     UIButton *cancelBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 55, 60, 25)];

 63     [cancelBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

 64     [cancelBtn setTitle:@"撤销" forState:UIControlStateNormal];

 65     [cancelBtn addTarget:self action:@selector(cancelPainting) forControlEvents:UIControlEventTouchUpInside];

 66     [self.view addSubview:cancelBtn];

 67     

 68     //4、清屏按钮

 69     UIButton *clearScreenBtn = [[UIButton alloc] initWithFrame:CGRectMake(70, 55, 60, 25)];

 70     [clearScreenBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

 71     [clearScreenBtn setTitle:@"清屏" forState:UIControlStateNormal];

 72     [clearScreenBtn addTarget:self action:@selector(clearScreen) forControlEvents:UIControlEventTouchUpInside];

 73     [self.view addSubview:clearScreenBtn];

 74     

 75     //5、添加一个橡皮擦

 76     UIButton *brushBtn = [[UIButton alloc] initWithFrame:CGRectMake(140, 55, 60, 25)];

 77     [brushBtn setTitle:@"橡皮擦" forState:UIControlStateNormal];

 78     [brushBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

 79     [brushBtn addTarget:self action:@selector(brush) forControlEvents:UIControlEventTouchUpInside];

 80     [self.view addSubview:brushBtn];

 81     

 82     //6、保存到相册按钮

 83     UIButton *saveBtn = [[UIButton alloc] initWithFrame:CGRectMake(210, 55, 100, 25)];

 84     [saveBtn setTitle:@"保存到相册" forState:UIControlStateNormal];

 85     [saveBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

 86     [saveBtn addTarget:self action:@selector(saveImgToAlbum) forControlEvents:UIControlEventTouchUpInside];

 87     [self.view addSubview:saveBtn];

 88 }

 89 

 90 //调节宽度

 91 - (void)setLineWidth:(UISlider *)sender{

 92     [self.paintV setLineWidth:sender.value];

 93 }

 94 

 95 //调节颜色

 96 - (void)setLineColor: (UIButton *)sender{

 97     [self.paintV setLineColor:sender.backgroundColor];

 98 }

 99 

100 //设置橡皮擦

101 - (void)brush{

102     self.paintV.lineColor = self.paintV.backgroundColor;

103     if (self.paintV.lineWidth < 5) self.paintV.lineWidth = 5;

104 }

105 //撤销

106 - (void)cancelPainting{

107     [self.paintV cancelPainting];

108 }

109 //清屏

110 - (void)clearScreen{

111     [self.paintV clearScreen];

112 }

113 

114 //保存图片到相册

115 - (void)saveImgToAlbum{

116     [self.paintV saveImgToAlbum];

117 }

118 

119 //返回上一页

120 - (void)returnPrePage{

121     [self dismissViewControllerAnimated:YES completion:nil];

122 }

123 

124 - (void)didReceiveMemoryWarning {

125     [super didReceiveMemoryWarning];

126     // Dispose of any resources that can be recreated.

127 }

128 

129 /*

130 #pragma mark - Navigation

131 

132 // In a storyboard-based application, you will often want to do a little preparation before navigation

133 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

134     // Get the new view controller using [segue destinationViewController].

135     // Pass the selected object to the new view controller.

136 }

137 */

138 

139 @end
View Code

 

 

你可能感兴趣的:(quartz)