(四十八)Quartz2D引擎进阶

图形上下文栈:

应用,修改过上下文后,下一次画会在这个基础上进行,如果清空状态,需要上下文栈。

可以先把原来的上下文保存起来,然后恢复:

- (void)drawRect:(CGRect)rect {
    
    CGContextRef ref = UIGraphicsGetCurrentContext();
    
    // 保存上下文
    CGContextSaveGState(ref);
    
    CGContextMoveToPoint(ref, 100, 100);
    CGContextAddLineToPoint(ref, 200, 200);
    [[UIColor redColor] set];
    CGContextSetLineCap(ref, kCGLineCapRound);
    CGContextSetLineWidth(ref, 5);
    CGContextStrokePath(ref);
    
    // 恢复上下文
    CGContextRestoreGState(ref);
    
    CGContextMoveToPoint(ref, 250, 200);
    CGContextAddLineToPoint(ref, 100, 180);
    CGContextStrokePath(ref);
    
}

在CGContextRef中有一个专门的空间用于保存上下文的状态,在其内部也有一个区域会把要画的东西先画一遍。

CGContextSaveGState是将ctx拷贝一份,放到栈中,Restore则是出栈。

Tip:CorePlot已经封装好了各种函数图。

矩阵操作:

先设置状态,再画才有作用:注意角度转弧度的时候除以180.0。

第一个是改变缩放比例,第二个是跳转转角。

CGContextScaleCTM(ctx, x_scale, y_scale);
CGContextRotateCTM(ctx, angle / 180.0 * M_PI_2);

图片的裁剪:

先在图像后面画一个形状,然后调用裁剪方法,最后再显示图片,就可以生成裁剪后的图片:

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 50, 50));
    
    CGContextClip(ctx);
    
    CGContextFillPath(ctx);
   
    UIImage *image = [UIImage imageNamed:@"head"];
    
    [image drawInRect:CGRectMake(0, 0, 50, 50)];

注意是先画一个圆,然后在圆心处放一个与圆的外接正方形重合的图片,这样就可以实现圆型裁剪。

注意先添加图形,再执行裁剪,再显示图形,最后显示图片。


刷帧的方法:多次调用绘图函数

注意drawRect只能由系统调用,手动调用无法获得上下文。

调用view的setNeedsDisplay可以让系统调用。

Tip:如果视图没有改变,调用这个方法仍然会重绘。

Tip:在drawRect方法中调用setNeedsDisplay不会引起死循环。

Tip:从storyboard或者xib初始化完成后会调用awakeFromNib,可以在这里做一些初始化的效果,例如定时器。

Tip:1s以上的使用NSTimer,对于高速刷帧,应该使用CADisplayLink方法。

[CADisplayLink displayLinkWithTarget: ... selector: ... ],用link指针指向它。

添加到消息循环的方法:[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSdefaultRunLoop];


上下文显示到iOS手机屏幕,是通过Layer方式显示的。

Window指的是显示在Mac电脑屏幕上。


通过UIKit也可以调用Quarz2D:不需要主动传上下文。

UIRectFill方法可以画矩形,并且不需要传上下文。


通过创建路径的方式来绘图(涉及到内存管理):

实际上,直接使用ctx也是自动创建一个path,下面的过程通过path来绘图:即使是ARC,也需要使用release。

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 1.创建路径
    CGMutablePathRef path = CGPathCreateMutable();
    // 2.拼接路径
    CGPathMoveToPoint(path, NULL, 0, 0);
    CGPathAddLineToPoint(path, NULL, 100, 100);
    // 3.添加路径
    CGContextAddPath(ctx, path);
    // 4.渲染
    CGContextStrokePath(ctx);
    // 5.释放path
    CGPathRelease(path);


注意ColorSpace也是需要释放的。都有相应的Release函数(C语言方式)。

有一个统一的方法,CFRelease,可以释放任何对象。





原文地址:https://www.cnblogs.com/aiwz/p/6154203.html