iOS 2D绘图 (Quartz2D)之路径(stroke,fill,clip,subpath,blend)

像往常一样 这个系列的博客是跟着大神的脚步来的。按照往例 在此贴出原博客的出处:

http://blog.csdn.net/hello_hwc?viewmode=list

我对大神的崇拜之情 如滔滔江水 巴拉巴拉的 .........

言归正传

Stroke-描边

影响描边的因素

线的宽度-CGContextSetLineWidth

交叉线的处理方式-CGContextSetLineJoin

线顶端的处理方式-CGContextSetLineCap

进一步限制交叉线的处理方式-CGContextSetMiterLimit

是否要虚线-Line dash Pattern

颜色控件-CGContextSetStrokeColorSpace

画笔颜色-CGContextSetStrokeColor/CGContextSetStrokeColorWithColor

描边模式 -CGContextSetStrokePattern

虚线 画笔颜色 交叉的处理方式 前面的博客已经讲过,这里就不在赘述了。

CGContextSetMiterLimit

如果当前交叉线绘图模式是KCGLineJoinMiter(CGContextSetLineJoin),Quartz 根据设置的miter值来判断线的join是bevel或者miter。
具体的模式是:将miter的长度除以线的宽度,如果小于设置的miterLimit的值,则join style为bevel;

先看看join的三种效果

举个例子可能更加容易明白

CGContextMoveToPoint(context,10,10);
CGContextAddLineToPoint(context, 50, 50);
CGContextAddLineToPoint(context, 10, 90);
CGContextSetLineWidth(context, 10.0);
CGContextSetLineJoin(context, kCGLineJoinMiter);
CGContextSetMiterLimit(context,20.0);

CGContextStrokePath(context);

效果

将Miter设置为1 则效果如下:


Fill 填充

Quartz填充的时候 会认为subpath是封闭的,然后根据规则来填充,有两种规则

1>nonzero winding number rule.沿着当前点,画一条直线到区域外,检查交叉点 如果交叉点从左到右 则加一,从右到左,则减去一。如果结果不为0,则绘制。

2>even-odd rule,沿着当前点,花一条线到区域外,然后检查相交的路径,偶数则绘制,奇数则不绘制。
具体效果如下

相关函数

CGContextEOFillPath-用even-odd rule来填充

CGContextFillPath - 用nonzero winding number rule方式填充

CGContextFillRect/CGContextFillRects-填充指定区域内的path

CGContextFillEllipseInRect-填充椭圆

CGContextDrawPath-绘制当前Path(根据参数stroke/fill)


clip- 切割

顾名思义,根据path只绘制指定的区域,在区域外的都不会绘制。

举个例子 截取圆形区域

效果

注意,切割是和状态相关的,以为这切割以后都是在切割后的context中绘制的。

如果想要保存状态,要进行压栈和出栈处理

代码

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextBeginPath (context);
    CGContextAddArc(context,50, 50,20,0, M_PI * 2,true);
    CGContextClosePath (context);
    CGContextClip (context);
    CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
    CGContextFillRect(context, rect);

    //New Code
    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);

    CGContextMoveToPoint(context,10,10);
    CGContextAddLineToPoint(context, 50, 50);
    CGContextAddLineToPoint(context, 10, 90);

    CGContextSetLineWidth(context, 10.0);
    CGContextSetLineJoin(context, kCGLineJoinMiter);
    CGContextSetMiterLimit(context,20.0);
    CGContextStrokePath(context);
}
-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        self.opaque = NO;
    }
    return self;
}

相关函数

CGContextClip 按照nonzero winding number rule规则切割
CGContextEOClip 按照even-odd规则切割
CGContextClipToRect 切割到指定矩形
CGContextClipToRects 切割到指定矩形组
CGContextClipToMask 切割到mask

Subpath - 子路径

很简单,在stroke/fill或者CGContextBeginPath/CGContextClosePath以后就新开启一个子路径。

注意:

CGContextClosePath,会连接第一个点和最后一个点

Blend 混合模式

Quartz中,默认的颜色混合模式采用如下公式 
result = (alpha * foreground) + (1 - alpha) * background

可以使用CGContextSetBlendMode来设置不同的颜色混合模式,注意设置blend是与context绘制状态相关的,一切与状态相关的设置都要想到状态堆栈

background

foreGround

Normal Blend Mode

 Multiply Blend Mode

交叉部分会显得比较暗,用上一层和底层相乘,至少和一层一样暗

 

 Screen Blend Mode

原文地址:https://www.cnblogs.com/huanying2000/p/6226700.html