iOS之QuartZ 2D 繪圖(一)

Quartz2D

  • Quartz2D是蘋果封裝的一個庫,針對iOS和os系統(tǒng)繪制不同的類型的制圖方式

  • 圖形上下文(一種數(shù)據(jù)類型,類似int,double)數(shù)據(jù)類型(CGContextRef)

  • 不同的上下文(數(shù)據(jù)類型)可以繪制不同的類型(pdf,bitmap,layer,window,ptinter)

  • 進而上面5中類型,對應(yīng)不同的上下文

1. 繪制簡單圖形 -> 畫線

  • 在自定義的View我們可以通知drawRect:方法繪制,自己想要的線條
  • 蘋果內(nèi)部已經(jīng)創(chuàng)建了一個layerView上下文關(guān)聯(lián)
01_line.png
/控制器View將要顯示的時候調(diào)用
//-(void)viewWillAppear:(BOOL)animated 方法之后調(diào)用
- (void)drawRect:(CGRect)rect {
    
    //1.獲取上下文
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //2.創(chuàng)建線
    UIBezierPath *path = [UIBezierPath bezierPath];
    //設(shè)置起點
    [path moveToPoint:CGPointMake(50, 200)];
    
    //終點
    [path addLineToPoint:CGPointMake(300, 30)];
    
    //如果在添加線的時候 默認是從終點當做另一條線的起點
    [path addLineToPoint:CGPointMake(300, 250)];
    
    //設(shè)置顏色
    [[UIColor blackColor] set];
    //設(shè)置線寬
    CGContextSetLineWidth(contextRef, 5.0f);
    //設(shè)置鏈接點的 角度 枚舉值
    /*
     kCGLineJoinMiter,
     kCGLineJoinRound,
     kCGLineJoinBevel
     */
    CGContextSetLineJoin(contextRef, kCGLineJoinRound);
    
    //CGContextSetBlendMode(contextRef, kCGBlendModeScreen);
    
    //3.繪制
    //UIBezierPath 是UIKit礦建,需要轉(zhuǎn)化
    CGContextAddPath(contextRef, path.CGPath);
    
    //4.渲染到View上
    CGContextStrokePath(contextRef);
    
}


2.貝塞爾曲線UIBezierPath

  • 蘋果封裝的一個可快速創(chuàng)建繪制圖形的類
  • 其內(nèi)部也是要實現(xiàn):
    • 1.獲取上下文
    • 2.描述路徑
    • 3.把路徑添加到上下文
    • 4.渲染上下文
- (void)drawRect:(CGRect)rect {
    
    //創(chuàng)建路徑
    UIBezierPath *path = [UIBezierPath bezierPath];
    //設(shè)置起點
    
    [path moveToPoint:CGPointMake(50, 50)];
    
    //設(shè)置終點
    
    [path addLineToPoint:CGPointMake(300, 300)];
    
    //繪制 描邊
    [path stroke];
    //1.獲取上下文
    //2.描述路徑
    //3.把路徑添加到上下文
    //4.渲染上下文
    
    
}

2.1UIBezierPath常用的類方法

2.1.1 bezierPathWithRect: 繪制簡單的圖形:矩形,長方形

- (void)drawRect:(CGRect)rect {
    
    //創(chuàng)建路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 200, 200)];
    //描邊
    [path stroke];
    
    
}
03_rect.png

2.1.2bezierPathWithRoundedRect: cornerRadius:

參數(shù)一:要繪制的圖形點 參數(shù)二:是圓角半徑,當圓角半徑等于一半就是圓(寬度和高度相等的情況下)

- (void)drawRect:(CGRect)rect {
    
    //創(chuàng)建路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50, 200, 100) cornerRadius:50];
    path.lineWidth = 10.f;
    
    [path stroke];
    
    
}
04_橢圓.png

2.1.3 繪制圓弧

+ (instancetype)bezierPathWithArcCenter:(CGPoint)center
radius:(CGFloat)radius 
startAngle:(CGFloat)startAngle 
endAngle:(CGFloat)endAngle 
clockwise:(BOOL)clockwise
參數(shù)一: 圓心
參數(shù)二: 半徑
參數(shù)三: 開始的角度
參數(shù)四: 結(jié)束的角度
參數(shù)五; 繪制的方向 (順時針還是逆時針)

   //創(chuàng)建路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.center radius:50 startAngle:M_PI endAngle:0 clockwise:YES];
    path.lineWidth = 10.f;
    [[UIColor redColor] set];
    [path stroke];
    // 起點是0 
    //順時針正
    //逆時針負

05_圓弧.png
2.1.4 UIBezierPath二階曲線

參數(shù)一:終點
參數(shù)二: 控制點
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;

- (void)drawRect:(CGRect)rect {
    
  //創(chuàng)建路徑
    UIBezierPath *path = [UIBezierPath bezierPath];
    //設(shè)置起點
    [path moveToPoint:CGPointMake(50, 200)];
    //設(shè)置終點和控制點
    [path addQuadCurveToPoint:CGPointMake(200, 50) controlPoint:CGPointMake(20, 20)];
    //設(shè)置顏色
    [[UIColor redColor] set];
    //描邊
    [path stroke];
    
}

WX20190514-141555.png
2.1.5UIBezierPath三階曲線
- (void)drawRect:(CGRect)rect {
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    [path moveToPoint:CGPointMake(50, 200)];

    [path addCurveToPoint:CGPointMake(270, 80) controlPoint1:CGPointMake(50, 80) controlPoint2:CGPointMake(200, 200)];
    
    [[UIColor redColor] set];
    
    [path stroke];
    

    
}
WX20190514-142254.png

下載進度的繪制 小demo

  • 可用于 圖片的展示(下載進度)
110.gif

#import "CCDownloadProgressView.h"


@interface CCDownloadProgressView ()

@property (nonatomic, weak) UILabel *progressLabel;


@end


@implementation CCDownloadProgressView

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        
    }
    
    return self;
}


- (void)awakeFromNib{
    [super awakeFromNib];
    
}

//界面顯示的時候調(diào)用
//核心代碼
- (void)drawRect:(CGRect)rect {
    
    //獲取上下文
//    CGContextRef ref = UIGraphicsGetCurrentContext();
    
    //繪制路徑
    CGFloat width = rect.size.width *0.5;
    CGFloat height = rect.size.height *0.5;
    CGPoint center = CGPointMake(width, height);
    CGFloat endAng = 2 *M_PI *self.progress + (-M_PI_2);
    
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:width - 10 startAngle:-M_PI_2 endAngle:endAng clockwise:YES];
    //設(shè)置顏色
    [self.circleColor set];
    //把路徑
    [path stroke];
    
}


- (void)setProgress:(CGFloat)progress {
    _progress = progress;
    
    self.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",progress *100];
    //重新繪制
    [self setNeedsDisplay];
}

- (void)setCircleColor:(UIColor *)circleColor{
    _circleColor = circleColor;
    self.progressLabel.textColor = circleColor;
}


- (void)layoutSubviews {
    [super layoutSubviews];
    
    self.progressLabel.frame = self.bounds;
}


- (UILabel *)progressLabel {
    if (!_progressLabel) {
        
        UILabel *contenLabel = [[UILabel alloc] init];
        contenLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:contenLabel];
        self.progressLabel = contenLabel;
        
    }
    
    return _progressLabel;
}

@end


3. 繪制文字

方法一

- (void)drawAtPoint:(CGPoint)point withAttributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs
缺點:
這個方法 繪制出來的文字不能換行

//繪制文字
- (void)drawRect:(CGRect)rect {
    
    NSString *text = @"這是一個文字的g繪制效果";
    
    //設(shè)置 字體的屬性
    NSDictionary *att = @{
                          NSFontAttributeName:[UIFont systemFontOfSize:20],
                          NSForegroundColorAttributeName:[UIColor redColor]
                          
                          };
    
    [text drawAtPoint:CGPointZero withAttributes:att];
   
  
}


WX20190521-165012.png
方法二
//繪制文字
- (void)drawRect:(CGRect)rect {
    
    NSString *text = @"這是一個文字的g繪制效果,這是一個文字的g繪制效果,這是一個文字的g繪制效果,這是一個文字的g繪制效果,這是一個文字的g繪制效果,這是一個文字的g繪制效果";
    
    NSDictionary *att = @{
                          NSFontAttributeName:[UIFont systemFontOfSize:20],
                          NSForegroundColorAttributeName:[UIColor redColor]
                          
                          };
    [text drawInRect:CGRectMake(0, 0, 300, 300) withAttributes:att];
   
    
}


WX20190521-170925.png
方法三

- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attributes context:(nullable NSStringDrawingContext *)context
這個方法,可以根據(jù)字體的多少,來計算高度
類似我們經(jīng)常使用 計算 文本高度的方法

- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attributes context:(nullable NSStringDrawingContext *)context


//繪制文字
- (void)drawRect:(CGRect)rect {
    
    NSString *text = @"5月20日,習近平赴江西考察調(diào)研。上午,他到了位于贛州市區(qū)的江西金力永磁科技股份有限公司,下午的行程則集中在了贛州于都縣。一周之前的中共中央政治局會議決定,從今年6月開始,在全黨自上而下分兩批開展“不忘初心、牢記使命”主題教育。在主題教育即將開展之際,習近平總書記此次到訪中央紅軍長征集結(jié)出發(fā)地,引人關(guān)注";
    
    NSDictionary *att = @{
                          NSFontAttributeName:[UIFont systemFontOfSize:20],
                          NSForegroundColorAttributeName:[UIColor redColor]
                          
                          };
    
    
    //設(shè)置寬度是300, 告訴是 無線大
    CGSize textSize = CGSizeMake(300, MAXFLOAT);
    
    [text drawWithRect:CGRectMake(0, 0, textSize.width, textSize.height) options:NSStringDrawingUsesLineFragmentOrigin attributes:att context:nil];
   
    
}



WX20190521-173523.png

補充:計算文本高度的方法

方式一
  • boundingRectWithSize:options:attributes:方法,適用于換行的情況,也適用于不換行的情況,為了兼容兩者的方法
   //文本內(nèi)容
       CGSize chatContentSize = [self sizeWithText:text WithMaxSize:CGSizeMake(cellMaxw, MAXFLOAT) fontSize:contentTextFont];
//計算字體寬高

- (CGSize)sizeWithText:(NSString *)text WithMaxSize:(CGSize)maxSize fontSize:(CGFloat)fontSize
{
    
    return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} context:nil].size;
}

方式二
  • sizeWithAttributes:計算文本寬度和高度,不會自動換行

    NSString *text = @"5月20日,習近平赴江西考察調(diào)研。上午,他到了位于贛州市區(qū)的江西金力永磁科技股份有限公司,下午的行程則集中在了贛州于都縣。一周之前的中共中央政治局會議決定,從今年6月開始,在全黨自上而下分兩批開展“不忘初心、牢記使命”主題教育。在主題教育即將開展之際,習近平總書記此次到訪中央紅軍長征集結(jié)出發(fā)地,引人關(guān)注";
    
    NSDictionary *att = @{
                          NSFontAttributeName:[UIFont systemFontOfSize:20],
                          NSForegroundColorAttributeName:[UIColor redColor]
                          
                          };
    
  
    CGSize textSize = [text sizeWithAttributes:att];
    //打印高度
   NSLog(@"%@",NSStringFromCGSize(textSize));

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容