2013-12-10 40 views
11

Tôi đang vẽ một biểu đồ hình tròn bằng cách sử dụng một CAShapeLayer cho mỗi lát của chiếc bánh. Ngay cả khi góc kết thúc của một lát bánh bằng với góc bắt đầu của lát liền kề, khử răng cưa là kết quả của màu nền cơ bản xuất hiện giữa mỗi lát cắt nếu đường viền giữa các lát nằm ở một góc.Vấn đề Antialiasing liền kề CAShapeLayer

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

Tôi muốn loại bỏ sự chênh lệch nhỏ giữa lát trong khi vẫn sử dụng khử răng cưa nên kết quả giỏ bánh vẫn có vẻ trơn tru. Về mặt khái niệm, có vẻ như có một cách để áp dụng antialiasing cho toàn bộ CALayer và các slice con của nó sau khi tất cả các slice pie được rút ra, điều đó sẽ thực hiện thủ thuật ... Các slice pie sẽ được khử răng cưa vào nhau thay vì vào lý lịch.

Tôi đã chơi xung quanh với nhiều thuộc tính CALayer như tôi có thể nghĩ đến và đang gặp khó khăn khi tìm thêm thông tin về điều này. Bất kỳ ý tưởng?

CẬP NHẬT: Xem câu trả lời của tôi bên dưới.

Trả lời

5

UPDATE: câu trả lời Rob là khá tốt, nhưng có thể dẫn đến các vấn đề khử răng cưa khác. Tôi đã kết thúc 'lấp đầy' những khoảng trống bằng cách vẽ các đường tròn xuyên tâm rộng 1pt dọc theo góc cuối của mỗi lát bánh, mỗi đường có cùng màu với lát liền kề. Những dòng này được vẽ tại một chỉ số z thấp hơn so với các lát bánh, vì vậy chúng nằm bên dưới. Dưới đây là những gì họ trông giống như không có những lát bánh vẽ trên đầu:

The filler lines with no slices drawn.

Và đây là sản phẩm cuối cùng:

Final result with lines underneath and slices on top.

8

Có thể bạn sẽ không thể làm cho cạnh bánh nướng của bạn gặp chính xác mà không bị nứt. Giải pháp đơn giản nhất là không thử.

Thay vì làm cho các lát bánh của bạn gặp nhau ở các cạnh, làm cho chúng chồng lên nhau. Vẽ lát đầu tiên như một đĩa đầy đủ:

first slice

Sau đó rút ra những miếng thứ hai như một đĩa đầy đủ, ngoại trừ khu vực thích hợp của slice đầu tiên:

second slice

Sau đó vẽ lát thứ ba dưới dạng đĩa đầy đủ, trừ khu vực thích hợp của hai lát đầu tiên:

third slice

Và như vậy:

fourth slicefifth slice

Dưới đây là mã của tôi:

#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

Cảm ơn rất nhiều cho các phản ứng, Rob. Tôi đã thử giải pháp này tại một thời điểm và đã nhìn thấy hiện vật antialiasing từ tối hơn, lớp bên dưới được antialiased vào nền. Nó xuất hiện như một cạnh tối tinh tế xung quanh biểu đồ hình tròn, đặc biệt đáng chú ý ở mép ngoài của các lát màu sáng hơn. Các giải pháp phụ xuyên tâm tôi đã mô tả dường như hoạt động tốt. – Aaron

+0

@Aaron Khi bạn chống bí danh, bạn kết thúc với một vòng màu + alpha pixel xung quanh hình dạng có màu sắc có hiệu quả bí danh. Làm điều này cho nhiều hình dạng với cùng một phác thảo, khu vực bên trong có hiệu quả của bạn sẽ trông ổn nhưng vùng chống răng cưa của bạn sẽ có màu (n) + màu phủ alpha (n-1) + lớp phủ alpha ... màu (0) + alpha. Điều này giải thích hiệu ứng bạn đang thấy. –

Các vấn đề liên quan