iOS开发---绘图

绘图操作

前言:在iOS开发中,系统已经给我们提供了功能强大的控件,可是很多并不能满足我们的需求。这时候我们需要,自定义一些美观的控件。所用的知识也就是下面的绘图。

1.基本的绘图知识

1.1图形上下文

  • 1.1图形上下文(Graphics Context):是一个CGContextRef类型的数据
  • 1.2图形上下文的作用

    保存绘图信息、绘图状态

    决定绘制的输出目标(绘制到什么地方去?)

    (输出目标可以是PDF文件、Bitmap或者显示器的窗口上)

1.2 - (void)drawRect:(CGRect)rect

  • 作用:就是用来绘图
  • 什么调用:当控件第一次显示的时候
  • rect:当前控件的bounds

1.2 绘图的步骤

1.获得图形上下文:

CGContextRef ctx = UIGraphicsGetCurrentContext();

2.拼接路径

  1. 新建一个起点

    void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)

  2. 添加新的线段到某个点

    void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)

  3. 添加一个矩形

    void CGContextAddRect(CGContextRef c, CGRect rect)

  4. 添加一个椭圆

    void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)

  5. 添加一个圆弧

    void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,

    CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)

3.添加路径到上下文

  1. Mode参数决定绘制的模式

    void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)

  2. 绘制空心路径

    void CGContextStrokePath(CGContextRef c)

  3. 绘制实心路径

    void CGContextFillPath(CGContextRef c)

提示:一般以CGContextDraw、CGContextStroke、CGContextFill开头的函数,都是用来绘制路径的

4.渲染到View上面

1.3 基本的绘图实例

1. 绘制线条

  1. 获得图形上下文: UIGraphicsGetCurrentContext()
  2. 拼接路径:UIBezierPath
  3. 添加路径到上下文 CGContextAddPath(ctx, path.CGPath)
  4. 渲染到View上面 CGContextStrokePath(ctx)
- (void)drawLine
{
    // 一个路径对象,可以对应多跟线
    // 1.获取跟当前view想关联的上下文,系统自动帮我们创建的上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 设置上下文的状态,应该放在渲染之前就可以
    // 创建对应颜色对象,调用set方法
    [[UIColor redColor] set];
    // 设置上下文的线宽
    CGContextSetLineWidth(ctx, 15);
    // 设置线段的连接样式
    CGContextSetLineJoin(ctx, kCGLineJoinRound);
    // 设置线段的端点样式
    CGContextSetLineCap(ctx, kCGLineCapRound);

    // 2.拼接路径,UIBezierPath,封装好了一套很好使用的路径
    UIBezierPath *path = [UIBezierPath bezierPath];
    // 2.1 设置起点
    [path moveToPoint:CGPointMake(10, 125)];
    // 2.2 添加一根线到某个点
    [path addLineToPoint:CGPointMake(220, 125)];
    // 如果只使用一根路径,默认下一根线的起点在上一根跟线终点
    [path addLineToPoint:CGPointMake(200, 150)];

    // 3.添加路径到上下文
    CGContextAddPath(ctx, path.CGPath);
    // 4.渲染到view上面的图层
    CGContextStrokePath(ctx);

}

2.绘制曲线

一般通过贝塞尔曲线来绘制图形:UIBezierPath

-(void)drawLIneQuadCurve
{
    // 1.获取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 2.拼接路径
    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:CGPointMake(10, 125)];
    [path addQuadCurveToPoint:CGPointMake(240, 125) controlPoint:CGPointMake(125, 0)];

    // 3.路径添加到上下文
    CGContextAddPath(ctx, path.CGPath);

    // 4.渲染上下文
    //以填充的方式渲染
    //CGContextFillPath(ctx);
    CGContextStrokePath(ctx);
}

3.绘制矩形

// 绘制矩形
- (void)drawRect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50, 100, 100) cornerRadius:50];

    CGContextAddPath(ctx, path.CGPath);

    // 设置填充的颜色
    [[UIColor redColor] setFill];

    [[UIColor greenColor] setStroke];

    // 填充:必须封闭的路径
    // 即描边又填充
    // 如果以后只需要描边,最好不要使用fill
    CGContextDrawPath(ctx, kCGPathFillStroke);
    //    CGContextFillPath(ctx);
    CGContextStrokePath(ctx);
}

4.绘制圆弧

- (void)drawRect:(CGRect)rect {
    // 画圆弧
    // center:圆心
    // radius:半径
    // clockwise:当前是 yes:顺时针 no:逆时针
    CGPoint center = CGPointMake(125, 125);

    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(125, 125) radius:100 startAngle:0 endAngle:-M_PI_2  clockwise:NO];
    // 添加一根线到圆心
    [path addLineToPoint:center];

    // 关闭路径:从路径的终点到起点
    // [path closePath];

    // 填充,默认会关闭路径,从路径的终点到起点
    [path fill];
}

