iOS: UIBezierPath and CAShapeLayer fillRule

前端 未结 1 1641
耶瑟儿~
耶瑟儿~ 2021-02-03 16:00

I have used both UIBezierPath and CAShapeLayer before. But almost every time in conjunction with filling the object contained within the path with col

1条回答
  •  太阳男子
    2021-02-03 16:51

    The main problem is that you can't really fill the outside of a shape, since there's no generic way to define what that means. What you need to do is first plot a path around the "outside" of your shape, and then add the circle as a subpath. How you do that depends on which fill rule you want to use. EvenOdd is the easiest:

    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;
    

    NonZero is a little bit harder because you have to force the path to be counter-clockwise which isn't an option for most of the UIBezierPath convenience methods:

    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;
    

    Depending on how you're constructing your actual path it may not make a difference either way.

    If you haven't seen it already, the winding rules documentation has some nice diagrams that I find helpful.

    0 讨论(0)
提交回复
热议问题