如何将角半径应用于CAShapeLayer而非UIView的特定角

时间:2019-04-25 07:56:14

标签: ios swift

我正在绘制一个条形图,我希望每个条形的拐角半径都在顶部。

这是我绘制条形图的代码:

let barLayer = CAShapeLayer()
barLayer.frame = CGRect(x: xPos, y: yPos, width: barWidth, height: mainLayer.frame.height - bottomSpace - yPos)

let path =  UIBezierPath(roundedRect: barLayer.frame, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 5.0, height: 5.0))
barLayer.path = path.cgPath
barLayer.backgroundColor = color.cgColor
mainLayer.addSublayer(barLayer)

将其应用于UIView时,我只需添加另一行:

myView.layer.mask = barLayer 

但是与CAShapeLayer的合作使我有些困惑。如何添加拐角半径?

这是我想要实现的:

enter image description here

edit2:尝试使用两层:

let cornerRadiusLayer = CAShapeLayer()
cornerRadiusLayer.frame = CGRect(x: xPos, y: yPos, width: barWidth, height: mainLayer.frame.height - bottomSpace - yPos)
let path =  UIBezierPath(roundedRect: cornerRadiusLayer.frame, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 5.0, height: 5.0))
cornerRadiusLayer.path = path.cgPath

let barLayer = CALayer()
barLayer.frame = CGRect(x: xPos, y: yPos, width: barWidth, height: mainLayer.frame.height - bottomSpace - yPos)
barLayer.backgroundColor = color.cgColor
barLayer.mask = cornerRadiusLayer
mainLayer.addSublayer(barLayer)

5 个答案:

答案 0 :(得分:1)

如何使用图层的maskedCorners属性?

let barLayer = CAShapeLayer()
barLayer.frame = // some frame
barLayer.masksToBounds = true

barLayer.cornerRadius = // some corner radius
barLayer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]

let gradient = CAGradientLayer()
gradient.colors = // some colors
gradient.frame = barLayer.bounds

barLayer.addSublayer(gradient)

结果:

result

答案 1 :(得分:0)

请添加到CALyer实例。

barLayer.masksToBounds  = true

答案 2 :(得分:0)

我相信您不会看到圆角,因为您设置了barLayer.backgroundColor。尝试改用barLayer.fillColor

答案 3 :(得分:0)

我已经在Playground中进行了一些实验,以重现您的情况,基本上,这段代码可以正常工作:

let view = UIView(frame: CGRect(x: 0, y: 0, width: 560, height: 760))

let mainLayer = CALayer()
mainLayer.frame = view.frame
view.layer.addSublayer(mainLayer)

let cornerRadiusLayer = CAShapeLayer()
let rect = CGRect(x: 30, y: 30, width: 100, height: 100)
let cornerRadiusPath = UIBezierPath(roundedRect: rect, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 5.0, height: 5.0))
cornerRadiusLayer.path = cornerRadiusPath.cgPath

let barLayer = CAShapeLayer()
let rectPath = UIBezierPath(rect: rect)
barLayer.path = rectPath.cgPath
barLayer.mask = cornerRadiusLayer
barLayer.fillColor = UIColor.red.cgColor


mainLayer.addSublayer(barLayer)

您不需要为图层提供框架,UIBezierPath就足够了,您应该使用fillColor而不是backgroundColor。 另外,为您的BarLayer使用CAShapeLayer。

这是上面代码的结果:

enter image description here

答案 4 :(得分:0)

使用像波纹管这样的自定义视图超级简单

@IBDesignable class VerticalGradientView: VariableSeparateCornerView {
    @IBInspectable var topColor: UIColor = UIColor.green {
        didSet {
           setGradient()
        }
    }
    @IBInspectable var bottomColor: UIColor = UIColor.yellow {
        didSet {
            setGradient()
        }
    }

    override class var layerClass: AnyClass {
        return CAGradientLayer.self
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        setGradient()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        initView()
    }

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

    private func initView() {
        self.roundCorners(corners: [.topLeft,.topRight], radius: 20)
    }

    private func setGradient() {
        (layer as! CAGradientLayer).colors = [topColor.cgColor, bottomColor.cgColor]
        (layer as! CAGradientLayer).startPoint = CGPoint(x: 0.5, y: 0)
        (layer as! CAGradientLayer).endPoint = CGPoint(x: 0.5, y: 1)
    }
}

@IBDesignable class VariableSeparateCornerView: UIView {

    private var corners: UIRectCorner = [.allCorners]
    private var radius: CGFloat = 0

    override func layoutSubviews() {
        super.layoutSubviews()
        self.refreshCorners()
    }

    func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        self.corners = corners
        self.radius = radius
        self.refreshCorners()
    }

    private func refreshCorners() {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }
} 

使用: 只需拖动UIView并将自定义类设置为VerticalGradientView enter image description here