How to draw CALayer border around its mask?

后端 未结 6 1534
谎友^
谎友^ 2021-02-07 09:39

So, I have a CALayer, which has a mask & I want to add border around this layer\'s mask. For example, I have set triangle mask to the layer and I want to have b

6条回答
  •  面向向阳花
    2021-02-07 09:57

    In a general case you cannot easily set a border around a mask. That's like asking to put a border around the transparent pixels of an image. Perhaps it may be done using image filters. In some more specific case, if you are using plain CAShapeLayer then here is a sample of code that does that:

    [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];
    

    It basically creates an arbitrary path and sets it as the mask. It then takes a copy of this layer to stroke the path. You might need to tweak things to get the exact effect you are looking for.

提交回复
热议问题