18

だから、私はCALayerマスクを持っていて、このレイヤーのマスクの周りに境界線を追加したいと思っています。たとえば、三角形のマスクをレイヤーに設定し、そのレイヤーの周りに境界線を設定したいとします。

誰でもこの問題を解決するのを手伝ってもらえますか?

4

6 に答える 6

5

次のコード例を検討してください。

- (void)drawRect:(CGRect)rect {
    CAShapeLayer *maskLayer = [CAShapeLayer layer];

    //Modify to your needs
    CGFloat maskInsetWidth = 5.0f;
    CGFloat maskInsetHeight = 5.0f;
    CGFloat maskCornerRadius = 5.0f;
    CGFloat borderWidth = 2.0f;
    UIColor *borderColor = [UIColor blackColor];

    CGRect insetRect = CGRectInset(self.bounds, maskInsetWidth, maskInsetHeight);
    insetRect.size.width = MAX(insetRect.size.width, 0);
    insetRect.size.height = MAX(insetRect.size.height, 0);

    CGPathRef path = [UIBezierPath bezierPathWithRoundedRect:insetRect cornerRadius:maskCornerRadius].CGPath;

    if (borderWidth > 0.0f && borderColor != nil) {
        CAShapeLayer *borderLayer = [CAShapeLayer layer];

        [borderLayer setPath:path];
        [borderLayer setLineWidth:borderWidth * 2.0f];
        [borderLayer setStrokeColor:borderColor.CGColor];
        [borderLayer setFillColor:[UIColor clearColor].CGColor];

        borderLayer.frame = self.bounds;
        [self.layer addSublayer:borderLayer];
    }
    [maskLayer setPath:path];
    [maskLayer setFillRule:kCAFillRuleEvenOdd];
    maskLayer.frame = self.bounds;
    [self.layer setMask:maskLayer];
}
于 2015-01-22T15:27:15.797 に答える
4

いくつかの提案:

  • 境界線の代わりに不透明な影を使用します (ぼかし効果が得られます)。
  • 別のレイヤーを作成し、境界線に必要な色で背景色を設定し、境界線の幅をシミュレートするために既に持っているマスクよりもわずかに大きいマスクでマスクし、レイヤーの後ろの中央に配置します(すべての形状で機能しない場合があります) )。
  • たとえば、vImageDilate一連の関数 (より複雑で、パフォーマンスの問題が発生する可能性があります) を使用して、境界線を計算するためにマスク イメージに対してモルフォロジー操作を実行します。
  • 形状が分かっていて数学的に記述できる場合は、それを描画し、Core Graphics 関数を使用して明示的にストロークします。
  • または、同じ場合 (数学的に既知の形状)、 a を使用しCAShapeLayerて境界線を描画します。
于 2013-04-05T13:10:01.107 に答える
1

一般に、マスクの周囲に境界線を簡単に設定することはできません。これは、画像の透明ピクセルの周囲に境界線を配置するように要求するようなものです。おそらく、画像フィルターを使用して行うことができます。より具体的なケースで、プレーンな CAShapeLayer を使用している場合、これを行うコードのサンプルを次に示します。

[CATransaction begin];
[CATransaction setDisableActions:YES];

CALayer *hostLayer = [CALayer layer];
hostLayer.backgroundColor = [NSColor blackColor].CGColor;
hostLayer.speed  = 0.0;
hostLayer.timeOffset = 0.0;

CALayer *maskedLayer = [CALayer layer];
maskedLayer.backgroundColor = [NSColor redColor].CGColor;
maskedLayer.position = CGPointMake(200, 200);
maskedLayer.bounds   = CGRectMake(0, 0, 200, 200);

CAShapeLayer *mask = [CAShapeLayer layer];
mask.fillColor = [NSColor whiteColor].CGColor;
mask.position = CGPointMake(100, 100);
mask.bounds   = CGRectMake(0, 0, 200, 200);

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 100, 100);
for (int i=0;  i<20;  i++) {
    double x = arc4random_uniform(2000) / 10.0;
    double y = arc4random_uniform(2000) / 10.0;
    CGPathAddLineToPoint(path, NULL, x, y);
}
CGPathCloseSubpath(path);

mask.path = path;

CGPathRelease(path);

maskedLayer.mask = mask;

CAShapeLayer *maskCopy = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:mask]];
maskCopy.fillColor = NULL;
maskCopy.strokeColor = [NSColor yellowColor].CGColor;
maskCopy.lineWidth = 4;
maskCopy.position = maskedLayer.position;

// Alternately, don't set the position and add the copy as a sublayer
// maskedLayer.sublayers = @[maskCopy];

hostLayer.sublayers = @[maskedLayer,maskCopy];

_contentView.layer = hostLayer;
_contentView.wantsLayer = YES;

[CATransaction commit];

基本的に任意のパスを作成し、それをマスクとして設定します。次に、このレイヤーのコピーを使用してパスをストロークします。探している正確な効果を得るには、微調整が必​​要になる場合があります。

于 2013-04-05T13:24:26.013 に答える