在我的场景中,我有两个视图:第一个视图包含CALayer实例(条),另一个视图包含CAGradientLayer并放置在第一个实例之上。下图描述了当前状态。
ios - 在CALayers上屏蔽CAGradientLayer-LMLPHP
但是我需要这个梯度只应用于第一个视图的条(CALayer)。
ios - 在CALayers上屏蔽CAGradientLayer-LMLPHP
我没有找到任何与我的问题相关的信息。感谢任何帮助。

最佳答案

你必须对渐变应用一个遮罩。有多种方法可以解决这个问题。
可以创建一个CAShapeLayer,将形状层的path设置为条形图的形状,并将渐变层的mask设置为该形状层。
或者可以去掉条形图层,改为使用两个渐变层,一个用于橙色条,另一个用于灰色条。将两个渐变层并排放置在子视图中,并将superview的层掩码设置为形状层。这是怎么做的。
您需要两个渐变层和一个形状层:

@IBDesignable
class BarGraphView : UIView {

    private let orangeGradientLayer = CAGradientLayer()
    private let grayGradientLayer = CAGradientLayer()
    private let maskLayer = CAShapeLayer()

您还需要栏宽:
    private let barWidth = CGFloat(9)

在初始化时,设置渐变并添加所有子层:
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

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

    private func commonInit() {
        backgroundColor = .black

        initGradientLayer(orangeGradientLayer, with: .orange)
        initGradientLayer(grayGradientLayer, with: .gray)

        maskLayer.strokeColor = nil
        maskLayer.fillColor = UIColor.white.cgColor
        layer.mask = maskLayer
    }

    private func initGradientLayer(_ gradientLayer: CAGradientLayer, with color: UIColor) {
        gradientLayer.colors = [ color, color, color.withAlphaComponent(0.6), color ].map({ $0.cgColor })
        gradientLayer.locations = [ 0.0, 0.5, 0.5, 1.0 ]
        layer.addSublayer(gradientLayer)
    }

在布局时,设置渐变层的帧并设置遮罩层的路径。这需要一点工作,因为你不想酒吧是半橙色和半灰色。
    override func layoutSubviews() {
        super.layoutSubviews()

        let barCount = ceil(bounds.size.width / barWidth)
        let orangeBarCount = floor(barCount / 2)
        let grayBarCount = barCount - orangeBarCount

        var grayFrame = bounds
        grayFrame.size.width = grayBarCount * barWidth
        grayFrame.origin.x = frame.maxX - grayFrame.size.width
        grayGradientLayer.frame = grayFrame

        var orangeFrame = bounds
        orangeFrame.size.width -= grayFrame.size.width
        orangeGradientLayer.frame = orangeFrame

        maskLayer.frame = bounds
        maskLayer.path = barPath()
    }

    private func barPath() -> CGPath {
        var columnBounds = self.bounds
        columnBounds.origin.x = columnBounds.maxX
        columnBounds.size.width = barWidth
        let path = CGMutablePath()
        for datum in barData.reversed() {
            columnBounds.origin.x -= barWidth
            let barHeight = CGFloat(datum) * columnBounds.size.height
            let barRect = columnBounds.insetBy(dx: 1, dy: (columnBounds.size.height - barHeight) / 2)
            path.addRoundedRect(in: barRect, cornerWidth: 2, cornerHeight: 2)
        }
        return path
    }

    let barData: [Double] = {
        let count = 100
        return (0 ..< count).map({ 0.5 + (1 + sin(8.0 * .pi * Double($0) / Double(count))) / 4 })
    }()

}

结果:
ios - 在CALayers上屏蔽CAGradientLayer-LMLPHP
BarGraphView在没有条的地方是透明的。如果要将其置于深色背景上,请在其后面放置深色视图,或使其成为深色视图的子视图:
ios - 在CALayers上屏蔽CAGradientLayer-LMLPHP

关于ios - 在CALayers上屏蔽CAGradientLayer,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43003983/

10-10 22:39