如何在视图中切出具有径向渐变的孔
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
我有透明光孔视图,视图覆盖超视图,覆盖视图中有孔渐变圆形视图,超视图仍然可见。 不知道如何实现渐变光孔视图,谁能帮帮我
编辑 ============
我尝试将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