Masking a CALayer with another CALayer

后端 未结 4 853
灰色年华
灰色年华 2021-02-07 08:49

I\'m trying to make a donut shape with CALayers. One CALayer will be a large circle, the other one will be a smaller circle positioned in its center, masking it.

The la

4条回答
  •  不要未来只要你来
    2021-02-07 09:09

    This is pretty easy using UIBezierPath and a CAShapeLayer as a masking layer. Code sample written as though it's in a UIView subclass.

    Objective-C:

    CGRect outerRect = self.bounds;
    CGFloat inset = 0.2 * outerRect.size.width; // adjust as necessary for more or less meaty donuts
    CGFloat innerDiameter = outerRect.size.width - 2.0 * inset;
    CGRect innerRect = CGRectMake(inset, inset, innerDiameter, innerDiameter);
    UIBezierPath *outerCircle = [UIBezierPath bezierPathWithRoundedRect:outerRect cornerRadius:outerRect.size.width * 0.5];
    UIBezierPath *innerCircle = [UIBezierPath bezierPathWithRoundedRect:innerRect cornerRadius:innerRect.size.width * 0.5];
    [outerCircle appendPath:innerCircle];
    CAShapeLayer *maskLayer = [CAShapeLayer new];
    maskLayer.fillRule = kCAFillRuleEvenOdd; // Going from the outside of the layer, each time a path is crossed, add one. Each time the count is odd, we are "inside" the path.
    maskLayer.path = outerCircle.CGPath;
    self.layer.mask = maskLayer;
    

    Swift:

    let outerRect = self.bounds
    let inset: CGFloat = 0.2 * outerRect.width // adjust as necessary for more or less meaty donuts
    let innerDiameter = outerRect.width - 2.0 * inset
    let innerRect = CGRect(x: inset, y: inset, width: innerDiameter, height: innerDiameter)
    let outerCircle = UIBezierPath(roundedRect: outerRect, cornerRadius: outerRect.width * 0.5)
    let innerCircle = UIBezierPath(roundedRect: innerRect, cornerRadius: innerRect.width * 0.5)
    outerCircle.appendPath(innerCircle)
    let mask = CAShapeLayer()
    mask.fillRule = kCAFillRuleEvenOdd
    mask.path = outerCircle.CGPath
    self.layer.mask = mask
    

提交回复
热议问题