iOS开发CoreGraphics核心图形框架之五——Patterns模型的应用

iOS开发CoreGraphics核心图形框架之五——Patterns模型的应用

一、引言

    Patterns称为模型可能并不直观,说一个场景我们或许就可以更加容易的理解Patterns。在开发中,开发者经常会遇到这样的需求,将某个图片或者某个图形进行平铺作为界面的背景,当然iOS中有现成的方法来将图片转换为背景色进行背景的渲染,但是这种方式并不太灵活,例如背景花纹的着色,背景图片的平铺间距设置等需求都无法满足。Patterns就是用来处理这样的需求。

    Patterns可以理解为一个模型单元,即花纹背景中的一个花纹单元,开发者可以自定义这个单元的绘制内容,一旦创建了CGPatternRef引用,开发者就可以将它向普通颜色一样进行使用,可以进行填充,可以进行路径绘制等。

二、创建CGPatternRef模型引用

    在UIView子类的drawRect:方法中来做如下的测试:

- (void)drawRect:(CGRect)rect {
    // Drawing code
    //创建回调结构体 后面会介绍
    CGPatternCallbacks callback = {0,&drawPatternCallback,&releaseInfoCallback};
    //创建模型引用
    CGPatternRef pattren = CGPatternCreate(NULL, CGRectMake(0, 0, 30,30), CGAffineTransformIdentity, 35, 35, kCGPatternTilingConstantSpacing, false, &callback);
    //创建颜色数组 代表RGBA的值
    static const CGFloat color[4] = { 0, 1, 0, 1 };
    //创建颜色空间
    CGColorSpaceRef baseSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern (baseSpace);
    //设置填充颜色空间
    CGContextSetFillColorSpace (UIGraphicsGetCurrentContext(), patternSpace);
    //设置填充模型
    CGContextSetFillPattern(UIGraphicsGetCurrentContext(), pattren, color);
    //进行填充
    CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, 200, 200));
    
}

上面的示例代码中,有几个地方需要进行介绍:

CGPatternCallBacks是CoreGraphics框架的CGPattern.h文件中定义的一个结构体,这个结构体组合了模型Pattern的版本,创建回调和释放回调。创建回调和释放回调需要传入两个方法块的地址,即block。这两个block的格式定义如下:

//创建模型回调的格式定义
//info参数为需要传递给回调函数的数据
//content参数为所绘制的图形上下文
typedef void (*CGPatternDrawPatternCallback)(void * __nullable info,
                                             CGContextRef cg_nullable context);
//释放回调 开发者可以在其中进行内存的释放
typedef void (*CGPatternReleaseInfoCallback)(void * __nullable info);

我们所实现的drawPatternCallback(),releaseInfoCallback()方法示例如下:

// 绘制 回调
#define PSIZE 16
void drawPatternCallback(void *info,CGContextRef myContext){
//这里我借用了官方文档中的代码 如下的代码将绘制出五角星
    int k;
    double r, theta;
    
    r = 0.8 * PSIZE / 2;
    theta = 2 * M_PI * (2.0 / 5.0); // 144 degrees
    
    CGContextTranslateCTM (myContext, PSIZE/2, PSIZE/2);
    
    CGContextMoveToPoint(myContext, 0, r);
    for (k = 1; k < 5; k++) {
        CGContextAddLineToPoint (myContext,
                                 r * sin(k * theta),
                                 r * cos(k * theta));
    }
    CGContextClosePath(myContext);
    CGContextFillPath(myContext);
}


// 移除 回调
void releaseInfoCallback(void *info) {
   
}

在回过来看创建CGPatternRef的方法:

/*
这个方法
第1个参数为要传递进创建模型方法的信息
第2个参数为设置每个模型单元的尺寸
第3个参数设置模型的几何变换
第4个参数设置模型的整体宽度  通过这个参数可以设置边距
第5个参数设置模型的整体高度  通过这个参数可以设置边距
第6个参数设置模型的渲染方式
第7个参数设置为有色渲染还是无色渲染 
第8个参数设置相关回调结构体
*/
CGPatternRef pattren = CGPatternCreate(NULL, CGRectMake(0, 0, 30,30), CGAffineTransformIdentity, 35, 35, kCGPatternTilingConstantSpacing, false, &callback);

关于模型的渲染方式,需要设置为CGPatternTiling类型的枚举,如下:

typedef CF_ENUM (int32_t, CGPatternTiling) {
    //无失真的平铺 将调整单元之间的间距
    kCGPatternTilingNoDistortion,
    //细微调整单元大小
    kCGPatternTilingConstantSpacingMinimalDistortion,
    //恒定间距,通过调整单元大小实现 会失真
    kCGPatternTilingConstantSpacing
};

CGContextSetFillPattern()方法用于将模型设置为要渲染界面的颜料,之后调用CGContextStrokePath(), CGContextFillPath(), CGContextFillRect()等相关方法都可以实现将模型铺平渲染到指定容器。需要注意,CGContextSetFillPattern()方法中第1个参数为绘图上下文,第2个参数为模型CGPatternRef引用,第3个参数为一个色值数组,这里如果模式是无色渲染方式创建的,需要传入4个元素的RGBA数组,如果是有色模式创建的,需要传入一个透明度值,可以是float类型的指针。

运行工程,效果如下图所示:

将代码简单修改如下,就可以实现以五角星围成的矩形:

- (void)drawRect:(CGRect)rect {
    // Drawing code
    CGPatternCallbacks callback = {0,&drawPatternCallback,&releaseInfoCallback};
    CGPatternRef pattren = CGPatternCreate(NULL, CGRectMake(0, 0, 30,30), CGAffineTransformIdentity, 30, 30, kCGPatternTilingConstantSpacing, false, &callback);
    static const CGFloat color[4] = { 1, 0, 0, 1 };
    CGColorSpaceRef baseSpace;
    CGColorSpaceRef patternSpace;
    baseSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
    patternSpace = CGColorSpaceCreatePattern (baseSpace);
    CGContextSetStrokeColorSpace (UIGraphicsGetCurrentContext(), patternSpace);
    CGContextSetStrokePattern(UIGraphicsGetCurrentContext(), pattren, color);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 40);
    CGContextStrokeRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, 200, 200));
}

效果如下:

三、CGPattern中其他方法

//获取CGPattern在CoreGraphics框架中的id
CFTypeID CGPatternGetTypeID(void);
//进行引用计数加1
CGPatternRef cg_nullable CGPatternRetain(CGPatternRef cg_nullable pattern);
//进行引用计数减1
void CGPatternRelease(CGPatternRef cg_nullable pattern);

专注技术,热爱生活,交流技术,也做朋友。 ——珲少 QQ群:203317592

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逍遥剑客的游戏开发

挑战蓝龙Kalecgos

12820
来自专栏移动开发面面观

GIF格式解析

59450
来自专栏章鱼的慢慢技术路

通过C#脚本实现旋转的立方体

18730
来自专栏Android群英传

Android Vector曲折的兼容之路

26730
来自专栏落影的专栏

Metal入门教程(一)图片绘制

这里是一篇Metal新手教程,先定个小目标:把绘制一张图片到屏幕上。 Metal系列教程的代码地址; OpenGL ES系列教程在这里;

1.1K50
来自专栏進无尽的文章

绘图-Core Graphics

CGContext又叫图形上下文,相当于一块画布,以堆栈形式存放,只有在当前context上绘图才有效。iOS有分多种图形上下文,其中UIView自带提供的在d...

13730
来自专栏腾讯Bugly的专栏

Android自绘动画实现与优化实战——以Tencent OS录音机波形动画为实例

前言 我们所熟知的,Android 的图形绘制主要是基于 View 这个类实现。 每个 View 的绘制都需要经过 onMeasure、onLayout、onD...

47240
来自专栏崔庆才的专栏

滑动宫格验证码都给碰上了?没事儿,看完此文分分钟拿下!

28450
来自专栏简书专栏

基于turtle的Python作画

pendown()的作用是落笔,只有落笔才能作画。 当不作画却想移动画笔的时候要提笔,用函数penup() forward是画笔向前移动,函数当中参数为移动...

78410
来自专栏阿凯的Excel

动态显示下拉框内容

过了冬至,你在北方瑟瑟发抖,我在广东秋风瑟瑟~ 最近小编经常梦回母校~放一张母校的美图! 年底了,又到了预订报刊的时候! 肯定有人会问,这年头还有谁看报刊...

31430

扫码关注云+社区

领取腾讯云代金券