利用CGMutablePathRef製做畫板塗鴉

效果圖:數組

安全

具體代碼以下:ide

ViewControl:工具

#import "ViewController.h"
#import "PenView.h"
#import "ToolView.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //建立畫板
    PenView *penView = [[PenView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    
    penView.backgroundColor = [UIColor whiteColor];
    
    [self.view addSubview:penView];
    
    //建立工具欄
    CGFloat width = [UIScreen mainScreen].bounds.size.width;
    ToolView *toolView = [[ToolView alloc]initWithFrame:CGRectMake(0, 20, width, 110)];
    toolView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:toolView];
    //block的實現
    [toolView addColorBlock:^(UIColor *color) {
        penView.color = color;
    } withLineWidth:^(CGFloat width) {
        penView.lineWidth = width;
    } andMyBlock:^{
        penView.color = [UIColor whiteColor];
        
        penView.lineWidth = 20;
        
    } andMyBlock:^{
        
        [penView back];
        
        
        
    } andMyBlock:^{
        
        [penView clear];
        
    }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

penview畫板類的penview.hatom

#import <UIKit/UIKit.h>

@interface PenView : UIView

{
    CGMutablePathRef path;
    
    NSMutableArray *pathArr;
}

@property (nonatomic, strong)UIColor *color;

@property (nonatomic, assign)CGFloat lineWidth;

- (void)back;

- (void)clear;

@end

penview畫板類的penview.m 大部分功能都是在這裏實現spa

#import "PenView.h"
#import "PathModel.h"

@implementation PenView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    
    if (self) {
        //給初始值
        _color = [UIColor blackColor];
        
        _lineWidth = 2.0;
    }
    
    return self;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //獲取手指開始點擊屏幕的位置
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:touch.view];
    //建立一個全局的路徑,注意這裏咱們用到了create,因此在下面必定要記得釋放
    path = CGPathCreateMutable();
    //起始點
    CGPathMoveToPoint(path, NULL, point.x, point.y);
    //刷新重繪
    [self setNeedsDisplay];
    
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    
    CGPoint point = [touch locationInView:touch.view];
    //畫線
    CGPathAddLineToPoint(path, NULL, point.x, point.y);
    
    [self setNeedsDisplay];

    
    
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    //爲了保證 不重複建立
    if (pathArr == nil) {
        
        pathArr = [[NSMutableArray alloc]init];
        
    }
    //創建的model用來保存咱們所畫的每條線段的粗細,顏色,等
    PathModel *model = [[PathModel alloc]init];
    
    model.path = path;
    
    model.color = _color;
    
    model.width = _lineWidth;
    
    //將model對象放入數組
    [pathArr addObject:model];
    

    //安全釋放
    CGPathRelease(path);
    //將指針對象清空
    path = nil;
    
    
    
}

//
- (void)drawRect:(CGRect)rect {
    
    
    //根據path,劃線
    if (path != nil) {
        //得到上下文
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        //添加路徑到上下文
        CGContextAddPath(ctx, path);
        //設置屬性
        [_color set];
        CGContextSetLineWidth(ctx, _lineWidth);
        //
        CGContextDrawPath(ctx, kCGPathStroke);
    }

    
    //咱們用model保存的每一條路徑。爲了確保以前畫的線段都存在。(你畫第二條線時,第一條線的路徑和顏色,粗細保存在model.保證你畫第二條線時,第一條線不會消失)
    if (pathArr != nil){
    
        for (int i = 0; i < pathArr.count; i ++) {
            //建立模型
            PathModel *model = [pathArr objectAtIndex:i];
            //去除模型中的數據
            CGMutablePathRef pa = model.path;
            UIColor *color = model.color;
            CGFloat width = model.width;
            
            //獲取上下文,這裏的上下文與前面獲取的爲同一個
            CGContextRef ctx = UIGraphicsGetCurrentContext();
            //添加路徑到上下文
            CGContextAddPath(ctx, pa);
            //設置顏色等屬性
            [color set];
            CGContextSetLineWidth(ctx, width);
            //
            CGContextDrawPath(ctx, kCGPathStroke);
            
        }
    }
    

}
//撤銷,說白了就是刪除數組裏的最後一個model
- (void)back
{
    [pathArr removeLastObject];
    
    [self setNeedsDisplay];
}
//清空
- (void)clear
{
    [pathArr removeAllObjects];
    
    [self setNeedsDisplay];
}

