CGGradient: khái niệm, các loại gradient và cách tạo

Tác giả: IT Sectr Đã đăng: 2026-07-21 Thời gian đọc: 9 phút

CGGradient là một đối tượng Core Graphics đại diện cho sự chuyển đổi mượt mà giữa hai hoặc nhiều màu sắc. Không giống như vẽ gradient qua vòng lặp với thay đổi màu, CGGradient sử dụng tính toán tăng tốc bằng phần cứng và hỗ trợ hai loại: tuyến tính (axial) và xuyên tâm. Theo Tài liệu Apple (2026), CGGradient được sử dụng để tạo các lớp phủ thực tế, hiệu ứng nền và mô phỏng nguồn sáng trong giao diện iOS và macOS.

Các điểm chính

  • CGGradient là một đối tượng Core Graphics để tạo chuyển đổi màu sắc mượt mà giữa các điểm
  • Gradient tuyến tính (axial) — chuyển đổi màu dọc theo đường thẳng giữa điểm bắt đầu và điểm kết thúc
  • Gradient xuyên tâm — chuyển đổi màu từ điểm trung tâm ra vòng tròn bên ngoài
  • Gradient được tạo từ mảng màu CGColor và mảng vị trí (locations) tương ứng từ 0.0 đến 1.0
  • Core Graphics kết xuất gradient với tổng hợp alpha và khử răng cưa (antialiasing)

CGGradient là gì?

CGGradient là một đối tượng bất biến trong Core Graphics, đóng gói một tập hợp các màu sắc và quy tắc pha trộn chúng dọc theo một chuyển đổi gradient. Bên trong, CGGradient lưu trữ một mảng CGColor, một mảng vị trí (locations) trong phạm vi [0.0, 1.0] và một tham chiếu đến CGColorSpace mà trong đó các màu được diễn giải. Mỗi màu được liên kết với một vị trí trên thang gradient: vị trí 0.0 tương ứng với điểm bắt đầu, 1.0 với điểm kết thúc của chuyển đổi.

Khi tạo CGGradient thông qua hàm CGGradientCreateWithColors, Core Graphics tính toán trước các giá trị màu trung gian. Một gradient có thể chứa số lượng điểm dừng màu (color stops) tùy ý, cho phép các chuyển đổi nhiều màu phức tạp. Số lượng màu phải ít nhất là hai và mỗi màu phải tương ứng với một vị trí trong mảng locations.

Kiến trúc của CGGradient khác với các API cấp cao hơn như CAGradientLayer từ Core Animation ở chỗ nó hoạt động trực tiếp trong ngữ cảnh Core Graphics. Điều này cung cấp toàn quyền kiểm soát quá trình vẽ và khả năng kết hợp gradient với các thao tác Quartz 2D khác — mặt nạ cắt, bóng đổ và biến đổi.

Gradient tuyến tính và xuyên tâm

Core Graphics hỗ trợ hai loại gradient: tuyến tính (axial) và xuyên tâm. Gradient tuyến tính được tạo bằng hàm CGGradientCreateWithColors và được vẽ bằng CGContextDrawLinearGradient. Gradient xuyên tâm yêu cầu cùng cấu trúc CGGradient nhưng được vẽ bằng CGContextDrawRadialGradient.

LoạiHàm vẽTham sốSử dụng
Tuyến tínhCGContextDrawLinearGradientstartPoint, endPoint, optionsNền, nút, thanh tiến trình
Xuyên tâmCGContextDrawRadialGradientstartCenter, startRadius, endCenter, endRadius, optionsĐiểm sáng, nguồn sáng, bóng đổ

Gradient tuyến tính (Axial)

Gradient tuyến tính kéo dài chuyển đổi màu dọc theo một đường thẳng từ điểm bắt đầu startPoint đến điểm kết thúc endPoint. Màu sắc được nội suy giữa hai điểm này và hành vi bên ngoài chúng được kiểm soát bởi các tùy chọn mở rộng. Gradient tuyến tính lý tưởng để tạo nền mượt, mô phỏng bề mặt kim loại và chuyển đổi màu trong các thành phần giao diện.

