16

CALayersでドーナツの形を作ろうとしています。1つのCALayerは大きな円になり、もう1つは中央に配置された小さな円になり、それをマスクします。

大きな円は問題なく表示されますが、電話をかけるとcircle.mask = circleMask;ビューが空になります。

これが私のコードです:

AriDonut.h

#import <UIKit/UIKit.h>

@interface AriDonut : UIView
-(id)initWithRadius:(float)radius;
@end

AriDonut.m

#import "AriDonut.h"
#import <QuartzCore/QuartzCore.h>

@implementation AriDonut

-(id)initWithRadius:(float)radius{
    self = [super initWithFrame:CGRectMake(0, 0, radius, radius)];
    if(self){

        //LARGE CIRCLE
        CALayer *circle = [CALayer layer];
        circle.bounds = CGRectMake(0, 0, radius, radius);
        circle.backgroundColor = [UIColor redColor].CGColor;
        circle.cornerRadius = radius/2;
        circle.position = CGPointMake(radius/2, radius/2);

        //SMALL CIRLCE
        CALayer *circleMask = [CALayer layer];
        circleMask.bounds = CGRectMake(0, 0, 10, 10);
        circleMask.cornerRadius = radius/2;
        circleMask.position = circle.position;

        //circle.mask = circleMask;

        [self.layer addSublayer:circle];

    }

    return self;
}

大きな円のスーパーレイヤーを次のように設定してみました。

CALayer *theSuper = circle.superlayer;
theSuper = nil;

しかし、それは違いを生みませんでした。

また、CircleのmasksToBoundsプロパティをYESとNOに設定してみましたが、違いはありませんでした。

何かご意見は?

4

4 に答える 4

15

実際、@ Davidが現在の(iOS 5.1)CALayerマスクを元に戻すことはできないことを示しているため、透明な穴を単純な円形のCALayerにするために使用する場合は、問題が発生します。

ドーナツを手に入れるためにできることは、円形のCALayerをbackgroundColor透明にすることですが、それにaborderColorと幅を与えborderWidthます。これがダンキンコードです:

    CALayer *theDonut = [CALayer layer];
    theDonut.bounds = CGRectMake(0,0, radius, radius);
    theDonut.cornerRadius = radius/2;
    theDonut.backgroundColor = [UIColor clearColor].CGColor;

    theDonut.borderWidth = radius/5;
    theDonut.borderColor = [UIColor orangeColor].CGColor;

    [self.layer addSublayer:theDonut];
于 2012-07-31T15:44:58.470 に答える
9

これは、UIBezierPathとCAShapeLayerをマスキングレイヤーとして使用すると非常に簡単です。UIViewサブクラスにあるかのように記述されたコードサンプル。

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;

迅速:

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
于 2015-12-06T03:56:41.720 に答える
5

マスクとして使用されるのは、マスキングレイヤーコンテンツのアルファ値です。(マスクをマスクとして使用するのではなく、サブレイヤーとして追加する場合。サブレイヤーで覆われているものはすべて、マスクとして使用すると表示されます。サブレイヤーで覆われていないものは、マスクとして使用すると非表示になります。 。)

あなたの小さな円は完全に透明なので、すべてが隠されています(隠されています)。を任意の完全に不透明な色に設定するbackgroundColorと(マスクにはアルファ値のみが使用されます)、それらのピクセルが通過します。

これはあなたが望むものの逆であることに注意してください。これにより、「ドーナツの穴」だけが表示されます。リバースマスクを実行するための組み込みの方法はありません。代わりに、を使用したり、を使用しCAShapeLayerたりするなど、別の方法でマスクのコンテンツを描画する必要がありますdrawInContext:

于 2012-07-30T11:21:20.053 に答える
1

CAShapeLayerマスキングに成功しましたCALayerCAShapeLayer使用したマスキングの形状を指定しますUIBezierPath

この質問への回答にコードを投稿しました:UIBezierPathのリバースパスを取得する方法。ドーナツの形については、コメント行のコメントを外してください。

于 2013-03-08T14:25:50.443 に答える