2013-10-15 111 views
2

我以前使用過UIBezierPathCAShapeLayer。但幾乎每次都要用裏面的顏色填充路徑中包含的對象。但是我希望這次能夠填充UIBezierPath包含的對象之外的顏色。iOS:UIBezierPath和CAShapeLayer fillRule

我只是編寫並運行了以下簡單的代碼努力地讓自己熟悉的fillRule屬性:

CAShapeLayer *myLayer = (CAShapeLayer*) self.layer; //size: 320 X 480 
UIBezierPath *testPath = [UIBezierPath bezierPathWithOvalInRect:(CGRect){{100, 100}, 100, 100}]; //a simple circle 
myLayer.fillRule = kCAFillRuleNonZero; // have tried this as well: kCAFillRuleEvenOdd; 
myLayer.path = testPath.CGPath; 
myLayer.fillColor = [UIColor whiteColor].CGColor; 

但顏色仍然充滿裏面。我想知道的是,我如何填補路徑之外的顏色?如果我在這裏使用fillRule錯誤,我想知道是否有其他方法可以實現此目的。提前致謝。

回答

7

主要的問題是你不能真正填充外形外部的,因爲沒有通用的方法來定義這意味着什麼。你需要做的是首先在你的形狀的「外部」周圍繪製一條路徑,然後將該圓形添加爲子路徑。你怎麼做取決於你想使用哪個填充規則。 EVENODD是最簡單的:

CAShapeLayer *myLayer = (CAShapeLayer*) self.layer; 
UIBezierPath *testPath = [UIBezierPath bezierPathWithRect:self.bounds]; 
[testPath appendPath:[UIBezierPath bezierPathWithOvalInRect:(CGRect){{100, 100}, 100, 100}]]; 
myLayer.fillRule = kCAFillRuleEvenOdd; 
myLayer.path = testPath.CGPath; 
myLayer.fillColor = [UIColor whiteColor].CGColor; 

非零則是有點困難,因爲你必須強制路徑是逆時針這是不是大多數的UIBezierPath方便的方法的選擇:

CAShapeLayer *myLayer = (CAShapeLayer*) self.layer; 
UIBezierPath *testPath = [UIBezierPath bezierPathWithRect:self.bounds]; 
UIBezierPath *counterClockwise = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:100 startAngle:0 endAngle:M_PI clockwise:NO]; 
[counterClockwise appendPath:[UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:100 startAngle:M_PI endAngle:0 clockwise:NO]]; 
[testPath appendPath:counterClockwise]; 
myLayer.fillRule = kCAFillRuleNonZero; 
myLayer.path = testPath.CGPath; 
myLayer.fillColor = [UIColor redColor].CGColor; 

根據你如何構建你的實際路徑,它可能不會有任何區別。

如果你還沒有看到它,winding rules documentation有一些很好的圖表,我覺得很有幫助。

+0

嗨,嘿,你真的很擅長這個。 +1。謝謝。爲了完整性,「CGMutablePath」可以做到同樣的事情嗎?提前致謝。 – Unheilig

+0

儘管如此,我會首先標記這個答案。希望你可以詳細闡述一下'CGMutablePath'。 – Unheilig

+1

是的,基本思想同樣適用於'CGPath'使用CGPathAddArc等。 – frozendevil