1.什么是Quart 2D呢?
不知道,但是可以通过Quart2D绘制图形,自定义控件等等.
2.如何通过Quart 2D绘制图形和自定义控件?
有两种方式:C语言/OC;OC其实最后还是转换成C,那么用C会不会效率稍高?
3.基本图形的绘制
- C语言方式
- 获取当前图形上下文 :
CGContextRef ctx = UIGraphicsGetCurrentContext();
- 绘制图形:
圆:CGContextRef _Nullable c:图形上下文; CGFloat x, CGFloat y:圆心坐标;CGFloat radius:半径;CGFloat startAngle:开始角度;CGFloat endAngle:结束角度;int clockwise:绘制的方向(顺时针还是逆时针)
[CGContextAddArc(CGContextRef _Nullable c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise) ];
椭圆:CGRect rect:一个矩形范围.
[CGContextAddEllipseInRect(CGContextRef _Nullable c, CGRect rect) ];
线:(给定一些点,连接成线) const CGPoint * _Nullable points:CGPoint类型的数组;size_t count:有几个点
[CGContextAddLines(CGContextRef _Nullable c, const CGPoint * _Nullable points, size_t count) ];
矩形:
[CGContextAddRect(CGContextRef _Nullable c, CGRect rect) ];
线:
[CGContextMoveToPoint(CGContextRef _Nullable c, CGFloat x, CGFloat y) ];
[CGContextAddLineToPoint(CGContextRef _Nullable c, CGFloat x, CGFloat y) ]; - 渲染:填充/描边
-
[CGContextStrokePath(CGContextRef _Nullable c) ];//描边
[CGContextFillPath(CGContextRef _Nullable c) ];//填充
- 获取当前图形上下文 :
- OC方式
- 绘制
-
圆:
[UIBezierPath bezierPathWithArcCenter:(CGPoint) radius:(CGFloat) startAngle:(CGFloat) endAngle:(CGFloat) clockwise:(BOOL)];
矩形:
[UIBezierPath bezierPathWithRect:(CGRect)];
圆角矩形:cornerRadius:(CGFloat):圆角实际上通过在矩形边角处绘制圆,然后将弧线外面部分截取掉实现的.此参数代表圆的半径,值越大,边角越圆 [UIBezierPath bezierPathWithRoundedRect:(CGRect) cornerRadius:(CGFloat)];
线:
UIBezierPath *path = [UIBezierPath bezierPath];//首先要获取UIBezierPath对象,调用对象方法画线
[path moveToPoint:(CGPoint)];
[path addLineToPoint:(CGPoint)]; - 渲染
-
UIBezierPath *path = [UIBezierPath bezierPath]; [path fill]; [path stroke];
4.奇偶性原则
有图形A,图形B,图形A,B有部分内容重合,设置使用奇偶性原则,设置填充模式,则重合次数为奇数次填充,偶数次不填充.
CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextAddArc(ctx, 100, 100, 100, 0, M_PI * 2, 0); CGContextAddArc(ctx, 200, 100, 100, 0, M_PI * 2, 0); CGContextDrawPath(ctx, kCGPathEOFill);
增加一行代码,再多画一个圆:
CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextAddArc(ctx, 100, 100, 100, 0, M_PI * 2, 0); CGContextAddArc(ctx, 200, 100, 100, 0, M_PI * 2, 0); CGContextAddArc(ctx, 150, 200, 100, 0, M_PI * 2, 0); CGContextDrawPath(ctx, kCGPathEOFill);
效果:
多出来的三角形:实际上多出来的三角形刚好是三个圆的起点.此种方式默认将图形的路径连接起来了.三角形部分同样遵守奇偶性原则.
OC实现同样的效果:
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:1]; [path addArcWithCenter:CGPointMake(200, 100) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:1]; [path addArcWithCenter:CGPointMake(150, 200) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:1]; path.usesEvenOddFillRule = YES; [path fill];
那么如何才能设置奇偶性,同时又不让各个图形的路径连接起来呢?
OC实现:
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:1]; UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 100) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:1]; [path appendPath:path2]; UIBezierPath *path3 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 200) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:1]; [path appendPath:path3]; path.usesEvenOddFillRule = YES; [path fill];
C实现方式:
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGMutablePathRef path = CGPathCreateMutable(); CGPathAddArc(path, NULL, 100, 100, 100, 0, M_PI * 2, 1);
CGMutablePathRef path2 = CGPathCreateMutable(); CGPathAddArc(path2, NULL, 200, 100, 100, 0, M_PI * 2, 1);
CGMutablePathRef path3 = CGPathCreateMutable(); CGPathAddArc(path3, NULL, 150, 200, 100, 0, M_PI * 2, 1);
CGPathAddPath(path, NULL, path2); CGPathAddPath(path, NULL, path3); CGContextAddPath(ctx, path); CGContextDrawPath(ctx, kCGPathEOFill);
除了这些应该还有很多其他的实现方式.另外,我还是不理解直接直接绘制的方式和通过路径绘制的方有什么区别.
5.非零环绕数规则.
效果:
C实现方式:
CGContextRef ctx = UIGraphicsGetCurrentContext(); CGMutablePathRef path = CGPathCreateMutable(); CGPathAddArc(path, NULL, 200, 200, 50, 0, M_PI * 2, 1); CGMutablePathRef path2 = CGPathCreateMutable(); CGPathAddArc(path2, NULL, 200, 200, 100, 0, M_PI * 2, 0); CGMutablePathRef path3 = CGPathCreateMutable(); CGPathAddArc(path3, NULL, 200, 200, 200, 0, M_PI * 2, 1); CGPathAddPath(path, NULL, path2); CGPathAddPath(path, NULL, path3); CGContextAddPath(ctx, path); CGContextDrawPath(ctx, kCGPathFill);
貌似纯OC代码不能实现,因为如果最后通过函数 CGContextDrawPath(ctx, kCGPathFill);渲染,就必须获取当前图形上下文.而如果不同过该函数渲染,纯OC貌似只有Fill,Stroke两种渲染方式.
CGContextRef ctx = UIGraphicsGetCurrentContext(); UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:50 startAngle:0 endAngle:M_PI * 2 clockwise:1]; UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:0]; UIBezierPath *path3 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:200 startAngle:0 endAngle:M_PI * 2 clockwise:1]; CGContextAddPath(ctx, path.CGPath); CGContextAddPath(ctx, path2.CGPath); CGContextAddPath(ctx, path3.CGPath); CGContextDrawPath(ctx, kCGPathFill);