Core Graphics 是苹果提供的一种二维图形绘制框架,用于在 iOS、macOS、tvOS 和 watchOS 上高效地绘制矢量图形、图像和路径。它是底层的绘图工具,使用 C 语言接口,功能强大,主要用于开发者需要更高精度和控制权的绘图场景。
在 SwiftUI 中,尽管大部分图形绘制任务可以通过 Path 和 Canvas 完成,但 Core Graphics 的概念和技术依然非常重要,因为 SwiftUI 的许多高级绘图功能(例如自定义形状)依赖于 Core Graphics 的底层实现。
常见数据类型
1、CGContext:绘图上下文;
2、CGPath:路径对象;
3、CGColor:颜色;
4、CGGradient:渐变对象;
5、CGImage:图像;
6、CGFont / CTFont:字体对象;
7、CGColorSpace:颜色空间;
8、CGAffineTransform:仿射变换结构体。
9、CGRect:矩形框架,用于定义二维空间中的位置和大小。
10、CGPoint:表示二维空间中的一个点(x, y 坐标)。
11、CGSize:表示尺寸,包含宽度和高度。
12、CGContext:图形上下文,负责将绘制的内容渲染到屏幕上。
let context = UIGraphicsGetCurrentContext()
context?.move(to: CGPoint(x: 0, y: 0))
context?.addLine(to: CGPoint(x: 100, y: 100))
context?.strokePath()
13、颜色与样式:支持填充(fill)、描边(stroke)、透明度(alpha)等。
context?.setStrokeColor(UIColor.red.cgColor)
context?.setLineWidth(3)
context?.setLineDash(phase: 0, lengths: [5, 2])
CGContext属性和方法
Core Graphics 本身是 C 风格的框架,并不像 Swift 或 SwiftUI 有“属性和方法”的概念,但在 Swift 中,它主要通过 CGContext 对象来访问绘图功能。我们可以理解为:
CGContext 是 Core Graphics 的“命令中心”,几乎所有绘图操作都通过它的方法调用实现。
一、常用绘图样式
1、设置描边颜色:setStrokeColor(_:);
2、设置填充颜色:setFillColor(_:);
3、设置线宽:setLineWidth(_:);
4、设置线帽样式:setLineCap(_:);
5、设置连接点样式:setLineJoin(_:);
6、设置虚线样式:setLineDash(phase:lengths:);
7、设置透明度:setAlpha(_:);
8、设置阴影:setShadow(offset:blur:);
9、设置混合模式:setBlendMode(_:);
10、设置文字绘制模式:setTextDrawingMode(_:)。
二、绘制路径方法
1、移动到某点:move(to:);
2、画线到某点:addLine(to:);
3、添加矩形:addRect(_:);
4、添加圆弧:addArc(center:radius:startAngle:endAngle:clockwise:);
5、添加椭圆:addEllipse(in:);
6、添加路径:addPath(_:);
7、关闭当前路径:closePath();
8、使用路径描边:strokePath();
9、使用路径填充:fillPath()。
注意:Core Graphics 使用“构建路径 → 决定填充或描边”的模式。
三、图像绘制方法
1、绘制图像:draw(_:in:);
2、绘制 PDF 页面:drawPDFPage(_:)(仅 macOS 可用);
3、裁剪区域:clip(to:),clip();
4、创建图像上下文(不在 CGContext 中):UIGraphicsBeginImageContext(…)。
四、状态管理(保存/恢复)
Core Graphics 是状态机式的,可以保存和恢复:
1、保存当前图形状态:saveGState();
2、恢复上一次保存的状态:restoreGState()。
用途:临时设置某种颜色、线宽、坐标变换,然后恢复原始状态。
五、坐标变换
1、平移:translateBy(x:y:);
2、缩放:scaleBy(x:y:);
3、旋转:rotate(by:);
4、应用变换矩阵:concatenate(_:);
5、当前变换矩阵:ctm (只读属性)。
六、渐变与颜色空间
1、创建渐变:CGGradient;
2、绘制线性渐变:drawLinearGradient(…);
3、绘制径向渐变:drawRadialGradient(…);
4、创建颜色空间:CGColorSpaceCreateDeviceRGB() 等。
七、文本绘制(基本)
Core Graphics 本身对文本支持较弱,通常配合 NSString 或 Core Text 使用:
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 20),
.foregroundColor: UIColor.black
]
("Hello" as NSString).draw(at: CGPoint(x: 10, y: 10), withAttributes: attributes)
八、路径填充规则
1、context.setFillRule(.winding) 或 .evenOdd
九、剪裁区域
1、clip(to:) 限制绘图区域(常用于图像遮罩);
2、context.clip() 使用当前路径作为剪裁区域。
十、其他方法示例
1、清除一块区域:clear(_:);
2、绘制带颜色的矩形:fill(_:);
3、设置图形抗锯齿:setShouldAntialias(_:)。
Core Graphics 和 SwiftUI 的关系
SwiftUI 通过 Canvas 和 Path 等组件封装了 Core Graphics 的许多功能,但在需要自定义高性能绘图时,仍可以直接访问 Core Graphics 的底层功能。
SwiftUI 中使用 Core Graphics 的场景
1、自定义绘图:绘制复杂的形状或图像。
2、图形变换:旋转、缩放、平移等操作。
3、高性能需求:在动态更新的复杂图形界面中,Core Graphics 提供了更底层的优化。
SwiftUI 的 Canvas 提供了与 Core Graphics 的接口,例如,使用 Canvas 绘制圆形:
import SwiftUI
struct CoreGraphicsView: View {
var body: some View {
Canvas { context, size in
let center = CGPoint(x: size.width / 2, y: size.height / 2)
let radius = min(size.width, size.height) / 2 - 20
// 使用 Core Graphics 绘制
context.stroke(
Path { path in
path.addArc(center: center, radius: radius, startAngle: .degrees(0), endAngle: .degrees(360), clockwise: false)
},
with: .color(.blue),
lineWidth: 5
)
}
.frame(width: 200, height: 200)
}
}
#Preview {
CoreGraphicsView()
}

