Как нарисовать дугу с изогнутым краем в iOS?


В одном из моих приложений я пытаюсь нарисовать дугу градиента с закругленными краями. Как на следующем рисунке.

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

Это то, что я сделал до сих пор, используя следующий код.

-(void)startArc
  {
   UIBezierPath *roundedArc = [self arcWithRoundedCornerAt:centerPoint startAngle:DEGREES_TO_RADIANS(-90) endAngle:DEGREES_TO_RADIANS(90) innerRadius:width-20 outerRadius:width cornerRadius:0];

        CAShapeLayer *mask = [CAShapeLayer new];
        [mask setPath:roundedArc.CGPath];
        [mask setFrame:_outerView.bounds];
        [mask setShouldRasterize:YES];
        [mask setRasterizationScale:[UIScreen mainScreen].scale];

    CAGradientLayer *gradient = [CAGradientLayer new];
        [gradient setFrame:_outerView.bounds];
    //    [gradient setColors:[NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.86 green:0.91 blue:0.96 alpha:1.0f] CGColor],(id)[[UIColor colorWithRed:0.98 green:0.99 blue:0.99 alpha:1.0f] CGColor], nil]];
        [gradient setColors:[NSArray arrayWithObjects:(id)[UIColor colorWithRed:0.19 green:0.64 blue:0.89 alpha:1.0].CGColor,(id)[UIColor colorWithRed:0.14 green:0.76 blue:0.56 alpha:1.0f].CGColor, nil]];

        [gradient setMask:mask];
        [_outerView.layer addSublayer:gradient];

}
- (UIBezierPath *)arcWithRoundedCornerAt:(CGPoint)center
                              startAngle:(CGFloat)startAngle
                                endAngle:(CGFloat)endAngle
                             innerRadius:(CGFloat)innerRadius
                             outerRadius:(CGFloat)outerRadius
                            cornerRadius:(CGFloat)cornerRadius
{
    CGFloat innerTheta = asin(cornerRadius / 2.0 / (innerRadius + cornerRadius)) * 2.0;
    CGFloat outerTheta = asin(cornerRadius / 2.0 / (outerRadius - cornerRadius)) * 2.0;

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path addArcWithCenter:center
                    radius:innerRadius + cornerRadius
                startAngle:endAngle - innerTheta
                  endAngle:startAngle + innerTheta
                 clockwise:false];

    [path addArcWithCenter:center
                    radius:outerRadius - cornerRadius
                startAngle:startAngle + outerTheta
                  endAngle:endAngle - outerTheta
                 clockwise:true];

    [path closePath];

    return path;
}

С помощью вышеуказанного кода я добился следующего

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

Может ли кто-нибудь дать мне знать о том, как достичь этих закругленных краев ? Тот, который я реализовал, имеет острые края.

1 3

1 ответ:

Вероятно, самый простой подход:

  1. Создайте один путь дуги (вдоль середины целевой дуги) в виде пути
  2. Установите ширину линии (20 в вашем случае) и заглушку линии (закругленные заглушки)
  3. преобразование пути в гладкий путь (CGContextReplacePathWithStrokedPath)
  4. Продолжайте с вашим существующим кодом для градиента

Поглаживание преобразует ваш 90-градусный дуговой путь, который бесконечно узок, в контур линии, которая является 20 пикселей в ширину и имеет закругленные концы линий.

Код может приблизительно выглядеть так:

- (UIBezierPath *)arcWithRoundedCornerAt:(CGPoint)center
                              startAngle:(CGFloat)startAngle
                                endAngle:(CGFloat)endAngle
                             innerRadius:(CGFloat)innerRadius
                             outerRadius:(CGFloat)outerRadius
                            cornerRadius:(CGFloat)cornerRadius
                                 context:(CGContext)context
{

    CGFloat radius = (innerRadius + outerRadius) / 2.0;

    CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, true);

    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextSetLineWidth(context, outerRadius - innerRadius);

    CGContextReplacePathWithStrokedPath(context)

    return [UIBezierPath bezierPathWithCGPath: CGContextCopyPath(context)];
}