5.绘制文字

- (void)drawRect:(CGRect)rect
{
    //=========================绘制文字==========================
    NSString *name = @"会长桂雏菊";
    // 描述文字的属性,颜色,字体大小
    NSMutableDictionary *attr = [NSMutableDictionary dictionary];
    // 字体
    attr[NSFontAttributeName] = [UIFont systemFontOfSize:15];
    // 颜色
    attr[NSForegroundColorAttributeName] = [UIColor redColor];
    // 边框颜色
    attr[NSStrokeColorAttributeName] = [UIColor redColor];
    // 边框宽度
    attr[NSStrokeWidthAttributeName] = @1;

    // 阴影
    NSShadow *shadow = [[NSShadow alloc] init];
    shadow.shadowOffset = CGSizeMake(3, 3);
    shadow.shadowColor = [UIColor yellowColor];
    shadow.shadowBlurRadius = 3;

    attr[NSShadowAttributeName] = shadow;

    [name drawInRect:CGRectMake(90, 100, 100, 50) withAttributes:attr];
}

6.绘制饼状图

在初始化的时候时候,系统通过调用drawRect方法绘图。但是如果我们要重绘,手动调用drawRect方法是无效的。不过系统为我们准备了重绘的方法:

重绘:setNeedsDisplay

- (void)drawRect:(CGRect)rect {
    // Drawing code
    NSArray *datas = @[@25,@25,@50];
    CGPoint center = CGPointMake(125, 125);
    CGFloat r = 100;
    CGFloat startA = 0;
    CGFloat angle = 0;
    CGFloat endA = 0;
    for (NSNumber *number in datas) {
        // 遍历一个数据,绘制一根扇形
        startA = endA;
        angle = number.intValue / 100.0 * M_PI * 2;
        endA = startA + angle;
        // 描述圆弧
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:r startAngle:startA endAngle:endA clockwise:YES];

        [path addLineToPoint:center];

        [[self randomColor] set];

        [path fill];
    }
}
//当点击View的时候,重绘
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self setNeedsDisplay];

}
//生成随机的颜色
- (UIColor *)randomColor
{
    CGFloat r = arc4random_uniform(256) / 255.0;
    CGFloat g = arc4random_uniform(256) / 255.0;
    CGFloat b = arc4random_uniform(256) / 255.0;
    return [UIColor colorWithRed:r green:g blue:b alpha:1];
}

7.上下文栈

将当前的上下文copy一份,保存到栈顶(那个栈叫做”图形上下文栈”):

void CGContextSaveGState(CGContextRef c)

将栈顶的上下文出栈,替换掉当前的上下文:

void CGContextRestoreGState(CGContextRef c)

- (void)drawRect:(CGRect)rect {
    // Drawing code

    // 1.获取上下文
    CGContextRef ctx =  UIGraphicsGetCurrentContext();
    // 2.拼接路径
    UIBezierPath *path = [UIBezierPath bezierPath];
    // 横
    [path moveToPoint:CGPointMake(10, 150)];
    [path addLineToPoint:CGPointMake(290, 150)];
    // 3.把路径添加到上下文
    CGContextAddPath(ctx, path.CGPath);

    //================================================
    // 保存上下文状态
    CGContextSaveGState(ctx);
    //================================================
    // 设置上下文的状态
    CGContextSetLineWidth(ctx, 10);
    [[UIColor redColor] set];

    // 4.渲染上下文,查看上下文的状态,根据状态去渲染
    CGContextStrokePath(ctx);
    // 竖
    path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(150, 10)];
    [path addLineToPoint:CGPointMake(150, 290)];

    // 3.把路径添加到上下文
    CGContextAddPath(ctx, path.CGPath);

    // ==============================================
    // 从上下文状态栈里面取出保存的状态,替换掉当前的状态
    CGContextRestoreGState(ctx);
    // =============================================

    // 4.渲染上下文,查看上下文的状态,根据状态去渲染
    CGContextStrokePath(ctx);

}

8.上下文的平移,旋转,缩放

利用矩阵操作,能让绘制到上下文中的所有路径一起发生变化

缩放

void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)

旋转

void CGContextRotateCTM(CGContextRef c, CGFloat angle)

平移

void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)

