CGGradient:什么是渐变、渐变类型及其创建

作者: IT Sectr 发布日期: 2026-07-21 阅读时间: 9 分钟

CGGradient — 是一个Core Graphics对象,表示两种或多种颜色之间的平滑过渡。与通过循环改变颜色来绘制渐变不同,CGGradient使用硬件加速计算,并支持两种类型:线性(axial)和径向(radial)。根据Apple Documentation(2026),CGGradient用于在iOS和macOS界面中创建逼真的填充、背景效果和模拟光源。

要点

  • CGGradient — 用于在点之间创建平滑颜色过渡的Core Graphics对象
  • 线性渐变(轴向)— 沿起点和终点之间的直线进行颜色过渡
  • 径向渐变(放射状)— 从中心点到外圆的颜色过渡
  • 渐变由CGColor颜色数组和相应位置(locations)数组(从0.0到1.0)创建
  • Core Graphics 执行渐变的渲染,包括Alpha合成和抗锯齿

什么是CGGradient?

CGGradient — 是Core Graphics中一个不可变对象,封装了一组颜色及其沿渐变过渡的混合规则。在内部,CGGradient存储一个CGColor数组、一个范围[0.0, 1.0]内的位置(locations)数组以及一个指向解释颜色的CGColorSpace的引用。每种颜色都与渐变标度上的一个位置相关联:位置0.0对应开始,1.0对应过渡结束。

通过CGGradientCreateWithColors函数创建CGGradient时,Core Graphics会预先计算颜色的中间值。渐变可以包含任意数量的颜色停止点(color stops),从而可以创建复杂的多色过渡。颜色数量必须至少为两个,并且每种颜色在locations数组中必须有一个对应的位置。

CGGradient的架构与Core Animation中的CAGradientLayer等更高级别的API不同,因为它直接在Core Graphics图形上下文中工作。这提供了对绘制过程的完全控制,以及将渐变与其他Quartz 2D操作(剪贴蒙版、阴影和变换)结合的能力。

线性渐变和径向渐变

Core Graphics支持两种类型的渐变:线性(轴向)和径向(放射状)。线性渐变由CGGradientCreateWithColors函数创建,并通过CGContextDrawLinearGradient绘制。径向渐变需要相同的CGGradient结构,但通过CGContextDrawRadialGradient绘制。

类型绘制函数参数应用
线性CGContextDrawLinearGradientstartPoint, endPoint, options背景、按钮、进度条
径向CGContextDrawRadialGradientstartCenter, startRadius, endCenter, endRadius, options发光、光源、阴影

线性渐变(轴向)

线性渐变将颜色过渡沿直线从起点startPoint延伸到终点endPoint。颜色在这两点之间进行插值,超出其边界的行为由扩展选项控制。线性渐变非常适合创建平滑的背景、模拟金属表面以及界面元素中的颜色过渡。

径向渐变(放射状)

径向渐变创建一个圆到另一个圆的颜色过渡。每个圆由中心(startCenter / endCenter)和半径(startRadius / endRadius)定义。颜色从内圆插值到外圆。特殊情况——当起始半径为0时:渐变从一个点扩散开来。径向渐变用于模拟光源、透镜、天体和聚光灯效果。

创建CGGradient:颜色和位置

CGGradient仅由一个基本函数——CGGradientCreateWithColors创建。该函数接受CGColorSpace、CGColor数组(CFArray)和CGFloat locations数组。如果locations为NULL,颜色将均匀分布在渐变标度上。如果指定了locations,其长度必须与颜色数量一致。

locations数组包含从0.0到1.0的值,定义了每种颜色的停止点。这些值必须单调递增。如果第一个值大于0.0,则从开始到此位置的颜色将根据位置0.0的颜色进行外推。对于小于1.0的最后一个值也是如此。此行为由绘制时的扩展选项控制。

选择渐变的颜色时,考虑色彩空间很重要。一个CGGradient中的所有颜色必须属于同一个CGColorSpace——Core Graphics在此空间中对分量进行插值。如果颜色在不同的空间中创建,则需要通过CGColorCreateCopyByMatchingToColorSpace将它们预先转换为同一空间。

在上下文中绘制渐变

Core Graphics提供两个绘制渐变的函数:CGContextDrawLinearGradient用于线性渐变,CGContextDrawRadialGradient用于径向渐变。这两个函数都接受图形上下文、CGGradient对象、扩展选项以及特定于类型的几何参数。绘制时会考虑当前的剪贴蒙版(clip)和上下文变换。

扩展选项(Gradient Options)

扩展选项控制渐变在0.0–1.0位置范围之外的行为。常量kCGGradientDrawsBeforeStartLocation用第一个停止点的颜色填充起始位置之前的区域。kCGGradientDrawsAfterEndLocation——用最后一个停止点的颜色填充。这些选项可以通过位掩码组合。对于径向渐变,这些选项应用于起始和结束半径之外的区域。

变换的影响

渐变被绘制在当前图形上下文的坐标系中,并考虑其变换(CTM——Current Transformation Matrix)。在调用绘制函数之前应用CGContextTranslateCTMCGContextScaleCTMCGContextRotateCTM会改变渐变的位置和比例。这允许将同一个CGGradient重复用于不同区域,而无需创建新对象。

选项:扩展、抗锯齿和遮罩

Core Graphics提供了几种额外的渐变管理机制:抗锯齿、通过剪贴蒙版(clipping mask)进行遮罩以及与透明度效果结合。抗锯齿在图形上下文中默认启用,并通过CGContextSetShouldAntialias进行控制。

剪贴蒙版允许将渐变的绘制区域限制为任意形状。在调用CGContextDrawLinearGradient之前,需要通过CGContextBeginPathCGContextAddPathCGContextClip定义轮廓。渐变将仅在此轮廓限定的区域内绘制。这广泛用于创建渐变图标、按钮和进度条。

渐变扩展(extend)——另一个重要参数。使用kCGGradientDrawsBeforeStartLocation时,Core Graphics将第一个停止点的颜色外推到直到startPoint的整个区域。如果没有此选项,渐变外部的区域将保持空白(透明)。两个选项的组合确保图形上下文的整个矩形都将被渐变填充,即使startPoint和endPoint位于其内部。

Swift代码示例

让我们看一下在iOS中使用CGGradient和Core Graphics创建和绘制渐变的实际示例

三色线性渐变

该示例创建一个具有三种颜色(蓝色、绿色、红色)的线性渐变,并在UIView的对角线上绘制它。locations数组不均匀地分布颜色:蓝色从0.0到0.3,绿色在0.6处,红色从0.6到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])
}

发光效果的径向渐变

该示例绘制了一个模拟发光的径向渐变。半径为零的起点定义了发光的中心,外圆定义了衰减边界。这种效果用于界面元素的照明或活动指示器。

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])
}

带剪贴蒙版的渐变

在此示例中,渐变通过剪贴轮廓被限制为圆形区域。在绘制渐变之前,定义了一条圆形路径,该路径成为当前上下文蒙版。渐变仅填充圆内的区域,从而产生渐变图标效果。

swift
func drawGradientInCircle(in ctx: CGContext,
                          rect: CGRect) {
    // 创建圆形剪贴路径
    let circlePath = CGMutablePath()
    circlePath.addEllipse(in: rect)
    ctx.addPath(circlePath)
    ctx.clip()

    // 在剪贴蒙版内绘制渐变
    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])
}

常见问题

CGGradient和CAGradientLayer有什么区别?

CGGradient — 是一个低级别的Core Graphics对象,用于在图形上下文中绘制。CAGradientLayer — 是一个高级别的Core Animation层,具有自动动画和硬件加速功能。CAGradientLayer对于UIKit来说更易于使用,但CGGradient提供了完全的控制和与任何CGContext的兼容性。

CGGradient中可以添加多少种颜色?

最少数量——2种颜色。上限仅受可用内存限制,因为Core Graphics会存储颜色数组和预先计算的插值表。实际上,一个渐变中超过10–15种颜色是不必要的——视觉过渡变得与平滑过渡无法区分。

如何制作带透明度的渐变?

在颜色数组中使用Alpha通道小于1.0的CGColor。例如,带透明度的颜色创建为UIColor(red: 0, green: 0, blue: 1, alpha: 0.5).cgColor。Core Graphics像颜色分量一样插值Alpha通道,从而创建平滑的透明度过渡。

CGGradient在macOS上能工作吗?

是的,CGGradient是Core Graphics的一部分,在两个平台上都可用:iOS和macOS。在macOS上,渐变通过重写drawRect在任何NSView中绘制。所有函数CGGradientCreateWithColors、CGContextDrawLinearGradient和CGContextDrawRadialGradient在两个平台上都是相同的。

如何旋转渐变?

要旋转渐变,请在绘制前对图形上下文应用变换CGContextRotateCTM(ctx, angle)。渐变的start和end点在变换后于上下文的局部坐标系中设置。或者,可以直接计算旋转后的坐标点,而不改变CTM。

总结

  • CGGradient — 用于颜色之间平滑过渡的不可变Core Graphics对象
  • 线性渐变通过CGContextDrawLinearGradient沿startPoint和endPoint之间的直线绘制
  • 径向渐变通过CGContextDrawRadialGradient从一个圆到另一个圆绘制
  • 渐变由CGColor数组和locations位置数组(0.0–1.0)创建
  • 扩展选项kCGGradientDrawsBeforeStartLocationkCGGradientDrawsAfterEndLocation控制范围外的填充
  • 剪贴蒙版(clip)将渐变的绘制区域限制为任意轮廓
  • 上下文变换(CTM)影响渐变的位置、比例和旋转

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读