ios 画图

1.效果图

Untitled3.gif

2.代码展示

  1. 创建header file
/*
  该方法负责绘制圆角矩形
 x1,y2: 圆角矩形左上角的坐标
 width , height :控制圆角矩形宽高
 radius 控制圆角矩形的四个圆角的半径
 */
//void CGContextAssRoundRect(CGContextRef c, CGFloat x1, CGFloat y1, CGFloat width, CGFloat height, CGFloat radius)
//{
//    //移动到左上角
//    CGContextMoveToPoint(c, x1 + radius, y1);
//    //添加一条连接到右上角的线段
//    CGContextAddLineToPoint(c, x1 + width - radius, y1);
//    //添加一段圆弧
//    CGContextAddArcToPoint(c, x1 + width, y1, x1 + width, y1 + radius, radius);
//    //添加一条连接到右下角的线段
//    CGContextAddLineToPoint(c, x1 + width, y1 + height - radius);
//    
//}
void CGContextAddRoundRect(CGContextRef c, CGFloat x1 , CGFloat y1, CGFloat width , CGFloat height , CGFloat radius)
{
    // 移动到左上角
    CGContextMoveToPoint (c, x1 + radius , y1);
    // 添加一条连接到右上角的线段
    CGContextAddLineToPoint(c , x1 + width - radius, y1);
    // 添加一段圆弧
    CGContextAddArcToPoint(c , x1 + width , y1, x1 + width
                           , y1 + radius, radius);
    // 添加一条连接到右下角的线段
    CGContextAddLineToPoint(c , x1 + width, y1 + height - radius);
    // 添加一段圆弧
    CGContextAddArcToPoint(c , x1 + width, y1 + height
                           , x1 + width - radius , y1 + height , radius);
    // 添加一条连接到左下角的线段
    CGContextAddLineToPoint(c , x1 + radius, y1 + height);
    // 添加一段圆弧
    CGContextAddArcToPoint(c , x1, y1 + height , x1
                           , y1 + height - radius , radius);
    // 添加一条连接到左上角的线段
    CGContextAddLineToPoint(c , x1 , y1 + radius);
    // 添加一段圆弧
    CGContextAddArcToPoint(c , x1 , y1 , x1 + radius , y1 , radius);
}


void CGContextAddStar(CGContextRef c , NSInteger n, CGFloat dx , CGFloat dy , NSInteger size)
{
    CGFloat dig = 4 * M_PI / n ;
    // 移动到指定点
    CGContextMoveToPoint(c , dx , dy + size);
    for(int i = 1 ; i <= n ; i++)
    {
        CGFloat x = sin(i * dig);
        CGFloat y = cos(i * dig);
        // 绘制从当前点连接到指定点的线条
        CGContextAddLineToPoint(c , x * size + dx ,y * size + dy);
    }
}

2.再创建一个header file

//枚举类型
typedef enum
{
    klineShape = 0,
    krectShape,
    kEillpseShape,
    kRoundRectShape,
    kPenShape
    
}ShapeType;

3.继承uiview

@property (nonatomic, strong) UIColor* currentColor;
@property (nonatomic, assign) ShapeType shape;

CGPoint firstTouch, prevTouch, lastTouch;
// 定义向内存中图片执行绘图的CGContextRef
CGContextRef buffCtx;
UIImage* image;

