从另一个中减去Laye​​r,混合?

时间:2014-10-27 18:33:52

标签: ios swift core-graphics core-animation calayer

在下图中,蓝色圆圈仅用于调试目的。我的目标是蓝色圆圈后面的每一层都应该是透明的。我只想看到蓝色圆圈外的东西。

enter image description here

以下是用swift编写的代码:

    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)
思考
  • 从图层中提取,不知道是否可行
  • 混合,不知道如何使用CALayer

谢谢!! :)

1 个答案:

答案 0 :(得分:2)

我建议有三件事。

  1. 将羊角面包视图更改为图层(不确定这是否必要,但这就是我所做的)

  2. 为圆形创建一个CGPath,可以将其蒙版反转。您可以通过在圆周上包裹外部矩形来实现此目的,使路径如下所示:

  3. enter image description here

    1. 将圆形图层上的填充规则设置为偶数:

      circleLayer.fillRule = kCAFillRuleEvenOdd
      
    2. 这就是它的样子:

      enter image description here

      我调整了你的代码来尝试它,这就是我想出来的。您的里程可能会有所不同:

      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

      希望有所帮助。