2012-11-24 43 views
7

aight vì vậy tôi muốn vẽ một hình tam giác như vậy:Làm thế nào để vẽ một hình tam giác với góc tròn sử dụng quartz2d/CoreGraphics

rounded triangle

Hiện nay tôi đang sử dụng một sự kết hợp của một CAShapeLayer và tạo ra các đường dẫn với một UIBezierPath (mã dưới đây) và sau đó áp dụng đó như một mặt nạ cho lớp khác (self.layer như tôi đang ở trong một lớp con UIView và thay vì thiết lập lớp lớp tôi làm theo cách này để tôi có thể bảo tồn lớp ban đầu)

anyways mã:

_bezierPath = [[UIBezierPath bezierPath] retain]; 
#define COS30 0.86602540378 
#define SIN30 0.5 
[_bezierPath moveToPoint:(CGPoint){self.frame.size.width/2.f-r*SIN30,r*COS30}]; 
[_bezierPath addArcWithCenter:(CGPoint){self.frame.size.width/2.f,r*COS30*2.f} radius:r startAngle:2*M_PI/3.f endAngle:M_PI/3.f clockwise:YES]; 
[_bezierPath addLineToPoint:(CGPoint){self.frame.size.width-r*SIN30,self.frame.size.height-r*COS30}]; 
[_bezierPath addArcWithCenter:(CGPoint){self.frame.size.width-r*SIN30-r,self.frame.size.height-r*COS30} radius:r startAngle:0.f endAngle:-M_PI/3.f clockwise:YES]; 
[_bezierPath addLineToPoint:(CGPoint){r*SIN30,self.frame.size.height-r*COS30}]; 
[_bezierPath addArcWithCenter:(CGPoint){r*SIN30+r,self.frame.size.height-r*COS30} radius:r startAngle:4*M_PI/3.f endAngle:M_PI clockwise:YES]; 
[_bezierPath closePath]; 
CAShapeLayer *s = [CAShapeLayer layer]; 
s.frame = self.bounds; 
s.path = _bezierPath.CGPath; 
self.layer.mask = s; 
self.layer.backgroundColor = [SLInsetButton backgroundColorForVariant:SLInsetButtonColorForSLGamePieceColor(_color)].CGColor; 

và tiếc là kết quả không phải là điều tôi đang tìm kiếm, thay vì các góc trở thành nút bấm nhỏ (như thể quay của nó quá nhiều)

Cảm ơn trước

+0

tại sao cos (30) chứ không phải 60? – AlexWien

+0

bạn đang đề cập đến trường hợp nào? – DanZimm

Trả lời

14

Một người bạn tuyệt vời (John Heaton trong trường hợp bạn chạy vào anh ta, anh ấy khá tuyệt vời) nhắc tôi về lineCap và thuộc tính lineJoin mà đồ họa cốt lõi triển khai.

Một nơi nào đó:

#define border (10.f) 

Và trong giao diện của bạn:

@property (nonatomic, strong) UIBezierPath *bezierPath; 

Và trong init của bạn, tạo ra một con đường ngắn như thế này:

CGFloat inset = border/2.f; 
UIBezierPath *bezierPath = [UIBezierPath bezierPath]; 
[bezierPath moveToPoint:(CGPoint){ self.frame.size.width/2.f, inset }]; 
[bezierPath addLineToPoint:(CGPoint){ self.frame.size.width - inset, self.frame.size.height - inset }]; 
[bezierPath addLineToPoint:(CGPoint){ a, self.frame.size.height - a }]; 
[bezierPath closePath]; 

self.bezierPath = bezierPath; 

Và sau đó trong phương pháp drawRect: của bạn thực hiện một số việc như sau:

CGContextRef c = UIGraphicsGetCurrentContext(), context = c; 
CGColorRef col = [UIColor redColor].CGColor; 
CGColorRef bcol = [UIColor redColor].CGColor; 
CGContextSetFillColorWithColor(c, col); 
CGContextSetStrokeColorWithColor(c, bcol); 
CGContextSetLineWidth(c, border); 
CGContextSetLineJoin(c, kCGLineJoinRound); 
CGContextSetLineCap(c, kCGLineCapRound); 
CGContextAddPath(c, self.bezierPath.CGPath); 
CGContextStrokePath(c); 
CGContextAddPath(c, self.bezierPath.CGPath); 
CGContextFillPath(c); 

Và đó đúng cách sẽ cung cấp cho bạn góc tròn trên một hình tam giác, còn với tùy chọn để có đường viền hoặc phác thảo

+0

Cân nhắc việc thay thế '# define' bằng' const'! –

+0

Tôi đã chọn sử dụng macro như trái ngược với cái gì đó như 'static const' vì bạn không cần phải tham chiếu đến con trỏ, kiểm tra kiểu bổ sung là không cần thiết ở đây (nó được sử dụng trong một thường trình giả định nó là một float) và nó mở ra khả năng cung cấp hằng số này tại thời gian biên dịch hoặc với cli args hoặc trong cấu hình của xcode (ofc) tên 'border' không phải là tốt nhất và nên được thay đổi, nhưng mã này không nên đơn giản là copy/dán và nên được đọc qua và suy nghĩ về). – DanZimm

+0

Tôi hiểu, nhưng không phải toàn bộ dự án đã được biên dịch lại nếu macro bị thay đổi? –

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