Substract CALayer из другого, смесь?

На следующем изображении синий круг предназначен только для целей отладки. Моя цель состоит в том, что каждый слой за синим кругом должен быть прозрачным. Я хочу только видеть, что находится за пределами синего круга.

введите описание изображения здесь

Вот код, написанный быстрым:

let croissantView = UIView(frame: CGRectMake(100, 100, 100, 100)) croissantView.backgroundColor = UIColor.clearColor() self.view.addSubview(croissantView) let radius = 50 as CGFloat let width = 50 as CGFloat let origin = CGPointMake(0, 100) let end = CGPointMake(100,100) let highAmplitude = CGPointMake(50,180) let lowAmplitude = CGPointMake(50,150) let quad = UIBezierPath() quad.moveToPoint(origin) quad.addQuadCurveToPoint(end, controlPoint: highAmplitude) quad.closePath() let quad2 = UIBezierPath() quad2.moveToPoint(origin) quad2.addQuadCurveToPoint(end, controlPoint: lowAmplitude) quad2.closePath() let layer = CAShapeLayer() layer.path = quad.CGPath layer.strokeColor = UIColor.greenColor().CGColor layer.fillColor = UIColor.blackColor().CGColor croissantView.layer.addSublayer(layer) let anim = CABasicAnimation(keyPath: "path") anim.duration = 3 anim.repeatCount = 20 anim.fromValue = quad.CGPath anim.toValue = quad2.CGPath anim.autoreverses = true layer.addAnimation(anim, forKey: "animQuad") let animRotate = CABasicAnimation(keyPath: "transform.rotation") animRotate.duration = 5 animRotate.repeatCount = 20 animRotate.fromValue = 0 animRotate.toValue = 360 * CGFloat(M_PI) / 180 croissantView.layer.addAnimation(animRotate, forKey: "animRotate") let circle = UIBezierPath(arcCenter: croissantView.center, radius: 75, startAngle: 0, endAngle: 360 * CGFloat(M_PI) / 180, clockwise: true); let circleLayer = CAShapeLayer() circleLayer.path = circle.CGPath circleLayer.fillColor = UIColor.blueColor().CGColor circleLayer.opacity = 0.6 self.view.layer.addSublayer(circleLayer) 

мысли

  • Substract from Layer, не знаю, возможно ли
  • Blend, не знаю, как это сделать с помощью CALayer

Благодаря !! 🙂

Есть три вещи, которые я бы предложил.

  1. Измените вид круассана на слой (не уверен, что это было необходимо, но это то, что я сделал)

  2. Создайте CGPath для вашей формы круга, которая может инвертировать маску. Вы делаете это, обертывая внешний прямоугольник вокруг своего круга, чтобы путь выглядел так:

введите описание изображения здесь

  1. Установите правило заполнения на уровне формы круга до четного:

     circleLayer.fillRule = kCAFillRuleEvenOdd 

Вот как это выглядит:

введите описание изображения здесь

Я адаптировал ваш код, чтобы попытаться, и вот что я придумал. Ваш пробег может варьироваться:

 func applyMask() { let mainLayer = CALayer() mainLayer.bounds = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0) mainLayer.position = CGPoint(x: 200.0, y: 200.0) // Set the color for debugging mainLayer.backgroundColor = UIColor.orangeColor().CGColor self.view.layer.addSublayer(mainLayer) let radius = 50 as CGFloat let width = 50 as CGFloat let origin = CGPointMake(0, 100) let end = CGPointMake(100,100) let highAmplitude = CGPointMake(50,180) let lowAmplitude = CGPointMake(50,150) let quad = UIBezierPath() quad.moveToPoint(origin) quad.addQuadCurveToPoint(end, controlPoint: highAmplitude) quad.closePath() let quad2 = UIBezierPath() quad2.moveToPoint(origin) quad2.addQuadCurveToPoint(end, controlPoint: lowAmplitude) quad2.closePath() let layer = CAShapeLayer() layer.path = quad.CGPath layer.strokeColor = UIColor.greenColor().CGColor layer.fillColor = UIColor.blackColor().CGColor mainLayer.addSublayer(layer) let anim = CABasicAnimation(keyPath: "path") anim.duration = 3 anim.repeatCount = 20 anim.fromValue = quad.CGPath anim.toValue = quad2.CGPath anim.autoreverses = true layer.addAnimation(anim, forKey: "animQuad") let animRotate = CABasicAnimation(keyPath: "transform.rotation") animRotate.duration = 5 animRotate.repeatCount = 20 animRotate.fromValue = 0 animRotate.toValue = 360 * CGFloat(M_PI) / 180 mainLayer.addAnimation(animRotate, forKey: "animRotate") // Build a Circle CGPath var circlePath = CGPathCreateMutable() CGPathAddEllipseInRect(circlePath, nil, CGRectInset(mainLayer.bounds, -20.0, -20.0)) // Invert the mask by adding a bounding rectangle CGPathAddRect(circlePath, nil, CGRectInset(mainLayer.bounds, -100.0, -100.0)) CGPathCloseSubpath(circlePath) let circleLayer = CAShapeLayer() circleLayer.fillColor = UIColor.blueColor().CGColor circleLayer.opacity = 0.6 // Use the even odd fill rule so that our path gets inverted circleLayer.fillRule = kCAFillRuleEvenOdd circleLayer.path = circlePath mainLayer.mask = circleLayer mainLayer.addSublayer(layer) } 

Вот проект, в котором я пробовал: https://github.com/perlmunger/SwiftVertedMask

Надеюсь, это поможет.

  • stringByReplacingOccurrencesOfString, дающий странную ошибку
  • nils найдены разворачивание Необязательные значения в запросе MKLocalSearch
  • Передача данных в определенный контроллер просмотра без ввода контроллера Swift
  • Использование SKCameraNode для универсального приложения SWIFT
  • Ошибка при интеграции Королевства
  • Swift ResearchKit Условный ORKOrderedTask
  • Изменение рамки UITableview после прокрутки благодаря Autolayout
  • Изменить цвет элемента с отключенной кнопкой в ​​iOS
  • Google Места - текущие места: внутренняя ошибка в библиотеке API Places
  • Каково техническое определение опциона в Swift?
  • Как прослушивать жесты касания на разных элементах управления в одном представлении?
  • Давайте будем гением компьютера.