2012-11-24 5 views
7

Aight so möchte ich wie so ein Dreieck zeichnen:Wie ein Dreieck mit abgerundeten Ecken zeichnen quartz2d/Core Graphics mit

rounded triangle

Derzeit bin ich eine Kombination aus einem CAShapeLayer verwenden und den Pfad zu schaffen mit ein UIBezierPath (der Code ist unten) und dann das als Maske für eine andere Ebene (self.layer, wie ich in einer UIView-Unterklasse bin, und anstatt die Ebenenklasse zu setzen, mache ich es so, damit ich die ursprüngliche Ebene beibehalten kann)

sowieso der Code:

_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; 

und leider das Ergebnis ist nicht das, was ich suchte, anstatt die Ecken werden kleine Noppen (als ob es zu viel drehen)

Vielen Dank im Voraus

+0

warum cos (30) und nicht mehr als 60? – AlexWien

+0

In welchem ​​Fall beziehen Sie sich? – DanZimm

Antwort

14

Ein brillanten Freund (John Heaton bei Du rennst ihm entgegen, er ist ziemlich cool. Er erinnerte mich an die LineCap- und LineJoin-Eigenschaften, die Core-Grafiken verwenden.

Irgendwo:

#define border (10.f) 

Und in Ihrer Schnittstelle:

@property (nonatomic, strong) UIBezierPath *bezierPath; 

Und in Ihrer init einen kurzen Pfad so erstellen:

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; 

Und dann in Ihrer drawRect: Methode Folgendes tun:

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); 

Und das wird richtig geben Sie Ecken auf einem Dreieck abgerundet, auch mit der Möglichkeit, eine Grenze zu haben, oder zu skizzieren

+0

Überlegen Sie '' define' durch 'const' zu ersetzen! –

+0

Ich habe gewählt, ein Makro im Gegensatz zu etwas wie 'statisches const' zu verwenden, weil Sie nicht auf die Zahl mit einem Zeiger jemals verweisen müssen, ist die zusätzliche Typprüfung hier nicht notwendig (es wird in einer Routine verwendet, die es annimmt) ein float) und es öffnet die Fähigkeit, diese Konstante zur Kompilierzeit entweder mit cliargs oder in der xcode-Konfiguration zu liefern (der Name 'border' ist nicht der beste und sollte geändert werden, aber dieser Code sollte nicht einfach kopiert/eingefügt und sollte gelesen und darüber nachgedacht werden). – DanZimm

+0

Ich verstehe, aber ist das ganze Projekt nicht neu kompiliert, wenn das Makro geändert wird? –