Создайте маску CALayer, комбинируя несколько путей

Я пытаюсь создать маску для CALayer, содержащего изображение. Эта маска должна использовать объединение нескольких путей или обратное объединение. С точки зрения диаграммы Венна, которая могла бы быть дизъюнкцией или совместным отказом (посмотрите здесь диаграмму Венна, которую я не могу опубликовать: https://en.wikipedia.org/wiki/Logical_connective). Я также создал ветку на специализированном iOS-форуме с большим количеством графики и примерами кода: http://www.raywenderlich.com/forums/viewtopic.php?f=2&t=7155

Мне удается создать первый случай: объединение нескольких путей (дизъюнкция).

Вы можете скопировать код в новое одноэкранное приложение, чтобы попробовать его (не забудьте включить платформу Quartz):

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // create a yellow background
    UIView *bg = [[UIView alloc] initWithFrame:self.view.bounds];
    bg.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:bg];

    // create the layer on top of the yellow background that will be masked
    CALayer *imageLayer = [CALayer layer];
    imageLayer.frame = self.view.layer.bounds;
    imageLayer.backgroundColor = [[UIColor blueColor] CGColor];

    // create the mask that will be applied to the layer on top of the
    // yellow background
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.fillRule = kCAFillRuleEvenOdd;
    maskLayer.frame = self.view.frame;
    CAShapeLayer *maskSubLayer1 = [CAShapeLayer layer];
    maskSubLayer1.fillRule = kCAFillRuleEvenOdd;
    maskSubLayer1.frame = self.view.frame;
    CAShapeLayer *maskSubLayer2 = [CAShapeLayer layer];
    maskSubLayer2.fillRule = kCAFillRuleEvenOdd;
    maskSubLayer2.frame = self.view.frame;

    // add the paths to sublayers of the mask
    maskSubLayer1.path = CGPathCreateWithRect((CGRect){{100, 140}, {100, 150}}, nil);
    maskSubLayer2.path = CGPathCreateWithEllipseInRect((CGRect){{80, 40}, {190, 190}}, nil);
    // add the sublayers to the mask
    // (instead of using CGPathAddPath())
    [maskLayer addSublayer:maskSubLayer1];
    [maskLayer addSublayer:maskSubLayer2];
    // apply the mask to the layer on top of the yellow background
    imageLayer.mask = maskLayer;
    [self.view.layer addSublayer:imageLayer];

}

Однако обратное выглядит неукротимым, например, с маскированной маской:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // create a yellow background
    UIView *bg = [[UIView alloc] initWithFrame:self.view.bounds];
    bg.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:bg];

    // create the layer on top of the yellow background that will be masked
    CALayer *imageLayer = [CALayer layer];
    imageLayer.frame = self.view.layer.bounds;
    imageLayer.backgroundColor = [[UIColor blueColor] CGColor];

    // create the mask that will be applied to the layer on top of the
    // yellow background
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.fillRule = kCAFillRuleEvenOdd;
    maskLayer.frame = self.view.frame;
    CAShapeLayer *maskSubLayer1 = [CAShapeLayer layer];
    maskSubLayer1.fillRule = kCAFillRuleEvenOdd;
    maskSubLayer1.frame = self.view.frame;
    CAShapeLayer *maskSubLayer2 = [CAShapeLayer layer];
    maskSubLayer2.fillRule = kCAFillRuleEvenOdd;
    maskSubLayer2.frame = self.view.frame;

    // add the paths to sublayers of the mask
    maskSubLayer1.path = CGPathCreateWithRect((CGRect){{100, 140}, {100, 150}}, nil);
    [maskLayer addSublayer:maskSubLayer1];
    maskSubLayer2.path = CGPathCreateWithEllipseInRect((CGRect){{80, 40}, {190, 190}}, nil);
    [maskLayer addSublayer:maskSubLayer2];
    // use the maskLayer to mask the maskBackgroundLayer
    CALayer *maskBackgroundLayer = [CAShapeLayer layer];
    maskBackgroundLayer.frame = self.view.layer.bounds;
    maskBackgroundLayer.backgroundColor = [[UIColor greenColor] CGColor];
    maskBackgroundLayer.mask = maskLayer;

    // apply the maskBackgroundLayer to the layer on top of the yellow background
    imageLayer.mask = maskBackgroundLayer;
    [self.view.layer addSublayer:imageLayer];
    // just for testing: instead of the 2 lines above look at the maskBackgroundLayer
//    [self.view.layer addSublayer:maskBackgroundLayer];

}

Я ищу идеи, как добиться этого эффекта.

Подобные вопросы: iOS - обтравочное объединение двух путей с использованием UIBezierPath appendPath(не применимо в моем случае, поскольку пересечение может быть нерегулярным). Объединение пересекающихся CGPaths на iOS(неразрешено)

0 ответов

Другие вопросы по тегам