导读:本期聚焦于河北彩花创作的《如何用Core Graphics在iOS上绘制股票分时图的坐标轴与网格线?》,敬请观看详情。股票分时图的 readability 很大程度取决于坐标轴与网格线的渲染质量。Core Graphics 作为 iOS 底层绘图框架,提供了完全可控的上下文绘制能力。时间轴标签需要根据交易时段均匀排布,价格轴刻度则要映射最新价与涨跌停区间。直接用 UIView 的 drawRect 配合 CGContext 可以避开第三方图表库的臃肿依赖,但开发者常误把刻度计算放在绘制循环里导致掉帧。本文从坐标系映射原理出发,说明如何用 CGFloat 换算将数据结构转为屏幕点,并给出网格线虚线渲染与标签避免重叠的实用方案。

在 iOS 端自研股票分时图时,Core Graphics 是最常用也最灵活的底层绘图方案。它允许我们在 UIView 的 drawRect 方法中拿到当前的 CGContextRef,通过一系列 C 函数调用完成线条、文字与填充的绘制。相比集成成熟的图表框架,直接使用 Core Graphics 能把绘制逻辑压缩到最少依赖中,同时也要求开发者自己处理坐标映射、刻度计算和网格线样式。本文围绕时间轴标签、价格轴刻度以及网格线渲染三个核心部分,详细说明实现思路与代码细节。

如何用Core Graphics在iOS上绘制股票分时图的坐标轴与网格线?

时间轴标签的排布与绘制

股票分时图的时间轴通常覆盖一个交易日的连续交易时段,例如 A 股的分时从 09:30 到 11:30,再从 13:00 到 15:00,中间有午休缺口。我们在绘制时间轴标签时,首先要确定可用宽度,然后根据需要展示的标签数量做均分。常见做法是固定显示 5 到 7 个时间点,如 09:30、10:30、11:30、13:00、14:00、15:00,避免标签过于密集导致文字重叠。

具体绘制时,可以用 CGContextSetTextMatrixCGContextSetTextDrawingMode 配合 Core Text 或者更简单的 NSStringdrawInRect:withAttributes: 方法。由于 Core Graphics 的上下文坐标系原点在左上角,而 Core Text 默认排版是从左下角起算,若混用需要注意翻转。下面示例在 drawRect 中计算每一个时间标签的 x 坐标并绘制:

- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    NSArray *timeLabels = @[@"09:30", @"10:30", @"11:30", @"13:00", @"14:00", @"15:00"];
    CGFloat plotWidth = rect.size.width - self.leftMargin - self.rightMargin;
    NSDictionary *attr = @{NSFontAttributeName:[UIFont systemFontOfSize:11],
                           NSForegroundColorAttributeName:[UIColor grayColor]};
    for (NSInteger i = 0; i < timeLabels.count; i++) {
        CGFloat x = self.leftMargin + plotWidth * (i * 1.0 / (timeLabels.count - 1));
        NSString *text = timeLabels[i];
        CGSize size = [text sizeWithAttributes:attr];
        CGFloat drawX = x - size.width / 2.0;
        if (drawX < self.leftMargin) drawX = self.leftMargin;
        [text drawAtPoint:CGPointMake(drawX, rect.size.height - 20) withAttributes:attr];
    }
}

上面的代码把时间标签在水平方向按索引均分,并对最左侧标签做了越界修正。实际项目中,如果交易时段不连续,应该把午休缺口从宽度中剔除,或单独用两段线性映射来计算 x 坐标,否则时间轴会显得中间被拉平。标签字体大小也建议随视图宽度动态调整,在窄屏上减少到 10pt 能保证可读性。

价格轴刻度与坐标映射

价格轴的难点在于把业务价格映射到屏幕纵坐标。分时图一般以昨日收盘价为中轴,向上是上涨区间,向下是下跌区间。我们需要先确定最大涨跌幅度,例如普通股票为 ±10%,然后把这一区间映射到图表绘制区域的高度上。假设图表绘制区高度为 h,中轴 y 坐标为 midY,则价格 p 对应的 y 可用公式 y = midY - (p - preClose) / (preClose * 0.1) * (h / 2) 计算。

刻度线通常画在左侧,并标注对应价格。为了避免刻度过于密集,可以每 2% 或 5% 画一条横向参考线,并在左边缘写价格文本。下面示例展示如何根据昨收价与幅度生成价格刻度并绘制:

- (void)drawPriceAxisInContext:(CGContextRef)ctx rect:(CGRect)rect {
    CGFloat preClose = 10.0;
    CGFloat top = rect.origin.y + self.topMargin;
    CGFloat bottom = rect.origin.y + rect.size.height - self.bottomMargin;
    CGFloat midY = (top + bottom) / 2.0;
    CGFloat halfH = (bottom - top) / 2.0;
    NSDictionary *attr = @{NSFontAttributeName:[UIFont systemFontOfSize:11],
                           NSForegroundColorAttributeName:[UIColor darkGrayColor]};
    for (NSInteger percent = -10; percent <= 10; percent += 5) {
        CGFloat price = preClose * (1 + percent / 100.0);
        CGFloat y = midY - (price - preClose) / (preClose * 0.1) * halfH;
        NSString *text = [NSString stringWithFormat:@"%.2f", price];
        [text drawAtPoint:CGPointMake(2, y - 6) withAttributes:attr];
    }
}

这种映射方式把价格轴与涨跌幅度绑定,能直观反映当前价格相对昨收的位置。如果是个股停牌或科创板 ±20% 限制,只需修改分母的 0.1 为对应幅度即可。要注意的是,绘制价格文本时应避免与网格线重叠,可让文本右对齐到固定左边距内,保证数字清晰。

网格线渲染与性能注意事项

网格线用于辅助读取坐标,通常包含横向的价格参考线和纵向的时间参考线。在 Core Graphics 中,我们可以用 CGContextSetLineDash 画出虚线,避免实线过于抢眼。绘制网格应在 drawRect 中统一进行,并且只画必要数量,减少不必要的路径操作。下面给出横向网格线示例:

- (void)drawGridInContext:(CGContextRef)ctx rect:(CGRect)rect {
    CGFloat preClose = 10.0;
    CGFloat top = rect.origin.y + self.topMargin;
    CGFloat bottom = rect.origin.y + rect.size.height - self.bottomMargin;
    CGFloat midY = (top + bottom) / 2.0;
    CGFloat halfH = (bottom - top) / 2.0;
    CGContextSetStrokeColorWithColor(ctx, [UIColor lightGrayColor].CGColor);
    CGContextSetLineWidth(ctx, 0.5);
    CGFloat dash[] = {4, 4};
    CGContextSetLineDash(ctx, 0, dash, 2);
    for (NSInteger percent = -10; percent <= 10; percent += 5) {
        CGFloat price = preClose * (1 + percent / 100.0);
        CGFloat y = midY - (price - preClose) / (preClose * 0.1) * halfH;
        CGContextMoveToPoint(ctx, self.leftMargin, y);
        CGContextAddLineToPoint(ctx, rect.size.width - self.rightMargin, y);
        CGContextStrokePath(ctx);
    }
    CGContextSetLineDash(ctx, 0, NULL, 0);
}

在性能方面,drawRect 会在每次视图标记为需要显示时被调用,因此刻度计算和标签数组不应在绘制时反复创建临时对象。建议把时间标签数组、价格区间等缓存在属性中,只在数据更新时重算。若分时图需要随手势拖动,可以用 setNeedsDisplayInRect: 局部重绘,而不是整个视图重画,从而降低 CPU 占用。

另一个常见误区是开发者把分时折线数据和坐标轴绘制放在同一个循环里,导致坐标逻辑和曲线逻辑耦合,难以维护。更好的做法是分层:先画网格,再画坐标轴标签,最后画分时折线,每层使用独立方法,既清晰又方便单独优化。通过这些细节处理,Core Graphics 完全能胜任流畅的本地股票分时图渲染。

Core_GraphicsiOS绘图股票分时图修改时间:2026-08-18 13:10:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。