利用CGMutablePathRef制作画板涂鸦

效果图:

具体代码如下:

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.h

#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 大部分功能都是在这里实现

#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
时间: 2024-08-09 19:53:51

利用CGMutablePathRef制作画板涂鸦的相关文章

ArcGIS利用DEM制作简单三维

利用DEM数据镶嵌后,矢量数据裁剪得到研究范围的DEM数据,在ARCScene中进行三维制作 ArcGIS利用DEM制作简单三维 点击学习我的系统教程哦

【PhotoShop】利用PS制作唯美咖啡泡

难得喝杯咖啡,怎么能不拍张了(黑咖啡太苦经常喝实在受不了!) 得到如下图 看着还不错,可是总感觉空空荡荡的,所以就拿来PS练手了.最终效果图如下: 下面讲下制作过程: 首先是给照片加下咖啡泡的效果,找一张有咖啡泡的咖啡~然后选区把咖啡泡部分抠出来 把图片抠出来调整大小适应杯子,然后自然是选择混合选项让他更逼真了. 我这里选择的是点光,当然可以根据个人图片效果选择了.为了让图片更加逼真,我为该图层创建蒙版,并且用黑色画笔涂抹阴暗处(让阴暗处更阴暗)而显得有层次感.效果如图: 现在在加点文字吧.下面

利用CSS制作静态网页的注意事项

利用CSS制作静态网页主要是在<head>里面使用外联CSS文件来赋予网页样式 首先用div分区块,了解网页布局,脑子里面有个大概的页面布局 目前学习写的几种的网页布局可以分为以下几种情况: 1.页面中间 centen ,两边留白 :直接测量 centen 内容的宽度和高度,利用 maigin:auto 让内容居中即可: 2.页面顶部 head 满页面内容 ,下面centen 居中 ,两边留白:head 宽度设为100%,中间centen 内容的宽度和高度,利用 maigin:auto 让内容

利用replaceChild制作简单的吞噬效果【jsDEMO】

[功能说明] 利用replaceChild制作简单的吞噬效果 [HTML代码说明] <ul class="list" id="list"> <li class="in">1</li> <li class="in">2</li> <li class="in">3</li> <li class="in"

利用QuickCHM制作chm

CHM是一种常见的帮助文件格式,也是电子书的一种格式. 下面是使用QuickCHM制作chm的步骤: 1.先将所有的word文档存储为mht格式,点击,文件--另存为网页,如下 2.确保所有的word文档都已经拥有了自己的mht备份. 3.用QuickCHM导入工程,点击,文件--CHM向导,选择文件夹路径 4.更改章节名称,如下 5.更改章节图标,如下 6.添加新的章节,例如添加index章节 7.更改章节的结构,直接在左侧的树上拖动节点进行编辑 8.保存工程,点击保存按钮,会发现文件夹下多了

如何利用PhoneGap制作地图APP

摘要:百度地图API是一套由javascript编写的地图程序接口,按说它应该运行在浏览器上.现在,只要利用PhoneGap,我们就能开发出移动平台上能使用的APP了! --------------------------------------------- 一.安装平台 PhoneGap支持5种平台,IOS,安卓,黑莓,WebOS,塞班. 我们下面以IOS为例,开发一个定位的APP. 1.下载xCode 注意看清楚,狮子系统和雪豹系统的安装程序是不一样的. a.可以到苹果应用商店app st

利用removeChild制作简单的倒序删除效果【jsDEMO】

[功能说明] 利用removeChild制作简单的倒序删除效果 [HTML代码说明] <ul class="list" id="list"> <li class="in">1</li> <li class="in">2</li> <li class="in">3</li> <li class="in"

android利用jdk制作签名

Apk签名首先要有一个keystore的签名用的文件. keystore是由jdk自带的工具keytool生成的.具体生成方式参考一下: 开始->运行->cmd->cd 到你安装的jdk的目录这里我是 C:\Program Files\Java\jdk1.6.0_10\bin 然后输入:keytool -genkey -alias lvmama.keystore -keyalg RSA -validity 10000 -keystore lvmama.keystore 下面解释下签名的参

初学JS——利用JS制作的别踩白块儿(街机模式) 小游戏

初学JS--利用JS制作的别踩白块儿(街机模式) 小游戏 这个是上个星期5写的了,当时是突然想写个游戏,就想到了别踩白块儿,当时的想法是 可能普通模式的别踩白块儿因为他的"块儿"是滚动的向上这种,以我目前会的技术想不出怎么写, 但是如果是街机模式,通过你每按一次按键之后他像下跳一格这样的就非常好实现了. 通过我目前会的知识,实现的步骤大概是这样的: 建一个4X4的表格,制作2张150X100的图片,一张全白色,一张全黑色,命名为0.JPG,1.JPG 就是说当文件名为0的时候就是白色的