ios - 从另一个图层中减去图层,混合?

标签 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)
想法
  • 从Layer中减去,不知道是否可行
  • 混合,不知道如何使用 CALayer 进行

谢谢!! :)

最佳答案

我建议做三件事。

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

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

enter image description here

  • 将圆形图层上的填充规则设置为奇偶:

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

    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

    希望有帮助。

    关于ios - 从另一个图层中减去图层,混合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26594426/

    相关文章:

    iphone - 自定义字体在iOS 5中不起作用

    ios - 如何在 xib 文件中打开 ViewController

    ios - IBDesignable 在框架中不适用于嵌入式项目

    ios - drawRect - 绘制星形

    iphone - 试图复制 iPhone 键盘按钮

    ios - UINavigationBar Appearance on Modal Not Setting

    iOS - 处理大图像

    ios - 何时在 iOS 应用程序中使用 sqlite3_close

    ios - .While Editing 期间消失的清除按钮

    ios - 在 UIImageView 上添加一个圆形 mask 层