- (id)initWithCoder:(NSCoder*)aCoder
{
    self = [super initWithCoder:aCoder];
    if (self) {
        // 初始化时将当前颜色设为红色
        self.currentColor = [UIColor redColor];
        // 创建内存中的图片
        UIGraphicsBeginImageContext(self.bounds.size);
        // 获取向内存中图片执行绘图的CGContextRef
        buffCtx = UIGraphicsGetCurrentContext();
    }
    return self;
}
// 当用户手指开始触碰时激发该方法
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    // 获取触碰点坐标
    firstTouch = [touch locationInView:self];
    // 如果当前正在进行自由绘制,prevTouch代表第一个触碰点
    if (self.shape == kPenShape)
    {
        prevTouch = firstTouch;
    }
}
// 当用户手指在控件上拖动时不断地激发该方法
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    // 获取触碰点坐标
    lastTouch = [touch locationInView:self];
    // 如果当前正在进行自由绘制
    if (self.shape == kPenShape)
    {
        // 向内存中的图片执行绘制
        [self draw:buffCtx];
        // 取出内存中的图片,保存到image中
        image = UIGraphicsGetImageFromCurrentImageContext();
    }
    // 通知该控件重绘,此时会实时地绘制起始点与用户手指拖动点之间的形状
    [self setNeedsDisplay];
}
// 当用户手指离开控件时激发该方法
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    // 获取离开触碰的点坐标
    lastTouch = [touch locationInView:self];
    // 向内存中的图片执行绘制,即把最终确定图形绘制到内存中图片上
    [self draw:buffCtx];
    image = UIGraphicsGetImageFromCurrentImageContext();
    // 通知重绘。
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{
    // 获取绘图上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 将内存中的图片绘制出来
    [image drawAtPoint:CGPointZero];
    // 调用draw:方法执行绘制
    [self draw:ctx];
}
// 定义一个函数,用于根据firstTouch、lastTouch来确定矩形区域
- (CGRect) curRect
{
    return CGRectMake(firstTouch.x, firstTouch.y,
                      lastTouch.x - firstTouch.x ,
                      lastTouch.y - firstTouch.y);
}
- (void)draw:(CGContextRef)ctx
{
    // 设置线条颜色
    CGContextSetStrokeColorWithColor(ctx, self.currentColor.CGColor);
    // 设置填充颜色
    CGContextSetFillColorWithColor(ctx, self.currentColor.CGColor);
    // 设置线宽
    CGContextSetLineWidth(ctx, 2.0);
    CGContextSetShouldAntialias(ctx, YES);
    switch (self.shape) {
            CGFloat leftTopX , leftTopY;
        case klineShape:
            // 添加从firstTouch到lastTouch的路径
            CGContextMoveToPoint(ctx, firstTouch.x, firstTouch.y);
            CGContextAddLineToPoint(ctx, lastTouch.x, lastTouch.y);
            // 绘制路径
            CGContextStrokePath(ctx);
            break;
        case krectShape:
            // 填充矩形
            CGContextFillRect(ctx ,[self curRect]);
            break;
        case kEillpseShape:
            // 填充椭圆
            CGContextFillEllipseInRect(ctx ,[self curRect]);
            break;
        case kRoundRectShape:
            // 计算左上角的坐标
            leftTopX = firstTouch.x < lastTouch.x ? firstTouch.x :
            lastTouch.x;
            leftTopY = firstTouch.y < lastTouch.y ? firstTouch.y :
            lastTouch.y;
            // 添加圆角矩形的路径
            CGContextAddRoundRect(ctx ,leftTopX ,leftTopY ,
                                  fabs(lastTouch.x - firstTouch.x) ,
                                  fabs(lastTouch.y - firstTouch.y) , 16);
            // 填充路径
            CGContextFillPath(ctx);
            break;
        case kPenShape:
            // 添加从prevTouch到lastTouch的路径
            CGContextMoveToPoint(ctx, prevTouch.x, prevTouch.y);
            CGContextAddLineToPoint(ctx, lastTouch.x, lastTouch.y);
            // 绘制路径
            CGContextStrokePath(ctx);
            // 使用prevTouch保存当前点
            prevTouch = lastTouch;
            break;
    }
}
@interface ViewController ()
{
    NSArray *colors;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    colors = [NSArray arrayWithObjects:
              [UIColor redColor],[UIColor greenColor],
              [UIColor blueColor],[UIColor yellowColor],
              [UIColor purpleColor],[UIColor cyanColor],
              [UIColor blackColor] , nil];
    // Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)changeColor:(UISegmentedControl *)sender {
    // 根据用户的选择来修改FKDrawView的当前颜色
    ((GSCDrawView*)self.view).currentColor = [colors objectAtIndex:sender.selectedSegmentIndex];
}
- (IBAction)changeShape:(UISegmentedControl *)sender {
    
    // 修改FKDrawView控件的shape属性
    ((GSCDrawView*)self.view).shape = sender.selectedSegmentIndex;

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,598评论 25 707
  • 序 在百度和简书上找到很多实现的代码。找到的实现方式对于刚接触的人来说,很乱,很多方式。为何呢:因为实现画图的代码...
    双鲶鱼阅读 1,179评论 0 6
  • 前言 过年了,老家却没有网,用的朋友家的wifi,信号很不稳定,相当不爽。正好最近也有点郁闷,作为一个搬砖的人,倒...
    _onePiece阅读 582评论 0 3
  • 0 CGContextRef context = UIGraphicsGetCurrentContext(); 设...
    竖着走的大闸蟹阅读 501评论 1 3
  • 1 今天早上,我约了一个讲形象设计的行家,聊我的发型问题。 我的头发一直是我的老大难问题,又扎不住,又不乖巧,绑个...
    小荻老师阅读 325评论 1 2