阴影仅在左侧和上侧遮罩边界。是什么原因造成的?
Shadows masks to bounds only on the left and upper side. What causes this?
我正在尝试实现一项允许向透明按钮添加阴影的功能。为此,我正在创建一个图层来掩盖视图内的阴影。但是,我的阴影在左侧和上侧被剪裁,但在右侧和下侧没有剪裁。
这是它的外观(这不是透明按钮,但它们也可以正常工作,只是阴影被剪裁成这样。):
这是我实现此目的的代码:
private func applyShadow() {
layer.masksToBounds = false
if shouldApplyShadow && shadowLayer == nil {
shadowLayer = CAShapeLayer()
let shapePath = CGPath(roundedRect: bounds, cornerWidth: cornerRadi, cornerHeight: cornerRadi, transform: nil)
shadowLayer.path = shapePath
shadowLayer.fillColor = backgroundColor?.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowRadius = shadowRadius ?? 8
shadowLayer.shadowColor = (shadowColor ?? .black).cgColor
shadowLayer.shadowOffset = shadowOffset ?? CGSize(width: 0, height: 0)
shadowLayer.shadowOpacity = shadowOpacity ?? 0.8
layer.insertSublayer(shadowLayer!, at: 0)
/// If there's background color, there is no need to mask inner shadows.
if backgroundColor != .none && !(innerShadows ?? false) {
let maskLayer = CAShapeLayer()
maskLayer.path = { () -> UIBezierPath in
let path = UIBezierPath()
path.append(UIBezierPath(cgPath: shapePath))
path.append(UIBezierPath(rect: UIScreen.main.bounds))
path.usesEvenOddFillRule = true
return path
}().cgPath
maskLayer.fillRule = .evenOdd
shadowLayer.mask = maskLayer
}
}
}
我认为这与奇偶填充规则算法有关,我不确定。但是我怎样才能克服这个剪裁问题呢?
提前致谢。
编辑:
这是应用阴影时带有边框和文本的透明按钮的外观。我不想要。
它应该是这样的。内部没有阴影,但背景颜色也很清晰。 (除了剪裁的顶部和左侧):
我认为有几个问题...
您正在将 UIBezierPath(rect: UIScreen.main.bounds)
附加到您的路径,但这会将左上角放在图层的左上角... "clips" 顶部-左影.
如果您 DO 有背景颜色,您还需要剪掉这些角,否则它们会 "bleed" 在圆角之外角落.
试一试(仅稍作修改)。它被指定为 @IBDesignable
,因此您可以在 Storyboard / Interface Builder 中查看它的外观(我没有将任何属性设置为可检查 - 如果您愿意,我会把它留给您):
@IBDesignable
class MyRSButton: UIButton {
var shouldApplyShadow: Bool = true
var innerShadows: Bool?
var cornerRadi: CGFloat = 8.0
var shadowLayer: CAShapeLayer!
var shadowRadius: CGFloat?
var shadowColor: UIColor?
var shadowOffset: CGSize?
var shadowOpacity: Float?
override func layoutSubviews() {
super.layoutSubviews()
applyShadow()
}
private func applyShadow() {
// needed to prevent background color from bleeding past
// the rounded corners
cornerRadi = bounds.size.height * 0.5
layer.cornerRadius = cornerRadi
layer.masksToBounds = false
if shouldApplyShadow && shadowLayer == nil {
shadowLayer = CAShapeLayer()
let shapePath = CGPath(roundedRect: bounds, cornerWidth: cornerRadi, cornerHeight: cornerRadi, transform: nil)
shadowLayer.path = shapePath
shadowLayer.fillColor = backgroundColor?.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowRadius = shadowRadius ?? 8
shadowLayer.shadowColor = (shadowColor ?? .black).cgColor
shadowLayer.shadowOffset = shadowOffset ?? CGSize(width: 0, height: 0)
shadowLayer.shadowOpacity = shadowOpacity ?? 0.8
layer.insertSublayer(shadowLayer!, at: 0)
/// If there's background color, there is no need to mask inner shadows.
if backgroundColor != .none && !(innerShadows ?? false) {
let maskLayer = CAShapeLayer()
maskLayer.path = { () -> UIBezierPath in
let path = UIBezierPath()
path.append(UIBezierPath(cgPath: shapePath))
// define a rect that is 80-pts wider and taller
// than the button... this will "expand" it from center
let r = bounds.insetBy(dx: -40, dy: -40)
path.append(UIBezierPath(rect: r))
path.usesEvenOddFillRule = true
return path
}().cgPath
maskLayer.fillRule = .evenOdd
shadowLayer.mask = maskLayer
}
}
}
}
结果:
我正在尝试实现一项允许向透明按钮添加阴影的功能。为此,我正在创建一个图层来掩盖视图内的阴影。但是,我的阴影在左侧和上侧被剪裁,但在右侧和下侧没有剪裁。
这是它的外观(这不是透明按钮,但它们也可以正常工作,只是阴影被剪裁成这样。):
这是我实现此目的的代码:
private func applyShadow() {
layer.masksToBounds = false
if shouldApplyShadow && shadowLayer == nil {
shadowLayer = CAShapeLayer()
let shapePath = CGPath(roundedRect: bounds, cornerWidth: cornerRadi, cornerHeight: cornerRadi, transform: nil)
shadowLayer.path = shapePath
shadowLayer.fillColor = backgroundColor?.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowRadius = shadowRadius ?? 8
shadowLayer.shadowColor = (shadowColor ?? .black).cgColor
shadowLayer.shadowOffset = shadowOffset ?? CGSize(width: 0, height: 0)
shadowLayer.shadowOpacity = shadowOpacity ?? 0.8
layer.insertSublayer(shadowLayer!, at: 0)
/// If there's background color, there is no need to mask inner shadows.
if backgroundColor != .none && !(innerShadows ?? false) {
let maskLayer = CAShapeLayer()
maskLayer.path = { () -> UIBezierPath in
let path = UIBezierPath()
path.append(UIBezierPath(cgPath: shapePath))
path.append(UIBezierPath(rect: UIScreen.main.bounds))
path.usesEvenOddFillRule = true
return path
}().cgPath
maskLayer.fillRule = .evenOdd
shadowLayer.mask = maskLayer
}
}
}
我认为这与奇偶填充规则算法有关,我不确定。但是我怎样才能克服这个剪裁问题呢?
提前致谢。
编辑: 这是应用阴影时带有边框和文本的透明按钮的外观。我不想要。
它应该是这样的。内部没有阴影,但背景颜色也很清晰。 (除了剪裁的顶部和左侧):
我认为有几个问题...
您正在将
UIBezierPath(rect: UIScreen.main.bounds)
附加到您的路径,但这会将左上角放在图层的左上角... "clips" 顶部-左影.如果您 DO 有背景颜色,您还需要剪掉这些角,否则它们会 "bleed" 在圆角之外角落.
试一试(仅稍作修改)。它被指定为 @IBDesignable
,因此您可以在 Storyboard / Interface Builder 中查看它的外观(我没有将任何属性设置为可检查 - 如果您愿意,我会把它留给您):
@IBDesignable
class MyRSButton: UIButton {
var shouldApplyShadow: Bool = true
var innerShadows: Bool?
var cornerRadi: CGFloat = 8.0
var shadowLayer: CAShapeLayer!
var shadowRadius: CGFloat?
var shadowColor: UIColor?
var shadowOffset: CGSize?
var shadowOpacity: Float?
override func layoutSubviews() {
super.layoutSubviews()
applyShadow()
}
private func applyShadow() {
// needed to prevent background color from bleeding past
// the rounded corners
cornerRadi = bounds.size.height * 0.5
layer.cornerRadius = cornerRadi
layer.masksToBounds = false
if shouldApplyShadow && shadowLayer == nil {
shadowLayer = CAShapeLayer()
let shapePath = CGPath(roundedRect: bounds, cornerWidth: cornerRadi, cornerHeight: cornerRadi, transform: nil)
shadowLayer.path = shapePath
shadowLayer.fillColor = backgroundColor?.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowRadius = shadowRadius ?? 8
shadowLayer.shadowColor = (shadowColor ?? .black).cgColor
shadowLayer.shadowOffset = shadowOffset ?? CGSize(width: 0, height: 0)
shadowLayer.shadowOpacity = shadowOpacity ?? 0.8
layer.insertSublayer(shadowLayer!, at: 0)
/// If there's background color, there is no need to mask inner shadows.
if backgroundColor != .none && !(innerShadows ?? false) {
let maskLayer = CAShapeLayer()
maskLayer.path = { () -> UIBezierPath in
let path = UIBezierPath()
path.append(UIBezierPath(cgPath: shapePath))
// define a rect that is 80-pts wider and taller
// than the button... this will "expand" it from center
let r = bounds.insetBy(dx: -40, dy: -40)
path.append(UIBezierPath(rect: r))
path.usesEvenOddFillRule = true
return path
}().cgPath
maskLayer.fillRule = .evenOdd
shadowLayer.mask = maskLayer
}
}
}
}
结果: