天天看點

iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

什麼是Quartz2D?二維的繪圖引擎

什麼是二維?平面

什麼是引擎?經包裝的函數庫,友善開發者使用。也就是說蘋果幫我們封裝了一套繪圖的函數庫

同時支援iOS和Mac系統什麼意思?用Quartz2D寫的同一份代碼,既可以運作在iphone上又可以運作在mac上,可以跨平台開發。

開發中比較常用的是截屏/裁剪/自定義UI控件。

Quartz2D在iOS開發中的價值就是自定義UI控件。

使用圖形上下文畫圖,要遵循一下四個步驟

1.擷取圖像上下文

2.建立路徑

3.将路徑添加到圖形上下文(add)

4.渲染圖像上下文(fill,stroke)

以下方法請在UIView的drawRect方法中調用~

一.繪制一條直線的方法

#pragma mark - 直接使用圖形上下文畫圖
- (void)oneMethod
{
    //1.擷取圖形上下文,目前我們現在使用的都是UIGraphics開頭,CoreGraphics,項目簡稱CG
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    //2.描述路徑
    //2.1 建立路徑
    CGContextMoveToPoint(ctx, 10, 50);
    //2.2 添加線到一個點
    CGContextAddLineToPoint(ctx, 10,100);
    
    //3.完成路線
    CGContextStrokePath(ctx);

}
#pragma mark - 圖形上下文 + CGPathRef畫線
- (void)twoMethod
{
    //1.擷取圖形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    //2.使用path畫線
    CGMutablePathRef path = CGPathCreateMutable();
    
    //3.添加點
    CGPathMoveToPoint(path, NULL, 20, 50);
    CGPathAddLineToPoint(path, NULL, 20, 100);
    
    //4.将path添加到圖形上下文
    CGContextAddPath(ctx, path);
    
    //5.渲染上下文
    CGContextStrokePath(ctx);
}
#pragma mark - 貝塞爾曲線
- (void)threeMethod
{
    //1.建立路徑
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    //2.畫線
    [path moveToPoint:CGPointMake(30, 50)];
    [path addLineToPoint:CGPointMake(30, 100)];
    
    //3.渲染
    [path stroke];
}
#pragma mark - 圖形上下文 + 貝塞爾曲線
- (void)fourMethod
{
    //1.獲得圖形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    //2.建立路徑
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    //3.畫線
    [path moveToPoint:CGPointMake(40, 50)];
    [path addLineToPoint:CGPointMake(40, 100)];
    
    //4.将path添加到上下文
    CGContextAddPath(ctx, path.CGPath);
    
    //5.渲染
    CGContextStrokePath(ctx);
}

           

二.畫兩個相交的線,并且設定屬性

#pragma mark - 畫兩個相交的線,并設定屬性
- (void)drawTwoLineCrossSetAttribute
{
    //1.擷取圖形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    //2.将繪制路徑,并且将其添加到圖形上下文
    CGContextMoveToPoint(ctx, 123, 45);
    CGContextAddLineToPoint(ctx, 45, 80);
    
    //3.添加另一條線
    CGContextAddLineToPoint(ctx, 223, 159);
    
    //設定顔色
    [[UIColor greenColor] set];
    //設定線的寬度
    CGContextSetLineWidth(ctx, 10);
    //設定連結外的連結類型
    CGContextSetLineJoin(ctx, kCGLineJoinRound);
    //設定線的頭部方式
    CGContextSetLineCap(ctx, kCGLineCapRound);
    
    //4.渲染
    CGContextStrokePath(ctx);
}
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

畫出了兩條有連結的線,其中設定顔色的時候,是區分 設定線的顔色 ,和 設定圖檔的顔色 的,可以設定他們各自的屬性(但是經常設定錯誤),懶得去區分并且保證不會設定錯誤,建議設定

[[UIColor greenColor] set]

就不用考慮實線還是填充圖形了。還有,

CGContextSetLineJoin

是設定連接配接處的樣式,是枚舉,

CGContextSetLineCap

是設定線的頂部的樣式,也是枚舉。

注意:設定各種屬性的時候,一定要記住在渲染之前,否則無效

三.繪制兩條不相交的線,并且設定各自屬性

#pragma mark - 畫兩個不相交的線,并且設定各自屬性
- (void)drawTwoLineNoCrossSetAttribute
{
    //1.建立貝塞爾曲線路徑
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    //2.繪制路徑
    [path moveToPoint:CGPointMake(12, 49)];
    [path addLineToPoint:CGPointMake(68, 34)];
    [[UIColor redColor] set];
    [path setLineWidth:5];
    //3.渲染
    [path stroke];
    
    //繪制第二條路徑
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:CGPointMake(145, 167)];
    [path2 addLineToPoint:CGPointMake(98, 34)];
    [[UIColor greenColor] set];
    [path2 setLineWidth:10];
    [path2 setLineCapStyle:kCGLineCapRound];
    [path2 stroke];
    
}
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

使用貝塞爾曲線畫圖的好處在于,1.每一個貝塞爾底層都有一個圖形上線文,如果是用

CGContextMoveToPoint

畫圖,實際上就是一個圖形上下文,不好去控制,是以建議沒多條線可以使用貝塞爾曲線或者說使用底層的

CGMutablePathRef

畫線,比較靠譜。

四.繪制曲線

#pragma mark - 繪制曲線
- (void)drawQuadCurve
{
    //1.獲得圖形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    //2.設定起點
    CGContextMoveToPoint(ctx, 10, 50);
    
    /**
     *  添加曲線的五個參數
     *
     *  @param c#>   圖形上下文
     *  @param cpx#> 将來要突出的x值
     *  @param cpy#> 要突出的y值
     *  @param x#>   曲線結束時的x
     *  @param y#>   曲線結束時的y
     */
    
    CGContextAddQuadCurveToPoint(ctx, 160, 300, 310, 50);
    
    //設定顔色
    [[UIColor redColor] set];
    //設定寬度
    CGContextSetLineWidth(ctx, 5);
    
    //3.渲染圖層
    CGContextStrokePath(ctx);
}
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

五.繪制帶有圓角邊框的正方形

#pragma mark - 繪制一個帶有圓角邊框的正方形
- (void)drawRoundSquare
{
    //繪制一個空心的圓角矩形
    //1.建立路徑 貝塞爾曲線
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(10, 50, 100, 40) cornerRadius:5];
    //設定顔色
    [[UIColor redColor] set];
    //2.渲染
    [path stroke];
    
    //繪制一個實心的圓角正方形
    //1.建立路徑 貝塞爾曲線
    UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(10, 140, 100, 100) cornerRadius:5];
    //設定顔色
    [[UIColor orangeColor] set];
    //2.渲染
    [path2 fill];
    
    //繪制一個實心的圓
    //1.建立路徑 貝塞爾曲線
    UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(10, 290, 100, 100) cornerRadius:50];
    //設定顔色
    [[UIColor blueColor] set];
    //2.渲染
    [path3 fill];

}
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法
  • 1.

    stroke

    設定邊框的顔色,

    fill

    填充内部的顔色
  • 2.

    fill

    并不是随意使用的,必須是封閉的圖形。
  • 3.可以通過設定圓角是正方形的高度,生成一個原形,但不是最規範繪制原形的方法,不過也可以使用。

六.繪制一個弧度曲線

#pragma mark - 繪制一個弧度曲線
- (void)drawCurve
{
    /**
     *  繪制弧度曲線
     *
     *  @param ArcCenter 曲線中心
     *  @param radius       半徑
     *  @param startAngle 開始的弧度
     *  @param endAngle 結束的弧度
     *  @param clockwise YES順時針,NO逆時針
     */
    
    //繪制一條半圓曲線
    //1.建立路徑 貝塞爾曲線
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:M_PI clockwise:YES];
    [[UIColor redColor] set];
    [path setLineWidth:10];
    [path setLineCapStyle:(kCGLineCapRound)];
    //2.渲染
    [path stroke];
    
    //繪制一條3/4圓曲線
    //1.建立路徑 貝塞爾曲線
    UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 350) radius:50 startAngle:0 endAngle:270/360.0*(M_PI * 2) clockwise:YES];
    [[UIColor yellowColor] set];
    [path2 setLineWidth:10];
    [path2 setLineCapStyle:(kCGLineCapRound)];
    //2.渲染
    [path2 stroke];
    
    //繪制一個圓形曲線
    //1.建立路徑 貝塞爾曲線
    UIBezierPath *path3 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 550) radius:50 startAngle:0 endAngle:(M_PI * 2) clockwise:YES];
    [[UIColor blueColor] set];
    [path3 setLineWidth:10];
    [path3 setLineCapStyle:(kCGLineCapRound)];
    //2.渲染
    [path3 stroke];
    
}
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

1.M_PI是180度.M_PI_2是90°

2.這裡的角度都是弧度制度,如果我們需要15°,可以用15°/180°*π得到。

3.clockwise這個是順時針,如果穿1,就是順時針,穿0,是逆時針

七.繪制一個一個扇形

<span style="font-size:18px;">#pragma mark - 繪制扇形
- (void)drawFanShaped
{
    //1.擷取圖形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //繪制曲線
    CGFloat centerX = 100;
    CGFloat centerY = 100;
    CGFloat radius = 50;
    //2.添加一根線
    CGContextMoveToPoint(ctx, centerX, centerY);
    CGContextAddArc(ctx, centerX, centerY, radius, M_PI, (230 / 360.0)*(M_PI * 2), NO);
    
    //3.關閉線段
    CGContextClosePath(ctx);
    //4.渲染
    CGContextFillPath(ctx);
    
}</span>
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

1.線添加一個點

CGContextMoveToPoint

2.添加一個圓弧

CGContextAddArc

3.閉合繪圖

CGContextClosePath

4.給路徑設定顔色

CGContextStrokePath

,或者給圖形内部設定顔色

CGContextFillPath

5.使用貝塞爾曲線,也要設定閉合路徑

CGContextClosePath

學有所成,來個小練習~

八.簡單下載下傳進度的demo

自定義一個View CustomProgressView.h

@interface CustomProgressView : UIView
@property (nonatomic,assign) CGFloat progressValue;
@end
           

CustomProgressView.m

@implementation CustomProgressView
- (void)setProgressValue:(CGFloat)progressValue
{
    _progressValue = progressValue;
    [self setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect
{
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.center radius:100 startAngle:-M_PI_2 endAngle:(_progressValue / 100.0) *(2 * M_PI) - M_PI_2 clockwise:YES];
    [[UIColor redColor] set];
    [path setLineWidth:10];
    [path setLineCapStyle:(kCGLineCapRound)];
    [path stroke];
}

@end
           

ViewController.m

@interface ViewController ()
@property (nonatomic,retain) UISlider *slider;
@property (nonatomic,retain) CustomProgressView *progressView;
@property (nonatomic,retain) UILabel *label;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.progressView = [[CustomProgressView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width)];
    self.progressView.backgroundColor = [UIColor whiteColor];
    
    self.label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 80, 50)];
    self.label.center = self.progressView.center;
    self.label.textAlignment = NSTextAlignmentCenter;
    [self.progressView addSubview:self.label];
    
    [self.view addSubview:self.progressView];
    
    
    self.slider = [[UISlider alloc]initWithFrame:CGRectMake(10, 500, self.view.frame.size.width - 20, 50)];
    self.slider.minimumValue = 0;
    self.slider.maximumValue = 100;
    [self.slider addTarget:self action:@selector(changeValue:) forControlEvents:(UIControlEventValueChanged)];
    [self.view addSubview:self.slider];
}
- (void)changeValue:(UISlider *)sender
{
    self.progressView.progressValue = sender.value;
    self.label.text = [NSString stringWithFormat:@"%.f%%",sender.value];
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

想調用這個方法

drawRect:(CGRect)rect

,必須要使用

setNeedsDisplay

,其他的無效。

九.餅狀圖

PieView.m

@interface PieView ()
@property (nonatomic,retain) NSArray *nums;
@property (nonatomic,assign) NSInteger total;
@end
@implementation PieView
- (NSInteger)total
{
    if (_total == 0) {
        for (int i = 0; i < self.nums.count ; i ++) {
            _total += [self.nums[i] integerValue];
        }
    }
    return _total;
}
- (NSArray *)nums
{
    if (!_nums) {
        self.nums = @[@"10",@"20",@"30",@"40"];
    }
    return _nums;
}
- (void)drawRect:(CGRect)rect
{
    //繪制一個餅圖
    CGFloat radius = 150;
    CGFloat startA = 0;
    CGFloat endA = 0;
    
    for (int i = 0; i < self.nums.count; i++) {
        NSNumber *num = self.nums[i];
        startA = endA;
        endA = startA + [num floatValue]/self.total * (2 * M_PI);
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.center radius:radius startAngle:startA endAngle:endA clockwise:YES];
        [path addLineToPoint:self.center];
        
        CGFloat randRed = arc4random_uniform(256)/255.0;
        CGFloat randGreen = arc4random_uniform(256)/255.0;
        CGFloat randBlue = arc4random_uniform(256)/255.0;
        UIColor *randomColor = [UIColor colorWithRed:randRed green:randGreen blue:randBlue alpha:1];
        [randomColor set];
        
        [path fill];
    }
}

@end
           

ViewController.m

PieView *pie = [[PieView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    pie.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:pie];
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

十.柱狀圖

BarChartView.h

@interface BarChartView()
@property (nonatomic,retain) NSArray *nums;
@end
@implementation BarChartView
- (NSArray *)nums
{
    if (!_nums) {
        self.nums = @[@"10",@"20",@"30",@"40",@"50",@"60",@"70",@"80"];
    }
    return _nums;
}
- (void)drawRect:(CGRect)rect
{
    //1.擷取圖形上下文
    CGContextRef ctz = UIGraphicsGetCurrentContext();
    //2.繪制圖像
    //設定間距
    CGFloat margin = 30;
    //當柱狀圖的數量多于5的時候縮小它們的間距
    if (self.nums.count > 5) {
        margin = 10;
    }
    //柱狀圖的寬度 = ( view的寬度 - 間隔的總寬度 )/ 柱狀圖的個數
    CGFloat width = (rect.size.width - (self.nums.count + 1) *margin) / self.nums.count;
    for (int i = 0; i < self.nums.count; i++) {
        
        //求出 每一個數字所占的比例
        CGFloat num = [self.nums[i] floatValue]/100;
        //起點位置
        CGFloat x = margin + (width + margin) * i ;
        CGFloat y = rect.size.height * (1 - num);
        CGFloat height = rect.size.height * num;
        
        CGRect rectA = CGRectMake(x, y, width, height);
        CGContextAddRect(ctz, rectA);
        
        CGFloat randRed = arc4random_uniform(256)/255.0;
        CGFloat randGreen = arc4random_uniform(256)/255.0;
        CGFloat randBlue = arc4random_uniform(256)/255.0;
        UIColor *randomColor = [UIColor colorWithRed:randRed green:randGreen blue:randBlue alpha:1];
        
        [randomColor set];
        //渲染
        CGContextFillPath(ctz);
       
    }
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end
           

ViewController.m

BarChartView *view = [[BarChartView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    view.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:view];
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

十一.繪制圖檔

繪制文字和圖檔的時候,是不用去擷取圖像上下文的
-(void)drawRect:(CGRect)rect
{
    //剪切圖檔,超出的圖檔位置都要剪切掉!必須要在繪制之前寫,否則無效
//    UIRectClip(CGRectMake(0, 0, 100, 50));
    
    UIImage *image = [UIImage imageNamed:@"image"];
    
    //獨立
    //在什麼範圍内(原圖大小)
    [image drawInRect:rect];
    
    //在哪個位置開始畫
    [image drawAtPoint:CGPointMake(10, 10)];
    
    //平鋪
    [image drawAsPatternInRect:rect];
}
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法
[image drawInRect:rect]; //拉伸效果
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法
[image drawAtPoint:CGPointMake(10, 10)];//适應效果
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法
[image drawAsPatternInRect:rect];//平鋪效果
           

十二.繪制富文本

- (void)drawRect:(CGRect)rect
{
    NSString *str = @"不管開心與否\n每天都要努力生活\n愛自己\n愛家人";
    //設定文字的屬性
    NSMutableDictionary * paras = [NSMutableDictionary dictionary];
    //設定字型大小
    paras[NSFontAttributeName] = [UIFont systemFontOfSize:40];
    //設定字型顔色
    paras[NSForegroundColorAttributeName] = [UIColor blackColor];
    //設定镂空渲染顔色
    paras[NSStrokeColorAttributeName] = [UIColor orangeColor];
    //設定镂空渲染寬度
    paras[NSStrokeWidthAttributeName] = @3;
    
    //建立陰影對象
    NSShadow *shodow = [[NSShadow alloc] init];
    //陰影顔色
    shodow.shadowColor = [UIColor yellowColor];
    //陰影偏移量
    shodow.shadowOffset = CGSizeMake(5, 6);
    //陰影的模糊半徑
    shodow.shadowBlurRadius = 4;
    //蘋果的富文本就是這樣搞出來的
    paras[NSShadowAttributeName]  = shodow;
    [str drawAtPoint:CGPointZero withAttributes:paras];
}
           
iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

十三.雪花飄動

iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

雪花動畫

//隻有在drawRect方法中才能拿到圖形上下文,才可以畫圖
- (void)drawRect:(CGRect)rect {
    //設定下雪的動畫
    UIImage *image = [UIImage imageNamed:@"snow"];
    _snowY += ;

    [image drawAtPoint:CGPointMake(, _snowY)];
    if (_snowY >= rect.size.height) {
        _snowY = ;
    }
}
// 如果在繪圖的時候需要用到定時器,通常使用CADisplayLink
// NSTimer很少用于繪圖,因為排程優先級比較低,并不會準時調用
- (void)awakeFromNib
{
    // 建立定時器
    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timeChange)];

    // 添加主運作循環
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
// CADisplayLink:每次螢幕重新整理的時候就會調用,螢幕一般一秒重新整理60次
- (void)timeChange{
    [self setNeedsDisplay];
}
           
1.本質就是調用

drawRect

方法,一直重新整理雪花的y值

2.每一次調用

drawRect

,都建立大量的對象,有人說可能性能不好,不過你可能多慮了,沒吃都是在記憶體加載,不會建立新的

UIImage

十四.圖形上下文棧

我自己詳細的介紹了一下,上下文棧,可以看一下~

圖形上下文詳解

十五.圖形上下文矩陣

到底是個啥?

就是圖形上下文畫出的東西永遠是方方正正的,你要是想畫個偏離的矩形,按照過去的方法畫不出來,隻能使用矩陣的方式。分别有偏移,縮放,旋轉

iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

正常尺寸的橢圓

iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

x,y各自平移10px後的橢圓

iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

旋轉後的橢圓

iOS Quartz2D 的從零到一學習使用以下方法請在UIView的drawRect方法中調用~一.繪制一條直線的方法

縮放後的橢圓

- (void)drawRect:(CGRect)rect {
    //圖形上下文矩陣
    //1.畫一個橢圓
    CGContextRef ctx = UIGraphicsGetCurrentContext();
//    CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 100, 100));
    CGPathRef path = CGPathCreateWithEllipseInRect(CGRectMake(, , , ),nil);
    [[UIColor redColor] set];
    //1.偏移
//    CGContextTranslateCTM(ctx, 10, 10);
   //2.旋轉
//    CGContextRotateCTM(ctx, M_PI_4);
    //3.縮放
    CGContextScaleCTM(ctx, , );
    CGContextAddPath(ctx, path);
    CGContextFillPath(ctx);
}
           
1.繪制變化的圖形的步驟
  • 先繪制path
  • 設定圖形上下文矩陣
  • 将path添加到圖形上下文(這一步很重要,一定按照步驟來)
  • 渲染

2.繪圖的時候,我們要使用底層的 CGPathRef,或者貝塞爾,然後 CGContextRef+path的方式。

如不這樣,我注釋的CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 100, 100))方法,這個方法中已經先去添加了path到圖形上下文,即使我們在去添加圖形上下文矩陣,也是無效

3.可以和圖形上下文棧一起使用,給特定的一些圖案設定一些屬性,還有一些不會受到影響

本文為我的實踐所寫,部分執行個體已上傳至GitHub點選打開連結 特别感謝簡書作者王鑫20111無私分享~ 原文傳送門點選打開連結