项目需要一个环形进度条,所以需要弧形的文字显示进度,网上找了一圈没有什么适合的,所以自己封装了一个简单的弧形文字。
效果图如下:
首先我们需要一个结构体来计算出每个glyph的绘制点和偏移角度:
typedef struct GlyphArcInfo {
CGFloat width;
CGFloat angle;
} GlyphArcInfo;
创建上面结构体并赋值:
CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)self.attString);
assert(line != NULL); // 创建排版
CFIndex glyphCount = CTLineGetGlyphCount(line);
if (glyphCount == 0) {
// 获取字符总数
CFRelease(line);
return;
}
GlyphArcInfo *glyphArcInfo = (GlyphArcInfo *)calloc(glyphCount, sizeof(GlyphArcInfo)); // 创建GlyphArcInfo对象数组 GlyphArcInfo包含width和angle
PrepareGlyphArcInfo(line, glyphCount, glyphArcInfo, endAngle - startAngle);
其中PrepareGlyphArcInfo()是赋值的函数,它通过遍历每个CTRun中的glyph,并用单个glyph的width对结构体GlyphArcInfo赋值,并通过每个glyph中心点距离和总行宽的比值计算angle进行赋值:
static void PrepareGlyphArcInfo(CTLineRef line, CFIndex glyphCount, GlyphArcInfo *glyphArcInfo, CGFloat spaceAngle)
{
spaceAngle = -spaceAngle;
NSArray *runArray = (__bridge NSArray *)CTLineGetGlyphRuns(line); // 获取CTRun(字符模块)数组
// Examine each run in the line, updating glyphOffset to track how far along the run is in terms of glyphCount.
CFIndex glyphOffset = 0; // 记录glyphArcInfo数组的当前下标
for (id run in runArray) {
// 遍历CTRun的对象数组
CFIndex runGlyphCount = CTRunGetGlyphCount((__bridge CTRunRef)run); // 获取glyph(字形)的数量
// Ask for the width of each glyph in turn.
CFIndex runGlyphIndex =