典型用法对比
SwiftUI 与 Core Graphics 绘制路径的对比:
1、使用 SwiftUI 的 Path
struct CirclePathView: View {
var body: some View {
Path { path in
path.addArc(center: CGPoint(x: 100, y: 100), radius: 50, startAngle: .degrees(0), endAngle: .degrees(360), clockwise: true)
}
.stroke(Color.red, lineWidth: 2)
}
}
2、UIKit使用 Core Graphics
import UIKit
class CustomView: UIView {
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.addArc(center: CGPoint(x: 100, y: 100), radius: 50, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
context.setStrokeColor(UIColor.red.cgColor)
context.setLineWidth(2)
context.strokePath()
}
}
3、AppKit上使用Core Graphics
import AppKit
class CircleNSView: NSView {
override func draw(_ dirtyRect: NSRect) {
guard let context = NSGraphicsContext.current?.cgContext else { return }
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let radius = min(bounds.width, bounds.height) / 2 - 10
context.setStrokeColor(NSColor.blue.cgColor)
context.setLineWidth(5)
context.addArc(center: center, radius: radius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: false)
context.strokePath()
}
}
总结
Core Graphics可以绘制路径、图像和文本等内容。
Core Graphics 在 UIKit(iOS)和 AppKit(macOS)中的使用方式是有差异的,虽然它们都使用 CGContext,但调用方式、上下文获取方法、颜色/字体的封装对象、坐标系等方面都有明显不同。
UIKit中,通过UIGraphicsGetCurrentContext()(在 UIView.draw(_:) 中使用)获取CGContext。
AppKit中,通过NSGraphicsContext.current?.cgContext(在 NSView.draw(_:) 中使用)获取CGContext。
UIKit和AppKit在使用CGContext还存在以下区别:
1、颜色类型:UIKit使用UIColor,AppKit使用NSColor;
2、字体类型:UIKit使用UIFont,AppKit使用NSFont;
3、坐标系:UIKit原点在左上角,AppKit原点在左下角;
4、视图更新触发:UIKit使用setNeedsDisplay(),AppKit使用needsDisplay = true。
此外,UIKit和AppKit两个平台都支持CALayer、CAShapeLayer,但是iOS视图背后默认使用layer,动画、图层很常用;macOS只有wantsLayer = true后才启用layer。
相关文章
1、SwiftUI绘画视图Canvas:https://fangjunyu.com/2024/12/16/swiftui%e7%bb%98%e7%94%bb%e8%a7%86%e5%9b%becanvas/
2、SwiftUI绘制自定义形状的Path:https://fangjunyu.com/2024/12/16/swiftui%e7%bb%98%e5%88%b6%e8%87%aa%e5%ae%9a%e4%b9%89%e5%bd%a2%e7%8a%b6%e7%9a%84path/