UIBezierPath с цветовым градиентом

У меня вопрос о UIBezierPath.

Например, у меня есть этот путь:

Теперь я хочу иметь цветовой градиент от белого до красного. Слева направо.

Вот мой код:

UIBezierPath *bezierPath;
bezierPath = [UIBezierPath bezierPathWithArcCenter:_center radius:_radius startAngle:((4 * angle)) endAngle:(((20) * angle)) clockwise:YES];
[bezierPath addLineToPoint:_center];
[bezierPath closePath];
UIColor *color = [UIColor colorWithHue:0/sectors saturation:1. brightness:1. alpha:1];
[color setFill];
[color setStroke];
[bezierPath fill];
[bezierPath stroke];

Кто-нибудь может мне помочь?

Изменить 1:

У меня есть это цветовое колесо:

введите описание изображения здесь

    UIBezierPath *bezierPath;

for ( int i = 0; i < 360; i++) {
    bezierPath = [UIBezierPath bezierPathWithArcCenter:_center radius:_radius startAngle:((i * angle)) endAngle:(((i + 1) * angle)) clockwise:YES];

    [bezierPath addLineToPoint:_center];
    [bezierPath closePath];
    UIColor *color = [UIColor colorWithHue:i/sectors saturation:1. brightness:1. alpha:1];
    [color setFill];
    [color setStroke];
    [bezierPath fill];
    [bezierPath stroke];
}

но я хочу: (с белым градиентом)

введите описание изображения здесь

Ответ 1

вы можете попробовать:)

- (void)drawRect:(CGRect)rect
{
    CGFloat arcStep = (M_PI *2) / 360; // M_PI*2 is equivalent of full cirle
    BOOL clocklwise = NO;
    CGFloat x = CGRectGetWidth(rect) / 2; // circle center
    CGFloat y = CGRectGetHeight(rect) / 2; // circle center
    CGFloat radius = MIN(x, y) / 2;
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // draw colorful circle
    CGContextSetLineWidth(ctx, radius*2);
    for (CGFloat i = 0; i < 360; i+=1)
    {
        UIColor* c = [UIColor colorWithHue:i/360 saturation:1. brightness:1. alpha:1];

        CGContextSetStrokeColorWithColor(ctx, c.CGColor);

        CGFloat startAngle = i * arcStep;
        CGFloat endAngle = startAngle + arcStep + 0.02;

        CGContextAddArc(ctx, x, y, radius, startAngle, endAngle, clocklwise);
        CGContextStrokePath(ctx);
    }
    // drawing circles then, you might want few of them - smaller radius and less alpha with each step
    UIColor* c = [[UIColor whiteColor] colorWithAlphaComponent: 0.03];
    for (CGFloat fillRadius = radius/2; fillRadius > 0; fillRadius -= 1.f)
    {
        CGContextSetLineWidth(ctx, fillRadius*2);
        CGContextSetStrokeColorWithColor(ctx, c.CGColor);
        CGContextAddArc(ctx, x, y, fillRadius, 0, M_PI * 2, clocklwise);
        CGContextStrokePath(ctx);
    }
}

Ответ 2

Используйте CAGradientLayer и замаскируйте его с помощью CAShapeLayer Что-то вроде этого

- (void)addCircle{
CAShapeLayer *shapeLayer = [CAShapeLayer new];
shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(CGRectMake(10, 10, 100, 100), 4, 4)].CGPath;
shapeLayer.strokeColor = [UIColor redColor].CGColor;
shapeLayer.contentsScale = [UIScreen mainScreen].scale;
shapeLayer.shouldRasterize = NO;


CAGradientLayer *_gradientLayer = [CAGradientLayer layer];
_gradientLayer.frame =self.view.bounds;
_gradientLayer.startPoint = CGPointMake(0.0, 1);
_gradientLayer.endPoint = CGPointMake(1, 0);
_gradientLayer.colors = @[(id)[UIColor blueColor].CGColor,(id)[UIColor redColor].CGColor];

//Add gradient layer to view
[self.view.layer addSublayer:_gradientLayer];
_gradientLayer.mask = shapeLayer;
}

Вышеуказанный метод добавит треугольник, возможно, вам нужно изменить начальную и конечную точки. Также вы можете изменить значения градиента на все, что вам нужно.

Apple Docs

Учебное пособие по CAGradientLayer

Обновить. После обновления его более ясно, что его не треугольник вы хотите, но то, что вам нужно, возможно с CAGradientLayer и CAShapeLayer, вам нужно следовать тому же подходу, где вы можете добавить градиент с разные цвета и местоположения (остановки) (если вы добавляете места, то убедитесь, что местоположения и цвета равны), а затем замаскируйте его с помощью CAShapeLayer, который был окружен.

Ответ 3

Вы можете попробовать следующее:

    //// General Declarations
CGContextRef context = UIGraphicsGetCurrentContext();