Gradient xuyên tâm

Gradient xuyên tâm tạo chuyển đổi màu từ một vòng tròn sang vòng tròn khác. Mỗi vòng tròn được xác định bởi tâm (startCenter / endCenter) và bán kính (startRadius / endRadius). Màu được nội suy từ vòng tròn bên trong ra vòng tròn bên ngoài. Một trường hợp đặc biệt là khi bán kính bắt đầu bằng 0: gradient tỏa ra từ một điểm duy nhất. Gradient xuyên tâm được sử dụng để mô phỏng nguồn sáng, thấu kính, thiên thể và hiệu ứng đèn chiếu.

Tạo CGGradient: màu sắc và vị trí

CGGradient được tạo chỉ với một hàm cơ bản — CGGradientCreateWithColors. Hàm này nhận CGColorSpace, một mảng CGColor (CFArray) và một mảng CGFloat locations. Nếu locations là NULL, các màu được phân bố đều dọc theo thang gradient. Nếu locations được chỉ định, số lượng của chúng phải khớp với số lượng màu.

Mảng locations chứa các giá trị từ 0.0 đến 1.0 xác định các điểm dừng cho mỗi màu. Các giá trị phải tăng đơn điệu. Nếu giá trị đầu tiên lớn hơn 0.0, màu từ đầu đến vị trí này được ngoại suy từ màu tại vị trí 0.0. Tương tự cho giá trị cuối cùng nhỏ hơn 1.0. Hành vi này được kiểm soát bởi các tùy chọn mở rộng khi vẽ.

Khi chọn màu sắc cho gradient, điều quan trọng là phải xem xét không gian màu. Tất cả các màu trong một CGGradient phải thuộc cùng một CGColorSpace — Core Graphics nội suy các thành phần trong không gian đó. Nếu các màu được tạo trong các không gian khác nhau, chúng phải được chuyển đổi sang không gian chung trước qua CGColorCreateCopyByMatchingToColorSpace.

Vẽ gradient trong ngữ cảnh

Core Graphics cung cấp hai hàm để vẽ gradient: CGContextDrawLinearGradient cho tuyến tính và CGContextDrawRadialGradient cho xuyên tâm. Cả hai hàm đều chấp nhận một ngữ cảnh đồ họa, một đối tượng CGGradient, các tùy chọn mở rộng và các tham số hình học cụ thể theo loại. Việc vẽ được thực hiện có tính đến mặt nạ cắt hiện tại và biến đổi ngữ cảnh.

Tùy chọn mở rộng (Gradient Options)

Tùy chọn mở rộng kiểm soát hành vi của gradient ngoài phạm vi vị trí 0.0–1.0. Hằng số kCGGradientDrawsBeforeStartLocation lấp đầy khu vực trước vị trí bắt đầu bằng màu của điểm dừng đầu tiên. kCGGradientDrawsAfterEndLocation lấp đầy bằng màu của điểm dừng cuối cùng. Các tùy chọn này có thể được kết hợp thông qua mặt nạ bit. Đối với gradient xuyên tâm, các tùy chọn áp dụng cho khu vực ngoài bán kính bắt đầu và kết thúc.

Ảnh hưởng của biến đổi

Gradient được vẽ trong hệ tọa độ của ngữ cảnh đồ họa hiện tại, có tính đến biến đổi của nó (CTM — Ma trận biến đổi hiện tại). Áp dụng CGContextTranslateCTM, CGContextScaleCTM hoặc CGContextRotateCTM trước khi gọi hàm vẽ sẽ thay đổi vị trí và tỷ lệ của gradient. Điều này cho phép tái sử dụng một CGGradient duy nhất cho các khu vực khác nhau mà không cần tạo đối tượng mới.

Tùy chọn: mở rộng, làm mịn và mặt nạ

Core Graphics cung cấp một số cơ chế bổ sung để kiểm soát gradient: khử răng cưa (antialiasing), tạo mặt nạ qua mặt nạ cắt (clipping mask) và kết hợp với hiệu ứng trong suốt. Khử răng cưa được bật theo mặc định trong ngữ cảnh đồ họa và được kiểm soát qua CGContextSetShouldAntialias.