- (void)drawRect:(CGRect)rect {
    // 获取上下文
   CGContextRef ctx =  UIGraphicsGetCurrentContext();

    // 拼接路径
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-100, -50, 200, 100)];
    // 矩阵操作:必须要在添加路径之前进行形变
    // 平移上下文
    CGContextTranslateCTM(ctx, 100, 100);
    // 旋转
    CGContextRotateCTM(ctx, M_PI_4);
    // 缩放
    CGContextScaleCTM(ctx, 0.5, 0.5);

    // 添加路径到上下文
    CGContextAddPath(ctx, path.CGPath);

    // 渲染上下文
    CGContextFillPath(ctx);
}

9.图片加水印

1.开启一个基于位图的图形上下文

void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)

  • size:上下文尺寸
  • opaque:不透明 Yes 不透明 透明 NO
  • scale:是否缩放上下文,0表示不要缩放

2.从上下文中取得图片(UIImage):

UIImage* UIGraphicsGetImageFromCurrentImageContext()

3.结束基于位图的图形上下文:

void UIGraphicsEndImageContext()

- (void)viewDidLoad {开启一个基于位图的图形上下文
void     UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)

    [super viewDidLoad];

    UIImage *image = [UIImage imageNamed:@"hina"];
    // 创建位图上下文
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);

    [image drawAtPoint:CGPointZero];

    // 文字
    NSString *str = @"会长桂雏菊";
    [str drawAtPoint:CGPointMake(0, 0) withAttributes:nil];
    // 根据上下文的内容生成一张图片
    image = UIGraphicsGetImageFromCurrentImageContext();
    // 关闭上下文
    UIGraphicsEndImageContext();

    // 用来网络中传输图片
    NSData *data = UIImagePNGRepresentation(image);
    [data writeToFile:@"/Users/apple/Desktop/image.png" atomically:YES];
}

10.图片裁剪

1.将当前上下所绘制的路径裁剪出来(超出这个裁剪区域的都不能显示):

void CGContextClip(CGContextRef c)

思路分析

先画一个大圆,在设置裁剪区域,把图片画上去,超出裁剪区域的自动裁剪掉。

* 加载旧图片,根据旧图片,获取上下文尺寸。

* 确定圆环宽度 borderW

* 上下文的尺寸 = 新图片的尺寸

* 确定新的上下文尺寸: newImageW : oldImageW + 2 * borderW newImageH : oldImageH + 2 * borderW,

* 绘制大圆:

1.获取上下文 2.添加路径到上下文 3.设置大圆的颜色 = 圆环的颜色 4.渲染

* 设置裁剪区域,和图片尺寸一样大,只不过,x,y不一样,x=borderW,y=borderW.

* 绘制旧图片

* 获取新图片

* 关闭上下文

* 抽分类,3个参数,图片名称,圆环宽度,圆环颜色

+ (UIImage*)imageCircleWithImage:(UIImage *)image borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor
{
    // 设置圆环宽度
    CGFloat boardW = borderWidth;
    CGFloat imageW =  image.size.width + 2 * boardW;
    CGFloat imageH = image.size.height + 2 *boardW;

    // 只有正方形才能正切圆,选择一个最短的尺寸,正切。
    CGFloat circleW = imageW > imageH ? imageH : imageW;
    CGRect rect = CGRectMake(0, 0, circleW, circleW);

    // 2.开启图像上下文
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
    // 3。获取当前上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 4.画外圆
    UIBezierPath *path  = [UIBezierPath bezierPathWithOvalInRect:rect];
    CGContextAddPath(ctx, path.CGPath);

    [borderColor set];

    CGContextFillPath(ctx);

    // 设置头像尺寸
    rect = CGRectMake(boardW, boardW, image.size.width , image.size.height);

    // 5.创建裁剪路径
    UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:rect];

    // 6.裁剪路径
    // 根据这个路径进行裁剪,超出路径以外的部分就不会显示了
    [clipPath addClip];

    // 7.画头像
    [image drawInRect:rect];

    // 不能直接在这返回,上下文没有关闭,会消耗内存.
    // 8.获取新图片
    image = UIGraphicsGetImageFromCurrentImageContext();

    // 9.关闭上下文
    UIGraphicsEndImageContext();

    return image;

}

11.截取屏幕

View之所以能显示东西,完全是因为它内部的layer。View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,因此,绘制的东西其实是绘制到view的layer上去了

- (void)renderInContext:(CGContextRef)ctx;

