Подтвердить что ты не робот

Проблема со сглаживанием CAShapeLayer

Я рисую круговую диаграмму, используя CAShapeLayer для каждого фрагмента пирога. Даже когда конечный угол одного кусочка пирога равен начальному углу смежного среза, сглаживание приводит к тому, что основной цвет фона появляется между каждым куском среза, если граница между срезами находится под углом.

http://i.stack.imgur.com/Qdu8d.png

Я бы хотел устранить небольшой разрыв между срезами, все еще используя сглаживание, поэтому получающаяся в результате круговая тележка все еще выглядит гладкой. Понятно, что если бы существовал способ применить сглаживание ко всему CALayer, и это подслои кусочка кусочка после того, как были вырезаны кусочки пирога, это сделало бы трюк... Кусочки пирога были бы сглажены друг с другом, а не в фон.

Я играл с таким количеством свойств CALayer, о котором я могу думать, и мне сложно найти дополнительную информацию об этом. Любые идеи?

ОБНОВЛЕНИЕ: См. мой ответ ниже.

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ: Ответ Rob довольно хорош, но, возможно, приводит к другим проблемам сглаживания. Я закончил "заполнять" промежутки, рисуя широкие радиальные линии шириной 1pt вдоль угла конца каждого куска пирога, причем каждая линия имеет тот же цвет, что и смежный срез. Эти линии рисуются с меньшим индексом z, чем кусочки пирога, поэтому они находятся под ним. Здесь они выглядят без кусочков пирога, нарисованных сверху:

The filler lines with no slices drawn.

И вот конечный продукт:

Final result with lines underneath and slices on top.

Ответ 2

Вероятно, вы не сможете заставить края кусочков пирога встретиться ровно без трещин. Самое простое решение - не попробовать.

Вместо того, чтобы ваши кусочки пирога встречались по краям, сделайте их перекрытыми. Нарисуйте первый фрагмент как полный диск:

first slice

Затем нарисуйте второй срез как полный диск, за исключением правильной области первого фрагмента:

second slice

Затем нарисуйте третий срез как полный диск, за исключением правильной области первых двух срезов:

third slice

И так далее:

fourth slicefifth slice

Здесь мой код:

#import "PieView.h"

@implementation PieView {
    NSMutableArray *slices;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    [self layoutSliceLayers];
}

- (void)layoutSliceLayers {
    if (slices == nil) {
        [self createSlices];
    }
    [slices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [self layoutSliceLayer:obj index:idx];
    }];
}

static const int kSliceCount = 5;

- (void)createSlices {
    slices = [NSMutableArray arrayWithCapacity:kSliceCount];
    for (int i = 0; i < kSliceCount; ++i) {
        [slices addObject:[self newSliceLayerForIndex:i]];
    }
}

- (CAShapeLayer *)newSliceLayerForIndex:(int)i {
    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.fillColor = [UIColor colorWithWhite:(CGFloat)i / kSliceCount alpha:1].CGColor;
    [self.layer addSublayer:layer];
    return layer;
}

- (void)layoutSliceLayer:(CAShapeLayer *)layer index:(int)index {
    layer.position = [self center];
    layer.path = [self pathForSliceIndex:index].CGPath;
}

- (CGPoint)center {
    CGRect bounds = self.bounds;
    return CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
}

- (UIBezierPath *)pathForSliceIndex:(int)i {
    CGFloat radius = [self radius];
    CGFloat fudgeRadians = 5 / radius;
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointZero
        radius:radius startAngle:2 * M_PI * i / kSliceCount
        endAngle:2 * M_PI clockwise:YES];
    [path addLineToPoint:CGPointZero];
    [path closePath];
    return path;
}

- (CGFloat)radius {
    CGSize size = self.bounds.size;
    return 0.9 * MIN(size.width, size.height) / 2;
}

@end