如何在视图中切出具有径向渐变的孔

How to cut out a hole with radial gradient in view

我有透明光孔视图,视图覆盖超视图,覆盖视图中有孔渐变圆形视图,超视图仍然可见。 不知道如何实现渐变光孔视图,谁能帮帮我

编辑 ============

我尝试将cover view添加到全屏,cover view背景颜色清晰。,并将自定义CALayer添加到cover view层作为子层。

封面视图实施:

@实现 CoverView

   - (instancetype)initWithFrame:(CGRect)frame {
     self = [super initWithFrame:frame];
     if (self) {
     self.backgroundColor = [UIColor clearColor];
     }
     return self;
   }

    - (void)setGradientHoleFrame:(CGRect)gradientHoleFrame {
     if (!CGRectEqualToRect(_gradientHoleFrame, gradientHoleFrame)) {
    _gradientHoleFrame = gradientHoleFrame;
      [self loadRadialGradientLayer];
     }
   }

   - (void)loadRadialGradientLayer {
    RadialGradientLayer *layer = [[RadialGradientLayer alloc] init];
    layer.frame = self.bounds;
     layer.raidalGradientFrame = self.gradientHoleFrame;
     [layer setNeedsDisplay];
     [self.layer addSublayer:layer];
    }

@end

自定义径向渐变层:

CGFloat const GRADIENT_WIDTH = 10.0f;

@implementation RadialGradientLayer

- (void)setRaidalGradientFrame:(CGRect)raidalGradientFrame {
  if (!CGRectEqualToRect(_raidalGradientFrame, raidalGradientFrame)) {
    _raidalGradientFrame = raidalGradientFrame;
    [self setNeedsDisplay];
  }
}

- (void)drawInContext:(CGContextRef)context {
  CGContextSaveGState(context);
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  CGFloat colours[8] = { 0.0f, 0.0f, 0.0f, 0.0f,     // Clear region colour.
                         0.0f, 0.0f, 0.0f, 0.8 };   // Blur region colour.
  CGFloat locations[2] = { 0.0f, 1.0f };
  CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colours, locations, 2);
  CGPoint center = CGPointMake(self.raidalGradientFrame.origin.x + self.raidalGradientFrame.size.width / 2,
                               self.raidalGradientFrame.origin.y + self.raidalGradientFrame.size.height / 2);
  CGFloat radius = MIN(self.raidalGradientFrame.size.width / 2, self.raidalGradientFrame.size.height / 2) + GRADIENT_WIDTH;
  CGContextDrawRadialGradient(context, gradient, center, 0.0, center, radius, kCGGradientDrawsAfterEndLocation);

  CGGradientRelease(gradient);
  CGColorSpaceRelease(colorSpace);
}

@end

我使用它:

 CoverView *view = [[CoverView alloc] initWithFrame:[UIScreen mainScreen].bounds];
  // for get hole frame
  CGRect rect = [self.coinPointView.superview convertRect:self.coinPointView.frame toView:view];
  view.gradientHoleFrame = rect;
  [self.tabBarController.view addSubview:view];

终于得到如下结果

感谢@gbk 和@matt

你可以稍微玩一下,得到

为了获得这样的结果,我在 playground 中准备了示例代码 - 只需复制粘贴并尝试即可。

import UIKit
import PlaygroundSupport

class RadialGradientLayer: CALayer {

    required override init() {
        super.init()
        needsDisplayOnBoundsChange = true
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    required override init(layer: Any) {
        super.init(layer: layer)
    }

    //default colors
    public var colors = [UIColor.red.cgColor, UIColor.clear.cgColor]

    override func draw(in ctx: CGContext) {
        ctx.saveGState()

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        var locations = [CGFloat]()
        for i in 0...colors.count-1 {
            locations.append(CGFloat(i) / CGFloat(colors.count))
        }
        let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: locations)
        let center = CGPoint(x: bounds.width / 2.0, y: bounds.height / 2.0)
        let radius = min(bounds.width, bounds.height)
        ctx.drawRadialGradient(gradient!, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: radius, options: CGGradientDrawingOptions(rawValue: 0))
    }    
}

let view = UIView(frame: CGRect(x: 0, y: 0, width: 375, height: 300))
view.backgroundColor = UIColor.green

let label = UILabel(frame: view.bounds)
label.text = "test"
label.font = UIFont.systemFont(ofSize: 30)
label.textAlignment = .center
view.addSubview(label)

let gradientLayer = RadialGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [UIColor.clear.cgColor, UIColor.black.cgColor]
gradientLayer.setNeedsDisplay()

view.layer.addSublayer(gradientLayer)


view