Mặt nạ cắt cho phép giới hạn khu vực vẽ gradient thành một hình dạng tùy ý. Trước khi gọi CGContextDrawLinearGradient, cần xác định một đường dẫn qua CGContextBeginPath, CGContextAddPathCGContextClip. Gradient chỉ được vẽ trong khu vực giới hạn bởi đường dẫn này. Điều này được sử dụng rộng rãi để tạo biểu tượng gradient, nút và thanh tiến trình.

Mở rộng gradient là một tham số quan trọng khác. Khi sử dụng kCGGradientDrawsBeforeStartLocation, Core Graphics ngoại suy màu của điểm dừng đầu tiên trên toàn bộ khu vực trước startPoint. Nếu không có tùy chọn này, khu vực bên ngoài gradient vẫn không được lấp đầy (trong suốt). Kết hợp cả hai tùy chọn đảm bảo toàn bộ hình chữ nhật của ngữ cảnh đồ họa được lấp đầy bằng gradient, ngay cả khi startPoint và endPoint nằm bên trong nó.

Ví dụ mã Swift

Hãy xem các ví dụ thực tế về tạo và vẽ gradient trong iOS sử dụng CGGradient và Core Graphics.

Gradient tuyến tính với ba màu

Ví dụ này tạo một gradient tuyến tính với ba màu (xanh lam, xanh lục, đỏ) và vẽ nó theo đường chéo của UIView. Mảng locations phân bố các màu không đều: xanh lam từ 0.0 đến 0.3, xanh lục tại 0.6, đỏ từ 0.6 đến 1.0.

swift
func drawLinearGradient(in ctx: CGContext,
                          rect: CGRect) {
    let colors = [
        UIColor.blue.cgColor,
        UIColor.green.cgColor,
        UIColor.red.cgColor
    ] as CFArray

    let locations: [CGFloat] = [0.0, 0.6, 1.0]
    let space = CGColorSpaceCreateDeviceRGB()

    guard let gradient = CGGradientCreateWithColors(
        space, colors, locations
    ) else { return }

    let start = CGPoint(x: 0, y: 0)
    let end = CGPoint(x: rect.width,
                         y: rect.height)

    ctx.drawLinearGradient(gradient,
        start: start, end: end,
        options: [.drawsBeforeStartLocation,
                  .drawsAfterEndLocation])
}

Gradient xuyên tâm với hiệu ứng phát sáng

Ví dụ này vẽ một gradient xuyên tâm mô phỏng hiệu ứng phát sáng. Điểm bắt đầu với bán kính bằng không xác định tâm phát sáng và vòng tròn bên ngoài xác định ranh giới mờ dần. Hiệu ứng này được sử dụng để làm nổi bật các thành phần giao diện hoặc chỉ báo hoạt động.

swift
func drawRadialGlow(in ctx: CGContext,
                     center: CGPoint) {
    let colors = [
        UIColor.white.cgColor,
        UIColor.orange.cgColor,
        UIColor.clear.cgColor
    ] as CFArray
    let locations: [CGFloat] = [0.0, 0.4, 1.0]

    let gradient = CGGradientCreateWithColors(
        CGColorSpaceCreateDeviceRGB(), colors, locations)

    ctx.drawRadialGradient(gradient,
        startCenter: center, startRadius: 0,
        endCenter: center, endRadius: 100,
        options: [.drawsBeforeStartLocation,
                  .drawsAfterEndLocation])
}

Gradient với mặt nạ cắt

Trong ví dụ này, gradient được giới hạn trong một khu vực hình tròn thông qua đường dẫn cắt. Trước khi vẽ gradient, một đường dẫn hình tròn được xác định, trở thành mặt nạ ngữ cảnh hiện tại. Gradient chỉ lấp đầy khu vực bên trong vòng tròn, tạo hiệu ứng biểu tượng gradient.

