Core Graphics là framework kết xuất 2D của Apple, thuộc Core Foundation, có sẵn trên iOS, macOS, tvOS và watchOS. Nó cung cấp API C cấp thấp để làm việc với đồ họa vector và raster, bao gồm vẽ đường viền, gradient, bóng, hình ảnh và văn bản. Core Graphics là nền tảng cho UIKit, SwiftUI và AppKit. Theo Apple Developer Documentation, 2026, framework này được sử dụng trong hơn 90% ứng dụng iOS, vì mọi phần tử hiển thị đều đi qua Core Graphics hoặc phần cứng tương đương.
Điểm chính
Core Graphics (còn được gọi là Quartz 2D) là framework triển khai công cụ đồ họa 2D của Apple. Nó dựa trên thư viện đồ họa di động Quartz và sử dụng mô hình vẽ dựa trên trang, nơi mỗi hành động là một lệnh trong chuỗi giống như vẽ trên giấy. Core Graphics hỗ trợ khử răng cưa, độ trong suốt (pha trộn alpha) và không gian màu ICC.
Kiến trúc Core Graphics được xây dựng xung quanh một ngữ cảnh đồ họa (CGContext) đóng gói thiết bị đầu ra mục tiêu — màn hình, máy in, tài liệu PDF hoặc bộ đệm raster. Ngữ cảnh quản lý các cài đặt hiện tại: màu sắc, độ dày đường, biến đổi, vùng cắt và phông chữ. Cách tiếp cận này cung cấp API thống nhất cho các thiết bị đầu ra khác nhau mà không thay đổi mã vẽ.
Core Graphics chủ yếu hoạt động trên CPU, sử dụng mô hình vector (không phụ thuộc độ phân giải). Điều này có nghĩa là các đường và đường cong được raster hóa ở độ phân giải thiết bị hiện tại khi vẽ. Không giống như Metal, Core Graphics không yêu cầu quản lý tài nguyên GPU rõ ràng — hệ thống xử lý tất cả tối ưu hóa. Đối với hầu hết các tác vụ 2D (đồ họa, biểu đồ, phần tử UI tùy chỉnh), hiệu suất của Core Graphics đủ để duy trì 60 FPS.
Core Graphics bao gồm khoảng 50 loại cơ bản (loại không trong suốt), mỗi loại chịu trách nhiệm cho một chức năng cụ thể. Tất cả các loại tuân theo quy tắc quản lý bộ nhớ Core Foundation: được tạo thông qua các hàm có Create trong tên, yêu cầu gọi CGRelease và không tương thích ARC trong Objective-C (tuy nhiên Swift tự động quản lý bộ nhớ thông qua chú thích CF_RETURNS_RETAINED).
CGContext — ngữ cảnh vẽ, loại trung tâm của framework. CGPath — đường viền vector bất biến. CGColor — màu sắc với không gian màu được chỉ định. CGGradient — tô gradient. CGImage — hình ảnh raster. CGLayer — bộ đệm ngoại tuyến được tối ưu hóa cho vẽ lặp lại. CGDataProvider — nguồn dữ liệu cho hình ảnh. CGColorSpace — không gian màu (sRGB, Display P3, Gray).
Mỗi loại được thiết kế với chi phí tối thiểu: CGPath có thể được lưu vào bộ nhớ đệm và tái sử dụng giữa các ngữ cảnh khác nhau, CGColor được chuyển đổi thành biểu diễn phần cứng GPU khi truyền, CGLayer lưu trữ nội dung đã được raster hóa trước. Kiến trúc này cho phép Core Graphics hoạt động hiệu quả cả trong các tác vụ UI đơn giản và trình chỉnh sửa đồ họa chuyên nghiệp.
| Loại | Mục đích | Quản lý bộ nhớ |
|---|---|---|
| CGContext | Ngữ cảnh đồ họa | CFRelease hoặc tự động trong Swift |
| CGPath | Đường viền vector | CFRelease (bất biến) |
| CGColor | Màu trong không gian màu | CFRelease hoặc CGColorCreate |
| CGImage | Hình ảnh raster | CFRelease (sau khi tạo) |
| CGLayer | Bộ đệm ngoại tuyến | CFRelease hoặc CGLayerCreate |
CGPath là đối tượng bất biến mô tả một chuỗi các đoạn hình học: đường thẳng, đường cong Bezier, cung và đóng. Không giống như UIBezierPath, CGPath không chứa phương thức vẽ — nó chỉ lưu trữ hình học. Để vẽ, CGPath được thêm vào ngữ cảnh (CGContextAddPath) và sau đó được kết xuất qua strokePath hoặc fillPath. Tính bất biến đảm bảo an toàn luồng và khả năng lưu vào bộ nhớ đệm.
CGPathCreateMutable tạo một đường dẫn có thể thay đổi (CGMutablePathRef) để xây dựng từng bước. Sau khi lắp ráp cuối cùng, nó được chuyển đổi thành CGPathRef bất biến. Apple khuyến nghị giảm thiểu số lượng điểm trong CGPath — các đường viền quá phức tạp (hơn 1000 đoạn) làm chậm quá trình raster hóa. Để tối ưu hóa, hãy sử dụng CGPathCreateCopyBySimplifyingPath, loại bỏ các điểm cộng tuyến dư thừa.
Để tạo hoạt ảnh hình dạng giữa hai đối tượng CGPath, bạn có thể sử dụng CABasicAnimation trên thuộc tính path của CAShapeLayer. Hạn chế: cả hai CGPath phải có cùng số lượng đoạn (điểm kiểm soát). Hàm CGPathApply cho phép bạn duyệt qua tất cả các phần tử của đường dẫn và so sánh cấu trúc của chúng. Nếu các đoạn không khớp, hoạt ảnh sẽ bị giật — trong trường hợp này, hãy sử dụng CADisplayLink để nội suy thủ công các điểm.
// tạo đường dẫn có thể thay đổi
let mutablePath = CGMutablePath()
mutablePath.moveTo(to: CGPoint(x: 0, y: 0))
mutablePath.addLine(to: CGPoint(x: 100, y: 0))
mutablePath.addLine(to: CGPoint(x: 100, y: 100))
mutablePath.closeSubpath()
// chuyển đổi thành bất biến để lưu vào bộ nhớ đệm an toàn
let immutablePath: CGPath = mutablePath
CATransaction.perform {
shapeLayer.path = immutablePath
}
CGGradient là đối tượng xác định sự chuyển đổi mượt mà giữa hai hoặc nhiều màu dọc theo một đường thẳng (gradient tuyến tính) hoặc từ trung tâm ra ngoài (gradient xuyên tâm). CGGradient được tạo với không gian màu được chỉ định, một mảng CGColorRef và một mảng các vị trí dừng từ 0.0 đến 1.0. Sau khi tạo, gradient có thể được tái sử dụng nhiều lần trong các ngữ cảnh khác nhau.
CGShading là cơ chế mạnh mẽ hơn cho phép xác định hàm thay đổi màu dọc theo đường dẫn. Không giống CGGradient, hoạt động với một tập hợp màu cố định, CGShading sử dụng hàm callback (CGFunctionRef) tính toán màu tại mỗi điểm. Điều này cho phép tạo các gradient phức tạp với chuyển đổi phi tuyến tính và lược đồ màu tổng hợp.
Để vẽ gradient bên trong một hình dạng, cần có clip trên đường viền của hình dạng đó. Thứ tự: thêm đường dẫn vào ngữ cảnh, gọi CGContextClip, sau đó vẽ gradient. Nếu không có clip, gradient sẽ lấp đầy toàn bộ ngữ cảnh. Trên iOS, CGGradient được khuyến nghị là tùy chọn đơn giản và hiệu quả hơn — CGShading chỉ phù hợp cho các hàm màu tùy chỉnh.
func drawGradient(ctx: CGContext, rect: CGRect) {
let colors = [UIColor.red.cgColor, UIColor.blue.cgColor] as CFArray
guard let gradient = CGGradient(
colorsSpace: CGColorSpaceCreateDeviceRGB(),
colors: colors,
locations: [0.0, 1.0]
) else { return }
ctx.saveGState()
ctx.addEllipse(in: rect)
ctx.clip()
ctx.drawLinearGradient(
gradient,
start: CGPoint(x: rect.midX, y: rect.minY),
end: CGPoint(x: rect.midX, y: rect.maxY),
options: []
)
ctx.restoreGState()
}
CGImage là hình ảnh raster trong Core Graphics có thể được tải từ tệp, tạo theo chương trình hoặc lấy từ UIImage. CGImage chứa dữ liệu pixel, thông tin không gian màu, kích thước, độ sâu bit và bố cục dữ liệu. Không giống UIImage, CGImage không quản lý tỷ lệ Retina — trách nhiệm này thuộc về nhà phát triển thông qua tham số scale.
CGLayer là bộ đệm ngoại tuyến để raster hóa trước nội dung tĩnh. Nếu cùng một tập hợp lệnh vẽ được thực thi nhiều lần (ví dụ: mẫu nền), CGLayer sẽ raster hóa nó một lần và sau đó chỉ cần sao chép vào ngữ cảnh. Theo Apple, việc sử dụng CGLayer có thể tăng tốc vẽ lặp lại lên 2–5 lần trên CPU và lên đến 10 lần với tăng tốc phần cứng.
Để tải hình ảnh, hãy sử dụng CGImageSource — API mạnh mẽ để đọc siêu dữ liệu, hình thu nhỏ và từng khung hình từ GIF/APNG. CGImageSource cho phép tải dần dần và chỉ truy xuất các phần cần thiết. Khi làm việc với hình ảnh lớn (vượt quá kích thước màn hình), nên tạo CGImageSource với bộ nhớ đệm trên đĩa và sử dụng CGImageSourceCreateThumbnailAtIndex để hiển thị phiên bản thu nhỏ.
func createLayer(ctx: CGContext, size: CGSize) -> CGLayer? {
guard let layer = CGLayer(ctx, size: size, auxiliaryInfo: nil) else { return nil }
let layerCtx = layer.context !
// vẽ một lần
layerCtx.setFillColor(UIColor.lightGray.cgColor)
layerCtx.addEllipse(in: CGRect(origin: .zero, size: size))
layerCtx.fillPath()
return layer
}
// sử dụng trong draw()
for i in 0..<20 {
ctx.draw(layer, at: CGPoint(x: CGFloat(i) * 30, y: 0))
}
Hãy xây dựng một View tùy chỉnh để hiển thị hình mờ trên ảnh bằng Core Graphics. Hình mờ bao gồm văn bản bán trong suốt và logo vector được đặt chồng lên ảnh gốc. Mã này thể hiện việc làm việc với CGContext, CGImage, văn bản và độ trong suốt trong một ngữ cảnh duy nhất.
class WatermarkView: UIView {
private let watermarkText = "IT Sectr"
private let watermarkOpacity: CGFloat = 0.3
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
// vẽ ảnh nền
UIImage(named: "background")?.draw(in: rect)
// cấu hình độ trong suốt của hình mờ
ctx.saveGState()
ctx.translateBy(x: rect.midX, y: rect.midY)
ctx.rotate(by: -.pi / 6)
// văn bản bán trong suốt
let attributes: NSAttributedString.Attributes = [
.font: UIFont.boldSystemFont(ofSize: 48),
.foregroundColor: UIColor.white.withAlphaComponent(watermarkOpacity)
]
let textSize = watermarkText.size(withAttributes: attributes)
watermarkText.draw(
at: CGPoint(x: -textSize.width / 2, y: -textSize.height / 2),
withAttributes: attributes
)
// biểu tượng vector (hình tròn có chữ thập) bên dưới văn bản
ctx.setStrokeColor(UIColor.white.withAlphaComponent(watermarkOpacity).cgColor)
ctx.setLineWidth(3)
ctx.addEllipse(in: CGRect(x: -25, y: -75, width: 50, height: 50))
ctx.strokePath()
ctx.moveTo(x: -15, y: -50)
ctx.addLineTo(x: 15, y: -50)
ctx.moveTo(x: 0, y: -65)
ctx.addLineTo(x: 0, y: -35)
ctx.strokePath()
ctx.restoreGState()
}
}
Mã sử dụng các tính năng chính của Core Graphics: saveGState/restoreGState để cách ly hiệu ứng hình mờ khỏi nền, translateBy và rotate để định vị và xoay, văn bản bán trong suốt qua withAlphaComponent và biểu tượng vector qua addEllipse và addLineTo. Toàn bộ hình mờ được vẽ như một tổng thể duy nhất sau ảnh nền.
Khi tạo hình mờ cho ảnh trong sản xuất, điều quan trọng là phải xem xét hiệu suất. Nếu ảnh lớn hơn màn hình, hãy giảm kích thước bằng CGImageSourceCreateThumbnailAtIndex trước khi áp dụng hình mờ. Core Graphics xử lý tất cả các thao tác trên CPU — để xử lý hàng loạt hàng chục ảnh, hãy sử dụng hàng đợi nền và CGBitmapContext để tránh chặn UI.
Câu hỏi thường gặp
UIKit là framework UI cấp cao sử dụng Core Graphics bên trong để vẽ. Core Graphics là API C cấp thấp cho đồ họa 2D. UIKit thuận tiện hơn cho các phần tử tiêu chuẩn, trong khi Core Graphics kiểm soát hoàn toàn từng pixel.
Core Graphics phù hợp cho đồ họa 2D tĩnh, biểu đồ và phần tử UI tùy chỉnh. Metal dành cho đồ họa 3D, hoạt ảnh phức tạp và xử lý mảng pixel lớn với tăng tốc GPU. Đối với 95% tác vụ UI, Core Graphics là đủ.
Sử dụng CGImageSource để tải hình thu nhỏ qua createThumbnailAtIndex thay vì tải đầy đủ. Để hiển thị hình ảnh lớn, hãy tạo CGImage với tùy chọn giảm mẫu. Giải phóng CGImage qua CGImageRelease khi không còn cần thiết.
Có, Core Graphics bao gồm hỗ trợ PDF đầy đủ qua CGPDFDocument để đọc và CGPDFContext để tạo tài liệu PDF. Bạn có thể vẽ bất kỳ nội dung CGContext nào trực tiếp vào trang PDF trong khi vẫn giữ nguyên vector.
Core Graphics tự động sử dụng độ phân giải thiết bị khi vẽ trên màn hình. Đối với ngữ cảnh ngoại tuyến, hãy sử dụng UIGraphicsBeginImageContextWithOptions với scale = 0 (tỷ lệ hệ thống) hoặc chỉ định rõ ràng 2.0/3.0 cho Retina/Retina HD.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm