Apple二维图像绘制框架Core Graphics
Apple二维图像绘制框架Core Graphics

Apple二维图像绘制框架Core Graphics

Core Graphics 是苹果提供的一种二维图形绘制框架,用于在 iOS、macOS、tvOS 和 watchOS 上高效地绘制矢量图形、图像和路径。它是底层的绘图工具,使用 C 语言接口,功能强大,主要用于开发者需要更高精度和控制权的绘图场景。

在 SwiftUI 中,尽管大部分图形绘制任务可以通过 PathCanvas 完成,但 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/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注