@end

//建立model類
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface PathModel : NSObject

@property (nonatomic, assign)CGMutablePathRef path;

@property (nonatomic, strong)UIColor *color;

@property (nonatomic, assign)CGFloat width;

@end

//建立工具欄的.h文件
#import <UIKit/UIKit.h>
@class seleButton;
typedef void(^ColorBlock)(UIColor *color);
typedef void(^LineWidth)(CGFloat width);
typedef void(^MyBlock)(void);
@interface ToolView : UIView

{
    seleButton *_lastButton;
    
    UIView *_colorView;
    
    UIView *_lineView;
    
    NSArray *_lineArr;
    
    ColorBlock _colorBlock;
    
    LineWidth _lineWidth;
    
    MyBlock _block1;
    
    MyBlock _block2;
    
    MyBlock _block3;
    
}
//set 方法 只不過這個方法參數有點多。
- (void)addColorBlock:(ColorBlock)colorBlock withLineWidth:(LineWidth)lineWidth andMyBlock:(MyBlock)block1 andMyBlock:(MyBlock)block2 andMyBlock:(MyBlock)block3;

@end
//建立工具欄的.m文件
#import "ToolView.h"
#import "seleButton.h"
#define KScreenWidth [UIScreen mainScreen].bounds.size.width
@implementation ToolView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
        //建立選擇按鈕
        [self _initSeleter];
        //建立選擇顏色的視圖
        [self _initColor];
        //建立選擇線寬的視圖
        [self _initLineWidthView];
        
    }
    return self;
}
//set方法
- (void)addColorBlock:(ColorBlock)colorBlock withLineWidth:(LineWidth)lineWidth andMyBlock:(MyBlock)block1
andMyBlock:(MyBlock)block2 andMyBlock:(MyBlock)block3{
    _colorBlock = colorBlock;
    
    _lineWidth = lineWidth;
    
    _block1 = block1;
    
    _block2 = block2;
    
    _block3 = block3;
    
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
}
//建立選擇按鈕
- (void)_initSeleter
{
    NSArray *titleArr = @[@"顏色",@"線寬",@"橡皮",@"撤銷",@"清屏"];
    
    //按鈕的frame
    CGFloat width = KScreenWidth / 5.0;
    
    for (int  i = 0; i < 5; i ++) {
        
        seleButton *selectButton = [[seleButton alloc]initWithFrame:CGRectMake(width * i, 0, width, 40)];
        
        selectButton.title = titleArr[i];
        
        selectButton.backgroundColor = [UIColor clearColor];
        
        selectButton.tag = 100 + i;
        
        [selectButton addTarget:self action:@selector(selectButtonAction:) forControlEvents:UIControlEventTouchUpInside];
        
        [self addSubview:selectButton];
        
    }
}

- (void)selectButtonAction:(seleButton *)button {
    
    //取消前一次點擊的按鈕
    _lastButton.isSeleter = NO;
    
    //設置選中的標示
    button.isSeleter = YES;
    
    //記錄選中的按鈕
    _lastButton = button;
    switch (button.tag) {
        case 100:
            //選擇顏色面板
            _colorView.hidden = NO;
            _lineView.hidden = YES;
            break;
        case 101:
            //選擇線寬面板
            _colorView.hidden = YES;
            _lineView.hidden = NO;
            break;
        case 102:
            //選擇橡皮面板
            if (_block1) {
                _block1();
            }
            break;
        case 103:
            //選擇撤銷
            if (_block2) {
                _block2();
            }
            break;
        case 104:
            //選擇清屏
            if (_block3) {
                _block3();
            }
            break;
        default:
            break;
    
    }
}

//建立顏色視圖
- (void)_initColor
{
    //建立顏色數組
    NSArray *colorArray = @[
                            [UIColor grayColor],
                            [UIColor redColor],
                            [UIColor greenColor],
                            [UIColor blueColor],
                            [UIColor yellowColor],
                            [UIColor magentaColor],
                            [UIColor orangeColor],
                            [UIColor purpleColor],
                            [UIColor blackColor]
                            ];
    
    //建立顯示顏色的fu視圖
    _colorView = [[UIView alloc]initWithFrame:CGRectMake(0, 40, KScreenWidth, 65)];
    _colorView.hidden = YES;
    _colorView.backgroundColor = [UIColor clearColor];
    [self addSubview:_colorView];
    
    //建立顯示顏色的zi視圖
    CGFloat width = KScreenWidth / 9.0;
    
    for (int i = 0; i < colorArray.count; i ++) {
        UIControl *control = [[UIControl alloc]initWithFrame:CGRectMake(width * i, 5, width - 5, 65 - 10)];
        
        control.backgroundColor = colorArray[i];
        [control addTarget:self action:@selector(colorAction:) forControlEvents:UIControlEventTouchUpInside];
        
        [_colorView addSubview:control];
    }
    
    

}

- (void)colorAction:(UIControl *)control
{
    UIColor *color = control.backgroundColor;
    
    //block的回調
    _colorBlock(color);

}

//建立線寬視圖
- (void)_initLineWidthView
{
    _lineView = [[UIView alloc]initWithFrame:CGRectMake(0, 40, KScreenWidth, 65)];
    
    _lineView.hidden = YES;
    
    _lineView.backgroundColor = [UIColor clearColor];
    
    [self addSubview:_lineView];
    
    _lineArr = @[@1,@3,@5,@8,@10,@15,@20];
    
    CGFloat width = KScreenWidth / 7.0;
    
    for (int i = 0; i < _lineArr.count; i ++) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        
        button.tag = i;
        
        NSString *name = [NSString stringWithFormat:@"%@點",_lineArr[i]];
        
        [button setTitle:name forState:UIControlStateNormal];
        button.frame = CGRectMake(width * i,  5, width - 5, 65 - 10);
        [button addTarget:self action:@selector(lineWidthAction:) forControlEvents:UIControlEventTouchUpInside];
        
        [_lineView addSubview:button];
    }
    
    
}



- (void)lineWidthAction:(UIButton *)button
{
    NSNumber *number = _lineArr[button.tag];
    
    NSLog(@"%@",number);
    
    CGFloat flo = [number floatValue];
    //block的回調
    _lineWidth(flo);
    
}

@end

按鈕的子類化建立
新建一個類繼承子UIControl
#import <UIKit/UIKit.h>

@interface seleButton : UIControl

@property (nonatomic, copy)NSString *title;

@property (nonatomic, assign)BOOL isSeleter;

@property (nonatomic, strong)UIFont *font;

@end
.m
#import "seleButton.h"

@implementation seleButton

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    
    if (self) {
        
        _title = @"默認標題";
        
        _isSeleter = NO;
        
        _font = [UIFont systemFontOfSize:17];
    }
    
    return self;
}

- (void)drawRect:(CGRect)rect {
    
    //繪製文字
    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc]init];
    //設置文字居中
    style.alignment = NSTextAlignmentCenter;
    
    NSDictionary *dic = @{
                          NSFontAttributeName:_font,
                          NSParagraphStyleAttributeName:style
                          };
    //花文字
    rect.origin.y += 10;
    [_title drawInRect:rect withAttributes:dic];
    
    //畫紅色選中線條
    if (_isSeleter){
        
        CGRect frame = CGRectMake(0, CGRectGetHeight(rect) - 2, CGRectGetWidth(rect), 2);
        
        [[UIColor redColor]set];
        
        UIRectFill(frame);
    
    }
    
}

- (void)setTitle:(NSString *)title
{
    _title = title;
    
    [self setNeedsDisplay];
}

- (void)setFont:(UIFont *)font
{
    _font = font;
    
    [self setNeedsDisplay];
}

- (void)setIsSeleter:(BOOL)isSeleter
{
    _isSeleter = isSeleter;
    
    [self setNeedsDisplay];
}


@end
相關文章
相關標籤/搜索