How to cut out a hole with radial gradient in view

一笑奈何 提交于 2020-01-03 04:52:04

问题


I have a transparent light hole view, a view overlay super view, and there is a hole gradient round view in the cover view, the super view is still visiable. I have no idea to implement the gradient light hole view, anyone can help me

EDIT ============

I try to add cover view to the full screen, the cover view background color is clear., and add custom CALayer to the cover view layer as sublayer.

the cover view implementation:

@implementation 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

the custom radial gradient layer:

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

and I user it:

 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];

Finally, I got result below.

thanks for @gbk and @matt


回答1:


You can play around a little bit and get

To achieve such result I prepared sample code in playground - just copy-paste it and try.

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


来源:https://stackoverflow.com/questions/46249409/how-to-cut-out-a-hole-with-radial-gradient-in-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!