//截取屏幕
+ (UIImage*)imageWithCaptureView:(UIView*)captureView;
{
    // 1.开启上下文
    UIGraphicsBeginImageContextWithOptions(captureView.bounds.size, NO, 0.0);
    // 2.获取当前上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 3.把控制器图层渲染到上下文
    [captureView.layer renderInContext:ctx];
    // 4.取出新图片
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-30 02:52:25

iOS开发---绘图的相关文章

iOS开发系列--绘图与滤镜全面解析

概述 在iOS中可以很容易的开发出绚丽的界面效果,一方面得益于成功系统的设计,另一方面得益于它强大的开发框架.今天我们将围绕iOS中两大图形.图形绘图框架进行介绍:Quartz 2D绘制2D图形和Core Image中强大的滤镜功能. Quartz 2D 基本图形绘制 视图刷新 其他图形上下文 Core Image Quartz 2D 在iOS中常用的绘图框架就是Quartz 2D,Quartz 2D是Core Graphics框架的一部分,是一个强大的二维图像绘制引擎.Quartz 2D在UI

iOS开发UI篇—Quartz2D使用(绘图路径)

iOS开发UI篇-Quartz2D使用(绘图路径) 一.绘图路径 A.简单说明 在画线的时候,方法的内部默认创建一个path.它把路径都放到了path里面去. 1.创建路径  cgmutablepathref 调用该方法相当于创建了一个路径,这个路径用来保存绘图信息. 2.把绘图信息添加到路径里边. 以前的方法是点的位置添加到ctx(图形上下文信息)中,ctx 默认会在内部创建一个path用来保存绘图信息. 在图形上下文中有一块存储空间专门用来存储绘图信息,其实这块空间就是CGMutablePa

iOS开发 - Quartz2D绘图

Quartz 2D简介 是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成PDF 截图\裁剪图片 自定义UI控件 - - drawRect:方法的使用 常见图形的绘制:线条.多边形.圆 绘图状态的设置:文字颜色.线宽等 图形上下文状态的保存与恢复 图形上下文栈 为了便于搭建美观的UI界面,iOS提供了UIKit框架,里面有各种各样的UI控件 UILabel:显示文字 UIImag

iOS 开发 Quartz 2D+ UIBezierPath绘图大全详解

Quartz 2D 使用大全结构图 UIKIt UIBezierPath Core Graphics OpenGL ES Quartz2D的区别和联系 UIKIt:UIKit中的控件都是基于Core Graphics实现的 UIBezierPath:UIBezierPath属于UIKit,它是苹果对复杂的Core Graphics进行的封装,方便我们用OC语言进行简单的绘图 Core Graphics:是一套基于C语言的API,支持向量图形,线.形状.图案.路径.剃度.位图图像和pdf 内容的绘

iOS开发中的绘图-Quartz2D-

转载请注明出处:http://blog.csdn.net/whjForWork/article/details/44926763 什么是Quartz2D Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 作用 Quartz 2D能完成的工作 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成PDF 截图\裁剪图片 自定义UI控件 - Quartz2D在iOS开发中的价值 为了便于搭建美观的UI界面,iOS提供了UIKit框架,里面有各种各样的

(转)IOS开发之——绘图(CGContext)

周刊 更多 登录 IOS开发之——绘图(CGContext) 时间 2014-04-21 09:17:43 CSDN博客 原文  http://blog.csdn.net/zhenyu5211314/article/details/24230581 0    CGContextRef context = UIGraphicsGetCurrentCont ext(); 设置上下文 1 CGContextMoveToPoint 开始画线 2 CGContextAddLineToPoint 画直线 4

iOS开发系列-动画绘图CALayer

代码下载地址:https://github.com/wwpeter/WW-MotionDemo.git 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建基础动画.关键帧动画.动画组.转场动画,如何通过UIView的装饰方法对这些动画操作进行简化等.在今天的文章里您可以看到动画操作在iOS中是如何简单和高效,很多原来想做但是苦于没有思路的动画在iOS中将变得越发简单:

文顶顶iOS开发博客链接整理及部分项目源代码下载

文顶顶iOS开发博客链接整理及部分项目源代码下载 网上的iOS开发的教程很多,但是像cnblogs博主文顶顶的博客这样内容图文并茂,代码齐全,示例经典,原理也有阐述,覆盖面宽广,自成系统的系列教程却很难找.如果你是初学者,在学习了斯坦福iOS7公开课和跟着文顶顶的博客做项目之后,最快只需要2个月时间,就基本可以独立完成iOS App的开发工作.有经验的开发者也可以在该博客中寻找代码片段进行学习借鉴,必有所收获. 在此也向@文顶顶 表示严重感谢! 由于文顶顶博客博文繁多,每次找文章需要频繁的翻页,

iOS开发系列--让你的应用“动”起来

--iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建基础动画.关键帧动画.动画组.转场动画,如何通过UIView的装饰方法对这些动画操作进行简化等.在今天的文章里您可以看到动画操作在iOS中是如何简单和高效,很多原来想做但是苦于没有思路的动画在iOS中将变得越发简单: CALayer CALayer简介 CALayer常用属性 CALayer绘图 C