//// Shadow Declarations
NSShadow* shadow = [[NSShadow alloc] init];
[shadow setShadowColor: UIColor.whiteColor];
[shadow setShadowOffset: CGSizeMake(2.1, -4.1)];
[shadow setShadowBlurRadius: 5];

//// Bezier Drawing
UIBezierPath* bezierPath = UIBezierPath.bezierPath;
[UIColor.blackColor setStroke];
bezierPath.lineWidth = 1;
[bezierPath stroke];


//// Bezier 2 Drawing
UIBezierPath* bezier2Path = UIBezierPath.bezierPath;
[bezier2Path moveToPoint: CGPointMake(170.5, 59.5)];
[bezier2Path addCurveToPoint: CGPointMake(170.5, 71.5) controlPoint1: CGPointMake(173.5, 65.5) controlPoint2: CGPointMake(170.5, 71.5)];
[bezier2Path addLineToPoint: CGPointMake(155.5, 57.5)];
[bezier2Path addLineToPoint: CGPointMake(170.5, 59.5)];
[UIColor.redColor setFill];
[bezier2Path fill];

////// Bezier 2 Inner Shadow
CGContextSaveGState(context);
UIRectClip(bezier2Path.bounds);
CGContextSetShadowWithColor(context, CGSizeZero, 0, NULL);

CGContextSetAlpha(context, CGColorGetAlpha([shadow.shadowColor CGColor]));
CGContextBeginTransparencyLayer(context, NULL);
{
    UIColor* opaqueShadow = [shadow.shadowColor colorWithAlphaComponent: 1];
    CGContextSetShadowWithColor(context, shadow.shadowOffset, shadow.shadowBlurRadius, [opaqueShadow CGColor]);
    CGContextSetBlendMode(context, kCGBlendModeSourceOut);
    CGContextBeginTransparencyLayer(context, NULL);

    [opaqueShadow setFill];
    [bezier2Path fill];

    CGContextEndTransparencyLayer(context);
}
CGContextEndTransparencyLayer(context);
CGContextRestoreGState(context);

и результат будет: введите описание изображения здесь

Ответ 4

Вы заархивируете его, используя QuartsCore. Если вы хотите получить изображение с рисунком, вы можете вызвать UIGraphicsBeginImageContext(), если вы хотите нарисовать его на UIView, вы должны перегрузить метод - (void) drawRect: (CGRect) rect UIView. Вы можете добавить путь к контексту и использовать его для обрезать контекст (не забудьте сохранить состояние контекста раньше). После того, как вы можете нарисовать gradient. Градиент будет обрезаться по пути.

Вы получите что-то вроде этого:

CGPathRef path = [bezierPath CGPath];
CGContextSaveGState(context);

CGContextAddPath(context, path);
CGContextClip(context);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSArray *colors = [NSArray arrayWithObjects:(id)[UIColor redColor].CGColor, (id)[UIColor blueColor].CGColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors( colorSpace, (CFArrayRef)colors, NULL);
CGColorSpaceRelease(colorSpace);
colorSpace = NULL;

CGContextDrawLinearGradient(context, gradient, CGPointMake(0.0, 0.0), CGPointMake(100.0, 100.0), kNilOptions);

CGContextRestoreGState(context);

Ответ 5

Еще один ответ на вопрос Олега относительно насыщения (белый градиент), который я нахожу более приятным, и в Свифт (3).

Вы можете добавить шаги к градиенту, если вам нужен больший белый круг (с 2-го белого шага в 0.2)

import UIKit

class HSView: UIView {
    override func draw(_ rect: CGRect) {
        let arcStep = 2 * CGFloat.pi / 360
        let isClockwise = false
        let x = rect.width / 2
        let y = rect.height / 2
        let radius = min(x, y) / 2
        let ctx = UIGraphicsGetCurrentContext()
        ctx?.setLineWidth(2 * radius)

        for i in 0..<360 {
            let color = UIColor(hue: CGFloat(i)/360, saturation: 1, brightness: 1, alpha: 1)
            let startAngle = CGFloat(i) * arcStep
            let endAngle = startAngle + arcStep + 0.02

            ctx?.setStrokeColor(color.cgColor)
            ctx?.addArc(center: CGPoint(x: x, y: y), radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: isClockwise)
            ctx?.strokePath()
        }

        let gradient = CGGradient(colorsSpace: UIColor.white.cgColor.colorSpace,
                                  colors: [
                                    UIColor.white.cgColor,
                                    UIColor.white.withAlphaComponent(0).cgColor,
                                    ] as CFArray,
                                  locations: [
                                    0,
                                    1,
            ]
        )
        ctx?.drawRadialGradient(gradient!, startCenter: CGPoint(x: x, y: y), startRadius: 0, endCenter: CGPoint(x: x, y: y), endRadius: 2 * radius, options: .drawsAfterEndLocation)
    }
}

Результат