CGContextSetFill 带渐变

CGContextSetFill with gradient

我现在有一个可以画二维码的功能

+ (void)drawQRCode:(QRcode *)code context:(CGContextRef)ctx size:(CGFloat)size {}

目前,我可以使用以下方法设置包括色彩空间在内的颜色:

CGContextSetFillColorWithColor(ctx, [theColor colorUsingColorSpaceName:NSCalibratedWhiteColorSpace].CGColor);

我正在尝试实现创建渐变的功能我已将两个 NSColors 转换为 NSGradient - 似乎没有任何方法可以将渐变作为 NSColor 所以我想知道用渐变设置上下文填充的最佳方法是什么?

提前感谢您的任何建议!

CGContext 有 drawLinearGradient

https://developer.apple.com/documentation/coregraphics/cgcontext/1454782-drawlineargradient

drawRadialGradient

https://developer.apple.com/documentation/coregraphics/cgcontext/1455923-drawradialgradient

要使用它们来填充形状,请将形状的路径放入上下文中,然后在绘制渐变之前将形状用作剪切路径。

下面是演示该技术的视图中的 drawRect:

- (void) drawRect: (CGRect) rect {
    CGColorRef myColors[3] = {
        [[UIColor redColor] CGColor],
        [[UIColor yellowColor] CGColor],
        [[UIColor blueColor] CGColor] };

    CGFloat locations[3] = { 0.0, 0.25, 1.0 };

    CGRect circleRect = CGRectInset([self bounds], 20, 20);
    CGFloat circleRadius = circleRect.size.width / 2.0;

    CGContextRef cgContext = UIGraphicsGetCurrentContext();

    CGContextSaveGState(cgContext);
    CGContextSetFillColorWithColor(cgContext, [[UIColor blackColor] CGColor]);
    CGContextFillRect(cgContext, [self bounds]);
    CGContextRestoreGState(cgContext);

    CGContextSaveGState(cgContext);
    CGContextAddEllipseInRect(cgContext, circleRect);
    CGContextClip(cgContext);

    CGContextTranslateCTM(cgContext, CGRectGetMidX(circleRect), CGRectGetMidY(circleRect));
    CGContextRotateCTM(cgContext, M_PI / 3.0);


    CFArrayRef colors = CFArrayCreate(nil, (const void**) myColors, 3, &kCFTypeArrayCallBacks);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colors, locations);
    CFRelease(colors);
    CFRelease(colorSpace);

    CGContextDrawLinearGradient(cgContext, gradient, CGPointMake(-circleRadius, 0),
                                CGPointMake(circleRadius, 0), kCGGradientDrawsAfterEndLocation + kCGGradientDrawsBeforeStartLocation);
    CFRelease(gradient);
    CGContextRestoreGState(cgContext);
}

这是 Swift 中的等效游乐场。

import UIKit
import PlaygroundSupport

class CircleGradientView : UIView {
    override func draw(_ rect: CGRect) {

        let colors  = [
            UIColor.red.cgColor,
            UIColor.yellow.cgColor, // Yellow
            UIColor.blue.cgColor  // Blue
        ]

        let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)!


        let locations : [CGFloat] = [0.0, 0.25, 1.0]
        let gradient = CGGradient(colorsSpace: colorSpace,
                                  colors: colors as CFArray,
                                  locations: locations)

        if let context = UIGraphicsGetCurrentContext() {
            let circleRect = self.bounds.insetBy(dx: 20, dy: 20)
            let circleRadius = circleRect.width / 2.0

            context.saveGState()
            context.addEllipse(in: circleRect)
            context.clip()

            context.translateBy(x: circleRect.midX, y: circleRect.midY)
            context.rotate(by: .pi / 3.0)

            context.drawLinearGradient(gradient!,
                                       start: CGPoint(x: -circleRadius, y: 0),
                                       end: CGPoint(x: circleRadius, y: 0),
                                       options: [.drawsAfterEndLocation, .drawsBeforeStartLocation])
           context.restoreGState()
        }
    }
}

let myView = CircleGradientView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
PlaygroundSupport.PlaygroundPage.current.liveView = myView