Как создать продвинутый градиент в Swift с CAGragientLayer — IOS Swift Guide

Перевод статьи от автора Baptiste Montagliani

5 шагов к созданию красивого градиента для вашего приложения

C CoreAnimation и CAGradientLayer, IOS позволяет легче сделать кастомные градиенты любого стиля. Возможно создать линейный, конический, радиальный градиент и настроить его как вы хотите с вашими цветами и ориентацией. Это также поддерживает анимацию изменения градиента для плавных и красочных приложений.

CAGradietLayer это подкласс CALayer и был специально разработан для создания простых и быстрых эффектов. Буквально с пятью строками кода, вы можете сгенерировать новый градиент и добавить на ваши view слои.

Вот эти 5 шагов для создания красивых градиентов для ваших приложений.

1. Линейный градиент

Создание слоя с градиентом цвета это очень просто. Для большей части базовых градиентов, требуется только цвета которые вы хотите использовать, и потом по желанию вы можете настроить локацию. Когда вы создали ваш градиент, просто добавьте на ваш view слой и назовите функцию addSublayer.

lazy var gradient: CAGradientLayer = {
    let gradient = CAGradientLayer()
    gradient.type = .axial
    gradient.colors = [
        UIColor.red.cgColor,
        UIColor.purple.cgColor,
        UIColor.cyan.cgColor
    ]
    gradient.locations = [0, 0.25, 1]
    return gradient
}()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    gradient.frame = view.bounds
    view.layer.addSublayer(gradient)
}

Атрибуты type опциональные для стиля данного градиента как линейный или осевой и являются дефолтными. Так же локация цветов используется когда вам необходимо настроить размер пространства каждого цвета. Иначе это опционально. Если вы не установите эти свойства, каждый цвет градиента будет показываться пропорционально на слое.

2. Настройте направление градиента

Как только мы создали новый градиент, настройте его цвета, но обычно направление вертикальное. Спасибо CAGradientLayer за то что мы тоже можем настроить направление. Более точно, мы может настроить начальную и конечную точку градиента. Для более легкого понимания, градиент будет заполнятся по линии между двумя точками, и так вы можете выбрать направление градиента, но также где будет начинаться и где будет заканчиваться.

Две точки выражены в процентах слоя, между (0,0) и (1,1). На пример, в стандартном вертикальном градиенте как выше начальная точка это (0,0), и конечная (0,1).

Давайте посмотрим два примера настройки направления: первый это идеальная диагональ, и вторая это горизонтальное направление.

Для диагонального направления, установим точки как в коде ниже:

gradient.startPoint = CGPoint(x: 0, y: 0)
gradient.endPoint = CGPoint(x: 1, y: 1)

для горизонтального направления, оставьте тот же y для обеих точек начала и конца, и вы получите горизонтальный градиент.

gradient.startPoint = CGPoint(x: 0, y: 1)
gradient.endPoint = CGPoint(x: 1, y: 1)

3. радиальный и конический градиенты

Создание радиального и конического градиентов очень похоже на линейный градиент.

Как видели в предыдущей части, слой градиента имеет свойство CAGradientLayerType с именем Type. Это свойство описано в документации Apple, которое позволяет вам выбрать какой стиль градиента вы хотите использовать на данном слое.

Здесь возможно три типа:

  • static let axial: CAGradientLayer
  • static let conic: CAGradientLayer
  • static let radial: CAGradientLayer

Для смены стиля градиента на конический или радиальный, установите или conic или radial для свойства типа слоя.

Если начальная и конечная точка для линейного градиента опциональная, здесь вам надо установить конкретные значения для радиального и конического градиентов.

В радиальном градиенте, начальная точка представляет собой среднюю точку круга, и конечная точка это самая дальная точки от круга. Если ваш слой не квадрат, вам надо сделать некоторые математические вычисления для поиска конечной точки для того чтобы градиет был круглой формы.

Для конического градиента, начальная точка все еще представляем среднюю точку  конуса, но конечная точка это где ваш первый и последний цвет будут соединятся. Таким образом это позволит вам вращать конический градиент.

lazy var gradient: CAGradientLayer = {
    let gradient = CAGradientLayer()
    gradient.type = .radial
    gradient.colors = [
        UIColor.purple.cgColor,
        UIColor.blue.cgColor,
        UIColor.green.cgColor,
        UIColor.yellow.cgColor,
        UIColor.orange.cgColor,
        UIColor.red.cgColor
    ]
    gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
    let endY = 0.5 + view.frame.size.width / view.frame.size.height / 2
    gradient.endPoint = CGPoint(x: 1, y: endY)
    return gradient
}()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    gradient.frame = view.bounds
    view.layer.addSublayer(gradient)
}

4. Анимировать изменения градиента

Другая крутая вещь CAGradientLayer это то, что многие его свойства могут быть анимированы! Вы можете легко анимировать изменение цвета, начальную и конечную точку например.

Давайте посмотрим как создать кастомную анимацию по смене цвета, путем создания расширения CAGradientLayer.

extension CAGradientLayer {
    
    func setColors(_ newColors: [CGColor],
                   animated: Bool = true,
                   withDuration duration: TimeInterval = 0,
                   timingFunctionName name: CAMediaTimingFunctionName? = nil) {
        
        if !animated {
            self.colors = newColors
            return
        }
        
        let colorAnimation = CABasicAnimation(keyPath: "colors")
        colorAnimation.fromValue = colors
        colorAnimation.toValue = newColors
        colorAnimation.duration = duration
        colorAnimation.isRemovedOnCompletion = false
        colorAnimation.fillMode = CAMediaTimingFillMode.forwards
        colorAnimation.timingFunction = CAMediaTimingFunction(name: name ?? .linear)
        
        add(colorAnimation, forKey: "colorsChangeAnimation")
    }
    
}
let newColors = [
    UIColor.purple.cgColor,
    UIColor.red.cgColor,
    UIColor.orange.cgColor
]

gradient.setColors(newColors,
                   animated: true,
                   withDuration: 2,
                   timingFunctionName: .linear)

Это работаем так же для анимации начальной и конечной точки, вы должны только заменить keyPath в CABasicAnimation реализации, тем что вы хотите анимировать, «startPoint» например.

5. CAGradientLayer в UIView

Каждый объект UIView имеет слой класса CALayer. В некоторых случаях, если вы хотите создать кастомный градиент view например, вы можете заменить стандартный слой этим слоем градиента. Вы можете заменить класс слоя вашим кастомным, путем перезаписи свойства layerClass вашего класса UIView.

Тем самым вам не нужно инициализировать новый объект CAGradientLayer, так как стандартный слой view будет возвращать нужный тип. Вы можете напрямую установить цвета и точки слоя объекта view с использованием свойств слоя: layer as? CAGradientLayer.

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

Резюме

В этой статье вы видели как воздавать полностью настраиваемые слои градиента, как выбирать и конфигурировать стили градиента и как анимировать ваши изменения в градиенте.

  1. Создание линейного градиента
  2. Настройка направления градиента
  3. Радиальный и конический градиенты
  4. Анимирование изменений градиента
  5. CAGradientLayer в UIView