iOS 2D绘图详解(Quartz 2D)之Transform(CTM,Translate,Rotate,Scale)

前言:Quartz默认采用设备无关的user space来进行绘图,当context(画板)建立之后,默认的坐标系原点以及方向也就确认了,可以通过CTM(current transformation matrix)来修坐标系的原点。从数组图像处理的角度来说,就是对当前context state乘以一个状态矩阵。其中的矩阵运算开发者可以不了解。


以下,会一一个Demo图解,坐标系的位移,旋转,sacle

最初的状态和代码

新建一个CustomView,.m文件

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextAddRect(context, CGRectMake(10,10,40, 20));
    CGContextSetFillColorWithColor(context,[UIColor blueColor].CGColor);
    CGContextFillPath(context);
}
-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        self.opaque = NO;
        self.layer.borderColor = [UIColor lightGrayColor].CGColor;
        self.layer.borderWidth = 1.0;
    }
    return self;
}
@end

调用

  CustomView * customView = [[CustomView alloc] initWithFrame:CGRectMake(100, 100,100, 100)];
    [self.view addSubview:customView];

图解


Translate

假如我们在绘制之前,进行坐标系移动会是什么效果呢?
代码

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context,10, 10);

    CGContextAddRect(context, CGRectMake(10,10,40, 20));
    CGContextSetFillColorWithColor(context,[UIColor blueColor].CGColor);
    CGContextFillPath(context);
}

效果

代码中,我们是还是在(10,10)点绘制,但是要注意,当前坐标系的原点已经移了


Rotate

在Transform的基础上我们再Rotate,45度,注意CGContextRotateCTM传入的参数是弧度
代码

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context,10, 10);
    CGContextRotateCTM(context,M_PI_4);
    CGContextAddRect(context, CGRectMake(10,10,40, 20));
    CGContextSetFillColorWithColor(context,[UIColor blueColor].CGColor);
    CGContextFillPath(context);
}

效果


Scale

对于Scale相对来说,好理解一点,无非就是成比例放大缩小。
这里不花坐标系了
代码

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context,10, 10);
    CGContextRotateCTM(context,M_PI_4);
    CGContextScaleCTM(context,0.5, 0.5);
    CGContextAddRect(context, CGRectMake(10,10,40, 20));
    CGContextSetFillColorWithColor(context,[UIColor blueColor].CGColor);
    CGContextFillPath(context);
}

效果


状态保存,恢复

在复杂的绘图中,我们可能只是想对一个subpath进行旋转移动,缩放。这时候,状态堆栈就起到作用了。
代码

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    //保存状态,入栈
    CGContextSaveGState(context);
    CGContextTranslateCTM(context,10, 10);
    CGContextRotateCTM(context,M_PI_4);
    CGContextScaleCTM(context,0.5, 0.5);
    CGContextAddRect(context, CGRectMake(10,10,40, 20));
    CGContextSetFillColorWithColor(context,[UIColor blueColor].CGColor);
    CGContextFillPath(context);
    CGContextRestoreGState(context);// 推出栈顶部状态

    //这里坐标系已经回到了最开始的状态
    CGContextAddRect(context, CGRectMake(0, 0, 10, 10));
    CGContextFillPath(context);
}

效果


Affine Transforms

可以通过以下方法先创建放射矩阵,然后然后再把放射矩阵映射到CTM

    • CGAffineTransform
    • CGAffineTransformTranslate
    • CGAffineTransformMakeRotation
    • CGAffineTransformRotate
    • CGAffineTransformMakeScale
    • CGAffineTransformScale
posted @   brave-sailor  阅读(776)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
历史上的今天:
2015-10-11 Swift之贪婪的UIButton
2015-10-11 Swift学习之UI开发初探
点击右上角即可分享
微信分享提示