有角度的梯度层

Kir*_*ira 6 gradient uiview cagradientlayer swift swift2

我有自定义UIView类在Swift 2中呈现渐变.我正在努力制作一个有角度的渐变,以便从左上角到右下角绘制.有人可以帮我一点吗?

import UIKit

class GradientView: UIView {

    let gradientLayer = CAGradientLayer()

    override func awakeFromNib() {
        // 1
        self.backgroundColor = ColorPalette.White

        // 2
        gradientLayer.frame = self.bounds

        // 3
        let color1 = ColorPalette.GrdTop.CGColor as CGColorRef
        let color2 = ColorPalette.GrdBottom.CGColor as CGColorRef
        gradientLayer.colors = [color1, color2]

        // 4
        gradientLayer.locations = [0.0, 1.0]

        // 5
        self.layer.addSublayer(gradientLayer)
    }

}
Run Code Online (Sandbox Code Playgroud)

我怀疑这应该是别的,但无论我输入什么都没有变化.

gradientLayer.locations = [0.0, 1.0]
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 24

您不想使用它locations来指定渐变的方向.而是使用startPointendPoint为此.

locations当想要指定应在何处,在startPoint和之间endPoint进行渐变时,使用该数组.例如,如果您希望颜色仅发生在起点和终点范围的10%的中间位置,您可以使用:

locations = [0.45, 0.55]
Run Code Online (Sandbox Code Playgroud)

所述locations阵列并不规定的方向.的startPointendPoint做的.所以,从左上角的对角线梯度到右下,你会设置startPointCGPoint(x: 0, y: 0)endPointCGPoint(x: 1, y: 1).

例如:

@IBDesignable
class GradientView: UIView {

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

    private var gradientLayer: CAGradientLayer { return layer as! CAGradientLayer }

    @IBInspectable var color1: UIColor = .white { didSet { updateColors() } }
    @IBInspectable var color2: UIColor = .blue  { didSet { updateColors() } }

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configureGradient()
    }

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

    private func configureGradient() {
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        updateColors()
    }

    private func updateColors() {
        gradientLayer.colors = [color1.cgColor, color2.cgColor]
    }

}
Run Code Online (Sandbox Code Playgroud)

例如

在此输入图像描述

注意,与直接问题无关:

  • 如果你打算梯度添加为子,你要更新这个子层的framelayoutSubviews,这样的观点的bounds变化,所以做了framegradientLayer.但是,更好的是,覆盖layerClass视图,它不仅会CAGradientLayer为你实例化,而且你还可以随着视图的大小变化享受渐变的动态调整,特别是更优雅地处理动画变化.

  • 同样,我设置color1并且color2它们将触发渐变的更新,以便颜色的任何变化将立即反映在视图中.

  • 我做了这个@IBDesignable,所以如果我把它放在自己的框架中,然后GradientView在IB中添加,我将看到在IB中呈现的效果.

对于Swift 2实现,请参阅此答案的先前版本.


Noa*_*der 8

任意角度的渐变起点和终点

Swift 4.2,Xcode 10.0

给定任意角度,我的代码将设置渐变层的相应起点和终点。

如果输入的角度大于360°,则除以360时将使用余数。

  • 输入415°将产生与输入55°相同的结果

如果输入的角度小于,则将逆时针旋转

  • -15°的输入将产生与345°的输入相同的结果

码:

public extension CAGradientLayer {

    /// Sets the start and end points on a gradient layer for a given angle.
    ///
    /// - Important:
    /// *0°* is a horizontal gradient from left to right.
    ///
    /// With a positive input, the rotational direction is clockwise.
    ///
    ///    * An input of *400°* will have the same output as an input of *40°*
    ///
    /// With a negative input, the rotational direction is clockwise.
    ///
    ///    * An input of *-15°* will have the same output as *345°*
    ///
    /// - Parameters:
    ///     - angle: The angle of the gradient.
    ///                  
    public func calculatePoints(for angle: CGFloat) {


        var ang = (-angle).truncatingRemainder(dividingBy: 360)

        if ang < 0 { ang = 360 + ang }

        let n: CGFloat = 0.5

        switch ang {

        case 0...45, 315...360:
            let a = CGPoint(x: 0, y: n * tanx(ang) + n)
            let b = CGPoint(x: 1, y: n * tanx(-ang) + n)
            startPoint = a
            endPoint = b

        case 45...135:
            let a = CGPoint(x: n * tanx(ang - 90) + n, y: 1)
            let b = CGPoint(x: n * tanx(-ang - 90) + n, y: 0)
            startPoint = a
            endPoint = b

        case 135...225:
            let a = CGPoint(x: 1, y: n * tanx(-ang) + n)
            let b = CGPoint(x: 0, y: n * tanx(ang) + n)
           startPoint = a
            endPoint = b

        case 225...315:
            let a = CGPoint(x: n * tanx(-ang - 90) + n, y: 0)
            let b = CGPoint(x: n * tanx(ang - 90) + n, y: 1)
            startPoint = a
            endPoint = b

        default:
            let a = CGPoint(x: 0, y: n)
            let b = CGPoint(x: 1, y: n)
            startPoint = a
            endPoint = b

        }
    }

    /// Private function to aid with the math when calculating the gradient angle
    private func tanx(_ : CGFloat) -> CGFloat {
        return tan( * CGFloat.pi / 180)
    }


    // Overloads

    /// Sets the start and end points on a gradient layer for a given angle.
    public func calculatePoints(for angle: Int) {
        calculatePoints(for: CGFloat(angle))
    }

    /// Sets the start and end points on a gradient layer for a given angle.
    public func calculatePoints(for angle: Float) {
        calculatePoints(for: CGFloat(angle))
    }

    /// Sets the start and end points on a gradient layer for a given angle.
    public func calculatePoints(for angle: Double) {
        calculatePoints(for: CGFloat(angle))
    }

}
Run Code Online (Sandbox Code Playgroud)

用法:

let gradientLayer = CAGradientLayer()

// Setup gradient layer...

// Gradient Direction: ?
gradient.calculatePoints(for: 0)

// Gradient Direction: ??
gradient.calculatePoints(for: -45)

// Gradient Direction: ?
gradient.calculatePoints(for: 180)

// Gradient Direction: ?
gradient.calculatePoints(for: 450)
Run Code Online (Sandbox Code Playgroud)

数学解释

因此,我最近实际上花了很多时间自己回答这个问题。以下是一些示例角度,仅用于帮助理解和可视化顺时针旋转方向。

角度示例

如果你有兴趣我怎么想通了,我做了一个表来形象化基本上就是我从做 - 360°

表