2013-12-10 20 views
11

Ich zeichne ein Kreisdiagramm, das einen CAShapeLayer für jede Scheibe des Kuchens mit. Selbst wenn der Endwinkel eines Kreissegment ist gleich den Anfangswinkel der benachbarten Scheibe, wird resultierende Anti-Aliasing in der darunterliegenden Hintergrundfarbe zwischen jeder pice Scheibe erscheinen, wenn die Grenze zwischen den Scheiben in einem Winkel ist.Angrenzend CAShapeLayer Anti-Aliasing-Ausgabe

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

Ich mag würde die kleine Lücke zwischen Scheiben zu beseitigen, während immer noch Anti-Aliasing mit so noch die resultierenden Kuchen Wagen glatt aussehen. Konzeptionell, so scheint es, wenn es eine Möglichkeit gäbe Anti-Aliasing auf die gesamte CALayer anzuwenden und es ist ein Kreissegment Subschichten, nachdem alle Tortenstück gezogen wurden, das würde den Trick tun ... Die Kreissegmente ineinander Anti-Aliasing werden würden, anstatt in die Hintergrund.

Ich habe mit so vielen CALayer Eigenschaften rumgespielt wie ich mir vorstellen kann und habe eine harte Zeit auf diese Informationen zu finden. Irgendwelche Ideen?

UPDATE: Siehe meine Antwort unten.

Antwort

5

UPDATE: Antwort Robs ist ziemlich gut, aber möglicherweise Ergebnisse in anderen Anti-Aliasing-Probleme. Ich beende die Lücken, indem ich 1pt breite radiale Linien entlang des Endwinkels jeder Tortenscheibe zeichne, wobei jede Linie die gleiche Farbe wie die angrenzende Scheibe hat. Diese Linien sind mit einem niedrigeren z-Index als die Kuchenscheiben gezeichnet, also sind sie darunter. Hier ist, wie sie aussehen, ohne dass die Tortenstücke auf gezeichnet:

The filler lines with no slices drawn.

Und hier ist das Endprodukt:

Final result with lines underneath and slices on top.

8

Du bist wahrscheinlich sein würde nicht in der Lage Ihre Tortenstück Kanten ohne Risse genau zu machen treffen. Die einfachste Lösung ist es nicht zu versuchen.

Statt machen Ihre Tortenstücke an den Rändern treffen, machen sie sich überlappen. Zeichnen Sie die erste Scheibe als Vollscheibe:

first slice

Dann wird die zweite Scheibe als eine vollständige Scheibe zeichnen, mit Ausnahme der richtigen Bereich der ersten Scheibe:

second slice

Dann ziehen die dritte Scheibe als Vollscheibe, mit Ausnahme des richtigen Bereich der ersten beiden Scheiben:

third slice

Und so weiter:

fourth slicefifth slice

mein Code hier:

#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 
+0

Vielen Dank für die Antwort, Rob. Ich habe diese Lösung an einem Punkt versucht und sah Antialiasing-Artefakte von den dunkleren, darunterliegenden Schichten, die in den Hintergrund antialiasiert wurden. Es erschien als ein subtiler dunkler Rand um das Tortendiagramm herum, der besonders am äußeren Rand der heller gefärbten Scheiben wahrnehmbar war. Die von mir beschriebene radiale Füllstofflösung scheint gut zu funktionieren. – Aaron

+0

@Aaron Wenn Sie eine Anti-Alias-Funktion verwenden, erhalten Sie einen Ring aus Farbe und Alpha-Pixel um eine effektvolle Alias-Form von Volltonfarbe. Wenn Sie dies für mehrere Formen mit demselben Umriss tun, sieht Ihr effektiv geglättetes Innengebiet gut aus, aber Ihre Anti-Alias-Zone wird Farbe (n) + Alpha überlagernde Farbe (n-1) + Alpha überlagern ... Farbe (0) + Alpha. Dies erklärt den Effekt, den Sie sehen. –