swift
func drawGradientInCircle(in ctx: CGContext,
                          rect: CGRect) {
    // Creating circular clip path
    let circlePath = CGMutablePath()
    circlePath.addEllipse(in: rect)
    ctx.addPath(circlePath)
    ctx.clip()

    // Drawing gradient inside clip mask
    let colors = [UIColor.magenta.cgColor,
                    UIColor.cyan.cgColor]
    let gradient = CGGradientCreateWithColors(
        CGColorSpaceCreateDeviceRGB(),
        colors as CFArray, nil)

    ctx.drawLinearGradient(gradient,
        start: CGPoint(x: 0, y: 0),
        end: CGPoint(x: rect.width,
                     y: rect.height),
        options: [.drawsBeforeStartLocation])
}

Các câu hỏi thường gặp

Sự khác biệt giữa CGGradient và CAGradientLayer là gì?

CGGradient là một đối tượng Core Graphics cấp thấp để vẽ trong ngữ cảnh đồ họa. CAGradientLayer là một lớp Core Animation cấp cao với hoạt ảnh tự động và tăng tốc phần cứng. CAGradientLayer dễ sử dụng hơn với UIKit, nhưng CGGradient cung cấp toàn quyền kiểm soát và tương thích với mọi CGContext.

Có thể thêm bao nhiêu màu vào CGGradient?

Tối thiểu là 2 màu. Giới hạn trên chỉ bị ràng buộc bởi bộ nhớ khả dụng, vì Core Graphics lưu trữ một mảng màu và bảng nội suy được tính toán trước. Trong thực tế, hơn 10–15 màu trong một gradient là không cần thiết — sự chuyển đổi thị giác trở nên không thể phân biệt được với một gradient mượt.

Làm thế nào để tạo gradient với độ trong suốt?

Sử dụng CGColor có kênh alpha nhỏ hơn 1.0 trong mảng màu. Ví dụ, một màu có độ trong suốt được tạo như UIColor(red: 0, green: 0, blue: 1, alpha: 0.5).cgColor. Core Graphics nội suy kênh alpha giống như các thành phần màu, tạo ra sự chuyển đổi độ trong suốt mượt mà.

CGGradient có hoạt động trên macOS không?

, CGGradient là một phần của Core Graphics, có sẵn trên cả hai nền tảng: iOS và macOS. Trên macOS, gradient được vẽ trong bất kỳ NSView nào thông qua việc ghi đè drawRect. Tất cả các hàm CGGradientCreateWithColors, CGContextDrawLinearGradient và CGContextDrawRadialGradient đều giống hệt nhau trên cả hai nền tảng.

Làm thế nào để xoay gradient?

Để xoay gradient, áp dụng biến đổi cho ngữ cảnh đồ họa trước khi vẽ: CGContextRotateCTM(ctx, angle). Các điểm bắt đầu và kết thúc của gradient được chỉ định trong hệ tọa độ cục bộ của ngữ cảnh sau khi biến đổi. Ngoài ra, bạn có thể tính toán trực tiếp tọa độ xoay của các điểm mà không cần thay đổi CTM.

Tổng kết

  • CGGradient là một đối tượng Core Graphics bất biến cho các chuyển đổi màu mượt mà
  • Gradient tuyến tính được vẽ dọc theo đường thẳng giữa startPoint và endPoint qua CGContextDrawLinearGradient
  • Gradient xuyên tâm được vẽ từ vòng tròn này sang vòng tròn khác qua CGContextDrawRadialGradient
  • Gradient được tạo từ mảng CGColor và mảng vị trí (0.0–1.0)
  • Tùy chọn mở rộng kCGGradientDrawsBeforeStartLocationkCGGradientDrawsAfterEndLocation kiểm soát việc lấp đầy bên ngoài phạm vi
  • Mặt nạ cắt giới hạn khu vực vẽ gradient thành một đường dẫn tùy ý
  • Biến đổi ngữ cảnh (CTM) ảnh hưởng đến vị trí, tỷ lệ và góc xoay của gradient

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.

Thảo luận dự án

Đọc thêm