1.把一条条路径当成model,有线宽,颜色,存进数组,画到视图上,
PathModel.h
// line --- model
//颜色\路径\宽度
@interface PathModel : NSObject
@property (nonatomic, assign) CGMutablePathRef path;
@property (nonatomic, strong) UIColor *color;
@property (nonatomic, assign) CGFloat width;
- (void)dealloc
{
//释放路径
CGPathRelease(_path);
}
- (void)setPath:(CGMutablePathRef)path
{
if (_path != path) {
CGPathRelease(_path);
_path = (CGMutablePathRef)CGPathRetain(path);
}
}
2.自定义Button(UIControl 画)
ToolButton.h
#import <UIKit/UIKit.h>
//定义button的类型
typedef enum : NSUInteger{
kToolButtonTitleType,
kToolButtonColorType,
kToolButtonWidthType,
kToolButtonNoneType
} kToolButtonType;
@interface ToolButton : UIControl
//是否选中
@property (nonatomic, assign) BOOL checked;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, strong) UIColor *color;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) kToolButtonType type;
@end
#import "ToolButton.h"
@implementation ToolButton
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
if (self.type == kToolButtonTitleType || self.type == kToolButtonWidthType) {
//绘制标题
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
style.alignment = NSTextAlignmentCenter;
NSDictionary *attr = @{
NSFontAttributeName: [UIFont boldSystemFontOfSize:20],
NSParagraphStyleAttributeName : style
};
[self.title drawInRect:rect withAttributes:attr];
} else if (self.type == kToolButtonColorType) {
//画内切圆
CGContextAddEllipseInRect(context, rect);
//CGContextSetFillColorWithColor(context, self.color.CGColor);
[self.color setFill];
CGContextDrawPath(context, kCGPathFill);
}
//绘制选中效果
if (self.checked) {
[[UIColor blackColor] set];
UIRectFrame(rect);
}
}
- (void)setChecked:(BOOL)checked
{
_checked = checked;
[self setNeedsDisplay];
}
@end
3.工具栏#import <UIKit/UIKit.h>
//block类型
typedef void(^ChangeColorBlock)(UIColor *);
typedef void(^ChangeWidthBlock)(CGFloat);
typedef void(^ChangeBlock)(void);
@class ToolButton;
@interface ToolView : UIView
{
UIView *_buttonView; //菜单栏
UIView *_colorView; //颜色
UIView *_widthView; //线宽
//声明block
ChangeColorBlock _colorBlock;
ChangeWidthBlock _widthBlock;
ChangeBlock _eraseBlock;
ChangeBlock _undoBlock;
ChangeBlock _clearBlock;
}
@property (nonatomic, strong) ToolButton *lastButton;
@property (nonatomic, strong) ToolButton *lastColor;
@property (nonatomic, strong) ToolButton *lastWidth;
@property (nonatomic, copy) ChangeColorBlock colorBlock;
@property (nonatomic, copy) ChangeWidthBlock widthBlock;
- (void)addErase:(ChangeBlock)eraseBlock undo:(ChangeBlock)undoBlock clear:(ChangeBlock)clearBlock;
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self createMenuView];
[self creatColorView];
[self createLineWidthView];
}
return self;
}
#pragma mark - 创建子视图
//菜单栏
- (void)createMenuView
{
//菜单栏的父视图
_buttonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), 25)];
_buttonView.backgroundColor = [UIColor clearColor];
[self addSubview:_buttonView];
NSArray *titles = @[@"颜色", @"线宽", @"橡皮", @"撤销", @"清屏"];
CGFloat width = CGRectGetWidth(self.bounds) / titles.count;
//创建5个按钮
for (int i = 0; i < titles.count; i++) {
ToolButton *button = [[ToolButton alloc] initWithFrame:CGRectMake(i * width, 0, width, 25)];
//指定button为title类型
button.type = kToolButtonTitleType;
button.title = titles[i];
button.backgroundColor = [UIColor clearColor];
button.tag = 100 + i;
[button addTarget:self
action:@selector(buttonAction:)
forControlEvents:UIControlEventTouchUpInside];
[_buttonView addSubview:button];
}
}
//颜色栏
- (void)creatColorView
{
_colorView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_buttonView.frame), CGRectGetWidth(self.bounds), 40)];
_colorView.backgroundColor = [UIColor clearColor];
_colorView.hidden = YES;
[self addSubview:_colorView];
NSArray *colors = @[
[UIColor darkGrayColor],
[UIColor redColor],
[UIColor greenColor],
[UIColor blueColor],
[UIColor yellowColor],
[UIColor orangeColor],
[UIColor purpleColor],
[UIColor brownColor],
[UIColor blackColor]
];
CGFloat width = CGRectGetWidth(self.bounds) / colors.count;
//创建按钮
for (int i = 0; i < colors.count; i++) {
ToolButton *button = [[ToolButton alloc] initWithFrame:CGRectMake(i * width, 0, width, width)];
button.type = kToolButtonColorType;
button.color = colors[i];
button.backgroundColor = [UIColor clearColor];
[button addTarget:self
action:@selector(tapColor:)
forControlEvents:UIControlEventTouchUpInside];
[_colorView addSubview:button];
}
}
//线宽栏
- (void)createLineWidthView
{
_widthView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_buttonView.frame), CGRectGetWidth(self.bounds), 40)];
_widthView.hidden = YES;
_widthView.backgroundColor = [UIColor clearColor];
[self addSubview:_widthView];
NSArray *widths = @[@1.0,@3.0,@5.0,@8.0,@10.0,@15.0,@20.0];
CGFloat width = CGRectGetWidth(self.bounds) / widths.count;
//创建按钮
for (int i = 0; i < widths.count; i++) {
ToolButton *button = [[ToolButton alloc] initWithFrame:CGRectMake(i * width, 0, width, 25)];
button.type = kToolButtonWidthType;
button.title = [NSString stringWithFormat:@"%@点", widths[i]];
button.width = [widths[i] floatValue];
button.backgroundColor = [UIColor clearColor];
[button addTarget:self
action:@selector(tapWidth:)
forControlEvents:UIControlEventTouchUpInside];
[_widthView addSubview:button];
}
}
#pragma mark - Actions
- (void)buttonAction:(ToolButton *)sender
{
//1.把上一个button选中状态取消
self.lastButton.checked = NO;
//2.把点击的button设置为选中
sender.checked = YES;
//3.记录下选择的button
self.lastButton = sender;
//点击button,切换视图
switch (sender.tag - 100) {
case 0:
_colorView.hidden = NO;
_widthView.hidden = YES;
break;
case 1:
_colorView.hidden = YES;
_widthView.hidden = NO;
break;
case 2: //橡皮
_eraseBlock();
break;
case 3: //撤销
_undoBlock();
break;
case 4: //清屏
_clearBlock();
break;
default:
break;
}
}
//颜色
- (void)tapColor:(ToolButton *)sender
{
//1.把上一个button选中状态取消
self.lastColor.checked = NO;
//2.把点击的button设置为选中
sender.checked = YES;
//3.记录下选择的button
self.lastColor = sender;
//block调用
if (_colorBlock != nil) {
_colorBlock(sender.color);
}
}
//线宽
- (void)tapWidth:(ToolButton *)sender
{
//1.把上一个button选中状态取消
self.lastWidth.checked = NO;
//2.把点击的button设置为选中
sender.checked = YES;
//3.记录下选择的button
self.lastWidth = sender;
if (_widthBlock != nil) {
_widthBlock(sender.width);
}
}
- (void)addErase:(ChangeBlock)eraseBlock undo:(ChangeBlock)undoBlock clear:(ChangeBlock)clearBlock
{
_eraseBlock = eraseBlock;
_undoBlock = undoBlock;
_clearBlock = clearBlock;
}
@end
4.绘画视图#import <UIKit/UIKit.h>
@interface PanelView : UIView
{
NSMutableArray *_pathes;
}
@property (nonatomic, assign) CGMutablePathRef currentPath;
@property (nonatomic, strong) UIColor *currentColor;
@property (nonatomic, assign) CGFloat currentWidth;
//清屏
- (void)clear;
//撤销
- (void)undo;
@end
@implementation PanelView
/*
* 绘制多条线:
* 1. 初始化就创建路径,一直使用同一条路径
* 2. 每创建一个路径,就保存在数组中
*/
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// _path = CGPathCreateMutable();
_pathes = [NSMutableArray array];
//设置默认的画笔
_currentColor = [UIColor blackColor];
_currentWidth = 5;
}
return self;
}
- (void)drawRect:(CGRect)rect {
//上下文
CGContextRef context = UIGraphicsGetCurrentContext();
/*
//从数组中取出路径,绘制
for (id path in _pathes) {
CGMutablePathRef lastPath = (__bridge CGMutablePathRef)(path);
CGContextAddPath(context, lastPath);
//设置颜色和线宽
//[[UIColor redColor] set];
// CGContextSetRGBStrokeColor(context, 0, 0, 0, 1)
// CGContextSetLineWidth(context, <#CGFloat width#>)
CGContextDrawPath(context, kCGPathStroke);
}
*/
//遍历所有的路径,把路径绘制
for (PathModel *model in _pathes) {
//路径添加到上下文
CGContextAddPath(context, model.path);
//设置上下文(颜色)
[model.color set];
//(线宽)
CGContextSetLineWidth(context, model.width);
//绘制
CGContextDrawPath(context, kCGPathStroke);
}
//第一次绘制的路径如果为空,就不绘制
if (_currentPath != nil) {
//路径添加到上下文
CGContextAddPath(context, _currentPath);
//设置上下文
CGContextSetLineWidth(context, _currentWidth);
[_currentColor set];
//绘制
CGContextDrawPath(context, kCGPathStroke);
/*
PathModel *model = [_pathes objectAtIndex:0];
CGContextAddPath(context, model.path);
[model.color set];
CGContextSetLineWidth(context, model.width);
*/
}
}
//触摸开始
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
//创建路径
_currentPath = CGPathCreateMutable();
//设置起始点
CGPathMoveToPoint(_currentPath, NULL, location.x, location.y);
}
//触摸移动
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
//移动,路径上添加线
CGPathAddLineToPoint(_currentPath, NULL, location.x, location.y);
//手动调用drawRect:
[self setNeedsDisplay];
}
//触摸结束
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
/*
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
//路径上添加结束点
CGPathAddLineToPoint(_currentPath, NULL, location.x, location.y);
*/
//把路径保存 注意桥接
//[_pathes addObject:(__bridge id)(_currentPath)];
// if (_pathes == nil) {
// _pathes = [NSMutableArray array];
// }
//创建model,保存绘图的属性
PathModel *model = [[PathModel alloc] init];
model.path = _currentPath;
model.color = _currentColor;
model.width = _currentWidth;
[_pathes addObject:model];
//释放路径
CGPathRelease(_currentPath);_currentPath = nil;
}
#pragma mark - 图形界面方法
- (void)clear
{
[_pathes removeAllObjects];
// _pathes = [NSMutableArray array];
// _pathes = nil;
//调用drawRect方法,重绘界面
[self setNeedsDisplay];
}
- (void)undo
{
[_pathes removeLastObject];
[self setNeedsDisplay];
}
@end
#define kStatusBarHeight 20
#define kScreenWidth ([UIScreen mainScreen].bounds.size.width)
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
PanelView *panel = [[PanelView alloc] initWithFrame:self.view.bounds];
panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:panel];
ToolView *tool = [[ToolView alloc] initWithFrame:CGRectMake(0, kStatusBarHeight, kScreenWidth, 100)];
tool.backgroundColor = [UIColor grayColor];
[self.view addSubview:tool];
//block赋值,设置block来修改相应的属性
tool.colorBlock = ^(UIColor *color){
panel.currentColor = color;
};
tool.widthBlock = ^(CGFloat width){
panel.currentWidth = width;
};
[tool addErase:^{
panel.currentColor = [UIColor whiteColor];
panel.currentWidth = 20;
} undo:^{
[panel undo];
} clear:^{
[panel clear];
}];
}
效果图