zoukankan      html  css  js  c++  java
  • IOS-Quartz2D

    一、画基本图形

      1 //
      2 //  BWView.m
      3 //  IOS_0221_Quartz2D画矩形
      4 //
      5 //  Created by ma c on 16/2/21.
      6 //  Copyright © 2016年 博文科技. All rights reserved.
      7 //
      8 
      9 #import "BWView.h"
     10 
     11 @implementation BWView
     12 /*
     13  一、什么是Quartz2D
     14  1.Quartz2D是一个二维绘图引擎,同时支持IOS和MAC系统
     15  
     16  2.Quartz2D能完成的工作
     17  1>绘制图形:线条三角形矩形圆形弧
     18  2>绘制文字:
     19  3>绘制生成图片(图像)
     20  4>读取生成PDF
     21  5>裁图裁剪图片
     22  6>自定义UI控件
     23  
     24  3.实例
     25  1>裁剪图片(圆形)
     26  2>涂鸦画板
     27  3>手势解锁
     28  
     29  4.最重要的价值
     30  1>自定义UI控件:因为有些UI界面及其复杂,而且比较个性化,用普通的UI控件根本无法实现,
     31  此时可以利用Quartz2D技术将控件内部结构画出来。
     32  
     33  5.最重要的概念
     34  1>图形上下文
     35  a.图形上下文(Graghics Context):是一个CGContextRef类型的数据
     36  b.作用:
     37  保留绘图信息,绘图状态
     38  决定绘制的输出目标
     39  绘制好的图形 -> (保存)图形上下文 -> (显示)输出目标
     40  c.相同的一套绘制序列,指定不同的Graghics Context,就可以将相同的图像绘制到不同的
     41  目标上。
     42  
     43  2>图形上下文栈
     44  a.将当前的上下文copy一份,保存到栈顶(那个栈叫做”图形上下文栈”)
     45    void CGContextSaveGState(CGContextRef c)
     46  b.将栈顶的上下文出栈,替换掉当前的上下文
     47    void CGContextRestoreGState(CGContextRef c)
     48 
     49  6.Quartz2D提供了以下几种类型的Graghics Context:
     50  1>Bitmap Graphics Context
     51  2>PDF Graphics Context
     52  3>Window Graghics Context
     53  4>Layer Graghics Context
     54  5>Printer Graghics Context
     55  
     56  7.如何利用Quartz2D自定义view
     57  1>新建一个类,继承自UIView
     58  2>实现 -(void)drawRect:(CGRect)rect方法
     59  a.取得跟当前view相关联的图形上下文
     60  b.绘制相应的图形内容
     61  c.利用图形上下文将绘制的所有内容显示到view上面
     62  
     63  8.常识:
     64  1>绘图顺序:后绘制的图形覆盖前一个图形
     65  2>Quartz2D的API是纯C语言
     66  3>Quartz2D的API来自于Core Graphics框架
     67  4>数据类型和函数基本都以CG作为前缀
     68  
     69  9.drawRect:中取得的上下文
     70  1>在drawRect:方法中取得上下文后,就可以绘制东西到view上
     71  2>View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,
     72    因此,绘制的东西其实是绘制到view的layer上去了
     73  3>View之所以能显示东西,完全是因为它内部的layer
     74  4>为什么要实现drawRect:方法才能绘图到view上?
     75    因为在drawRect:方法中才能取得跟view相关联的图形上下文
     76  5>drawRect:方法在什么时候被调用?
     77    当view第一次显示到屏幕上时(被加到UIWindow上显示出来)
     78    调用view的setNeedsDisplay或者setNeedsDisplayInRect:时
     79 
     80  
     81  10.Quartz2D绘图的代码步骤
     82  1>获得图形上下文
     83    CGContextRef ctx = UIGraphicsGetCurrentContext();
     84  2>拼接路径(下面代码是搞一条线段)
     85    CGContextMoveToPoint(ctx, 10, 10);
     86    CGContextAddLineToPoint(ctx, 100, 100);
     87  3>绘制路径
     88    CGContextStrokePath(ctx); // CGContextFillPath(ctx);
     89  
     90  11.常用拼接路径函数
     91  1>新建一个起点
     92    void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)
     93  2>添加新的线段到某个点
     94    void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)
     95  3>添加一个矩形
     96    void CGContextAddRect(CGContextRef c, CGRect rect)
     97  4>添加一个椭圆
     98    void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)
     99  5>添加一个圆弧
    100    void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,
    101    CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
    102  
    103  12.常用绘制路径函数
    104  1>Mode参数决定绘制的模式
    105    void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)
    106  2>绘制空心路径
    107    void CGContextStrokePath(CGContextRef c)
    108  3>绘制实心路径
    109    void CGContextFillPath(CGContextRef c)
    110    提示:一般以CGContextDraw、CGContextStroke、CGContextFill开头的函数,都是用来绘制路径的
    111  
    112  */
    113 
    114 // Only override drawRect: if you perform custom drawing.
    115 // An empty implementation adversely affects performance during animation.
    116 - (void)drawRect:(CGRect)rect {
    117     
    118     //drawRectangle();
    119     //drawLine();
    120     //drawCircle();
    121     //drawArc();
    122     //drawCurve();
    123     
    124 }
    125 ///画曲线
    126 void drawCurve()
    127 {
    128     // 1.获得上下文
    129     CGContextRef ctf = UIGraphicsGetCurrentContext();
    130     
    131     CGRect rect = CGRectMake(50, 50, 100, 100);
    132     
    133     //中间控制点
    134     CGFloat controlX = rect.size.width * 0.5;
    135     CGFloat controlY = rect.size.height * 0.5;
    136     
    137     //当前点
    138     CGFloat marginX = 20;
    139     CGFloat marginY = 10;
    140     CGFloat currentX = controlX - marginX;
    141     CGFloat currentY = controlY - marginY;
    142     CGContextMoveToPoint(ctf, currentX, currentY);
    143     
    144     //结束点
    145     CGFloat endX = controlX + marginX;
    146     CGFloat endY = currentY;
    147     
    148     //贝塞尔曲线
    149     CGContextAddQuadCurveToPoint(ctf, controlX, controlY, endX, endY);
    150     
    151     // 2.渲染
    152     CGContextStrokePath(ctf);
    153 }
    154 
    155 ///画圆弧
    156 void drawArc()
    157 {
    158     // 1.获得上下文
    159     CGContextRef ctf = UIGraphicsGetCurrentContext();
    160     
    161     // 2.画1/4圆
    162     CGContextMoveToPoint(ctf, 100, 50);
    163     CGContextAddLineToPoint(ctf, 100, 100);
    164     
    165     //画圆弧
    166     /*
    167             x/y:圆心
    168          radius:半径
    169      startAngle:开始角度
    170        endAngle:结束角度
    171       clockwise:圆弧的伸展方向(0:顺时针,1:逆时针)
    172      */
    173     CGContextAddArc(ctf, 100, 50, 50, M_PI_2, M_PI, 0);
    174     
    175     // 关闭路径(连接起点和最后一个点)
    176     CGContextClosePath(ctf);
    177     
    178     // 设置颜色
    179     [[UIColor redColor] set];
    180 
    181     // 3.显示
    182     CGContextFillPath(ctf);
    183 
    184 }
    185 
    186 ///画圆
    187 void drawCircle()
    188 {
    189     // 1.获得上下文
    190     CGContextRef ctf = UIGraphicsGetCurrentContext();
    191     
    192     // 2.画圆
    193     CGContextAddEllipseInRect(ctf, CGRectMake(60, 30, 100, 100));
    194     
    195     // 3.显示
    196     CGContextStrokePath(ctf);
    197 }
    198 
    199 ///画线
    200 void drawLine()
    201 {
    202     // 1.获得上下文
    203     CGContextRef ctf = UIGraphicsGetCurrentContext();
    204     
    205     
    206     //2.画线
    207     
    208     //拷贝当前上下文放到栈中
    209     CGContextSaveGState(ctf);
    210     
    211     // 设置线宽
    212     CGContextSetLineWidth(ctf, 5);
    213     // 设置颜色
    214     CGContextSetRGBStrokeColor(ctf, 1, 1, 0.1, 1);
    215     // 设置线段头尾部样式
    216     CGContextSetLineCap(ctf, kCGLineCapRound);
    217     // 设置线段转折点样式
    218     CGContextSetLineJoin(ctf, kCGLineJoinRound);
    219 
    220     //设置起点
    221     CGContextMoveToPoint(ctf, 10, 10);
    222     //添加一条线段到(100,100)
    223     CGContextAddLineToPoint(ctf, 100, 100);
    224     // 渲染显示到view上面
    225     CGContextStrokePath(ctf);
    226 
    227     //将栈顶的上下文出栈,替换当前的上下文
    228     CGContextRestoreGState(ctf);
    229 
    230     //设置起点
    231     CGContextMoveToPoint(ctf, 100, 50);
    232     //添加一条线段到(100,100)
    233     CGContextAddLineToPoint(ctf, 200, 100);
    234     CGContextAddLineToPoint(ctf, 230, 50);
    235     // 渲染显示到view上面
    236     CGContextStrokePath(ctf);
    237 }
    238 
    239 ///画矩形
    240 void drawRectangle()
    241 {
    242     // 1.获得上下文
    243     CGContextRef ctf = UIGraphicsGetCurrentContext();
    244     
    245     // 2.画矩形
    246     CGContextAddRect(ctf, CGRectMake(10, 10, 100, 100));
    247     
    248     // 3.绘制图形
    249     //CGContextStrokePath(ctf);
    250     CGContextFillPath(ctf);
    251 }
    252 
    253 ///画三角形
    254 void drawTriangle()
    255 {
    256     // 1.获得上下文
    257     CGContextRef ctf = UIGraphicsGetCurrentContext();
    258     
    259     // 2.拼接图形(路径)
    260     // 画三角形
    261     CGContextMoveToPoint(ctf, 0, 0);
    262     CGContextAddLineToPoint(ctf, 100, 100);
    263     CGContextAddLineToPoint(ctf, 150, 80);
    264     // 关闭路径(连接起点和最后一个点)
    265     CGContextClosePath(ctf);
    266     
    267     // 3.绘制图形
    268     CGContextStrokePath(ctf);
    269     
    270 }
    271 
    272 @end

    二、画文字和图片

     1 //
     2 //  DrawTextAndImgView.m
     3 //  IOS_0221_Quartz2D画矩形
     4 //
     5 //  Created by ma c on 16/2/21.
     6 //  Copyright © 2016年 博文科技. All rights reserved.
     7 //
     8 
     9 #import "DrawTextAndImgView.h"
    10 
    11 @implementation DrawTextAndImgView
    12 
    13 
    14 // Only override drawRect: if you perform custom drawing.
    15 // An empty implementation adversely affects performance during animation.
    16 - (void)drawRect:(CGRect)rect {
    17     
    18 //    drawText();
    19 //    drawImage();
    20 }
    21 
    22 ///画图片
    23 void drawImage()
    24 {
    25     // 1.取得图片
    26     UIImage *img = [UIImage imageNamed:@"1.jpg"];
    27     
    28     // 2.画
    29 //    [img drawAtPoint:CGPointMake(30, 0)];
    30 //    [img drawInRect:CGRectMake(50, 10, 100, 100)];
    31     [img drawAsPatternInRect:CGRectMake(0, 0, 400, 200)];
    32 }
    33 
    34 ///画文字
    35 void drawText()
    36 {
    37     
    38     //方法一 使用OC
    39     NSString *str = @"bowen,哈喽";
    40     NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    41     dict[NSForegroundColorAttributeName] = [UIColor redColor];
    42     dict[NSFontAttributeName] = [UIFont systemFontOfSize:30];
    43     //[str drawAtPoint:CGPointZero withAttributes:nil];
    44     [str drawInRect:CGRectMake(50, 50, 100, 100) withAttributes:dict];
    45     
    46     //方法二 使用C
    47     // 1.获得上下文
    48     CGContextRef ctf = UIGraphicsGetCurrentContext();
    49     // 2.画文字
    50     
    51     // 3.渲染显示
    52     CGContextStrokePath(ctf);
    53 }
    54 
    55 @end

    三、实用技术

      1 //
      2 //  MatrixOperation.m
      3 //  IOS_0221_Quartz2D画矩形
      4 //
      5 //  Created by ma c on 16/2/21.
      6 //  Copyright © 2016年 博文科技. All rights reserved.
      7 //
      8 
      9 #import "MatrixOperation.h"
     10 
     11 @implementation MatrixOperation
     12 /*
     13  1.利用矩阵操作,能让绘制到上下文中的所有路径一起发生变化
     14  缩放
     15  void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)
     16  旋转
     17  void CGContextRotateCTM(CGContextRef c, CGFloat angle)
     18  平移
     19  void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)
     20  
     21  2.裁剪
     22  CGContextClip(CGContextRef ctf);
     23  
     24  3.重绘,刷帧
     25  [self setNeedsDisplay];
     26  
     27  4.屏幕截图
     28  - (void)renderInContext:(CGContextRef)ctx;
     29  调用某个view的layer的renderInContext:方法即可
     30 
     31 
     32  */
     33 
     34 /*
     35  默认只在第一次显示的时候调用(只能由系统自动调用)
     36 */
     37 - (void)drawRect:(CGRect)rect {
     38 //    matrix();
     39 //    cut();
     40 //    brush(self.radius);
     41     
     42 //    customControl(self.image, rect);
     43     
     44 }
     45 
     46 ///矩阵操作
     47 void matrix()
     48 {
     49     CGContextRef ctf = UIGraphicsGetCurrentContext();
     50     
     51     //矩阵操作
     52 //    CGContextScaleCTM(ctf, 0.5, 0.5);
     53 //    CGContextRotateCTM(ctf, M_PI_2 * 0.2);
     54 //    CGContextTranslateCTM(ctf, 50, 50);
     55     
     56     CGContextAddRect(ctf, CGRectMake(10, 10, 50, 50));
     57     CGContextAddEllipseInRect(ctf, CGRectMake(100, 40, 100, 100));
     58     CGContextMoveToPoint(ctf, 100, 40);
     59     CGContextAddLineToPoint(ctf, 200, 150);
     60     
     61     CGContextStrokePath(ctf);
     62 
     63 }
     64 
     65 ///裁剪
     66 void cut()
     67 {
     68     CGContextRef ctf = UIGraphicsGetCurrentContext();
     69     
     70     CGContextAddEllipseInRect(ctf, CGRectMake(100, 100, 50, 50));
     71     
     72     //裁剪
     73     CGContextClip(ctf);
     74     
     75     CGContextStrokePath(ctf);
     76     
     77     UIImage *img = [UIImage imageNamed:@"1.jpg"];
     78     [img drawAtPoint:CGPointMake(100, 100)];
     79 }
     80 
     81 
     82 ///重绘,刷帧
     83 void brush(float radius)
     84 {
     85     CGContextRef ctf = UIGraphicsGetCurrentContext();
     86     CGContextAddArc(ctf, 60, 60, radius, 0, M_PI * 2, 0);
     87     CGContextFillPath(ctf);
     88 }
     89 - (void)setRadius:(float)radius
     90 {
     91     _radius = radius;
     92     //重绘(这个方法内部会重新调用drawRect:方法进行绘制)
     93     [self setNeedsDisplay];
     94 }
     95 
     96 ///自定义UIImageView控件
     97 void customControl(UIImage *image, CGRect rect)
     98 {
     99     [image drawInRect:rect];
    100 }
    101 - (void)setImage:(UIImage *)image
    102 {
    103     _image = image;
    104     [self setNeedsDisplay];
    105 }
    106 
    107 
    108 ///nib文件加载完毕时调用
    109 - (void)awakeFromNib
    110 {
    111     
    112 }
    113 
    114 @end
      1 //
      2 //  ViewController.m
      3 //  IOS_0221_Quartz2D画矩形
      4 //
      5 //  Created by ma c on 16/2/21.
      6 //  Copyright © 2016年 博文科技. All rights reserved.
      7 //
      8 
      9 #import "ViewController.h"
     10 #import "MatrixOperation.h"
     11 
     12 @interface ViewController ()
     13 
     14 @property (weak, nonatomic) IBOutlet UIImageView *imgView;
     15 - (IBAction)valueChange:(UISlider *)sender;
     16 @property (weak, nonatomic) IBOutlet MatrixOperation *brushView;
     17 - (IBAction)clip:(UIButton *)sender;
     18 
     19 @end
     20 
     21 @implementation ViewController
     22 
     23 - (void)viewDidLoad {
     24     [super viewDidLoad];
     25     
     26 //    [self watermark];
     27     [self picCut2];
     28 }
     29 ///图片裁剪(圆环)
     30 - (void)picCut2
     31 {
     32     // 1.加载原图
     33     UIImage *oldImage = [UIImage imageNamed:@"me.png"];
     34     
     35     // 2.开启上下文
     36     CGFloat borderW = 2; // 圆环的宽度
     37     CGFloat imageW = oldImage.size.width + 2 * borderW;
     38     CGFloat imageH = oldImage.size.height + 2 * borderW;
     39     CGSize imageSize = CGSizeMake(imageW, imageH);
     40     UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
     41     
     42     // 3.取得当前的上下文
     43     CGContextRef ctx = UIGraphicsGetCurrentContext();
     44     
     45     // 4.画边框(大圆)
     46     [[UIColor redColor] set];
     47     CGFloat bigRadius = imageW * 0.5; // 大圆半径
     48     CGFloat centerX = bigRadius; // 圆心
     49     CGFloat centerY = bigRadius;
     50     CGContextAddArc(ctx, centerX, centerY, bigRadius, 0, M_PI * 2, 0);
     51     CGContextFillPath(ctx); // 画圆
     52     
     53     // 5.小圆
     54     CGFloat smallRadius = bigRadius - borderW;
     55     CGContextAddArc(ctx, centerX, centerY, smallRadius, 0, M_PI * 2, 0);
     56     // 裁剪(后面画的东西才会受裁剪的影响)
     57     CGContextClip(ctx);
     58     
     59     // 6.画图
     60     [oldImage drawInRect:CGRectMake(borderW, borderW, oldImage.size.width, oldImage.size.height)];
     61     
     62     // 7.取图
     63     UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
     64     
     65     // 8.结束上下文
     66     UIGraphicsEndImageContext();
     67     
     68     // 9.显示图片
     69     self.imgView.image = newImage;
     70     
     71     // 10.写出文件
     72     NSData *data = UIImagePNGRepresentation(newImage);
     73     NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"new.png"];
     74     [data writeToFile:path atomically:YES];
     75 }
     76 
     77 ///图片裁剪(圆)
     78 - (void)picCut1
     79 {
     80     //1.加载原图
     81     UIImage *image = [UIImage imageNamed:@"me.png"];
     82     //2.开启上下文
     83     UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0);
     84     //3.取得当前上下文
     85     CGContextRef ctf = UIGraphicsGetCurrentContext();
     86     //4.画圆
     87     CGRect circleRect = CGRectMake(0, 0, image.size.width, image.size.height);
     88     CGContextAddEllipseInRect(ctf, circleRect);
     89     //5.按照当前形状裁剪,超出这个形状以外内容不显示
     90     CGContextClip(ctf);
     91     //6.画图
     92     [image drawInRect:circleRect];
     93     //7.取图
     94     UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
     95     //8.结束
     96     UIGraphicsEndImageContext();
     97     //9.写入文件
     98     NSData *data = UIImagePNGRepresentation(image);
     99     NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    100     [data writeToFile:path atomically:YES];
    101     //10.显示图片
    102     self.imgView.image = newImage;
    103     
    104 }
    105 
    106 ///制作水印
    107 - (void)watermark
    108 {
    109     UIImage *bgImg = [UIImage imageNamed:@"scene.png"];
    110     
    111     //上下文:基于位图(bitmap),所有的东西需要绘制到新的图片上去
    112     
    113     //1.创建一个基于位图的上下文
    114     UIGraphicsBeginImageContextWithOptions(bgImg.size, NO, 0.0);
    115     //2.画背景
    116     [bgImg drawInRect:CGRectMake(0, 0, bgImg.size.width, bgImg.size.height)];
    117     //3.画水印
    118     UIImage *waterImg = [UIImage imageNamed:@"logo.png"];
    119     CGFloat scale = 0.2;
    120     CGFloat margin = 5;
    121     CGFloat waterW = waterImg.size.width * scale;
    122     CGFloat waterH = waterImg.size.height * scale;
    123     CGFloat waterX = bgImg.size.width - waterW - margin;
    124     CGFloat waterY = bgImg.size.height - waterH - margin;
    125     [waterImg drawInRect:CGRectMake(waterX, waterY, waterW, waterH)];
    126     //4.从上下文中取得制作完毕的UIImage对象
    127     UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    128     //5.结束上下文
    129     UIGraphicsEndImageContext();
    130     //6.显示到UIImageView
    131     self.imgView.image = newImage;
    132     //7.将image对象压缩为PNG格式的二进制数据
    133     NSData *data = UIImagePNGRepresentation(newImage);
    134     //8.写入文件
    135     NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    136     [data writeToFile:path atomically:YES];
    137 }
    138 ///截图
    139 - (IBAction)clip:(UIButton *)sender {
    140     
    141     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    142         
    143         //1.开启上下文
    144         UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0.0);
    145         //2.将控制器的view的layer渲染到上下文
    146         [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    147         //3.取出图片
    148         UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    149         NSData *data = UIImagePNGRepresentation(newImage);
    150         [data writeToFile:@"/Users/mac/Desktop/a.png" atomically:YES];
    151         //4.结束上下文
    152         UIGraphicsEndImageContext();
    153     });
    154 }
    155 
    156 ///创建自定义ImageView
    157 - (void)createimgView
    158 {
    159     MatrixOperation *imgView = [[MatrixOperation alloc] init];
    160     imgView.frame = CGRectMake(100, 100, 100, 100);
    161     UIImage *img = [UIImage imageNamed:@"1.jpg"];
    162     imgView.image = img;
    163     [self.view addSubview:imgView];
    164 }
    165 
    166 - (IBAction)valueChange:(UISlider *)sender {
    167     
    168     self.brushView.radius = sender.value;
    169 }
    170 
    171 @end
  • 相关阅读:
    linux系统分区表修复
    centos 系统下彻底删除mysql
    mysql数据类型
    mysq 数据库基本管理
    centos 网卡聚合及Cisco交换机链路聚合
    Dell 服务器安装方法介绍
    linux分区之gpt(大于2T的分区)
    windows server 2008 远程桌面连接数修改--无限连接
    C# WinForm控件美化扩展系列之ListBox
    C# 文件 文件夹
  • 原文地址:https://www.cnblogs.com/oc-bowen/p/5205285.html
Copyright © 2011-2022 走看看