Перевод статьи от автора Baptiste Montagliani
Спасибо CoreAnimation и CALayer, за то что мы можем с легкостью применить нестандартные тени к любым UIView, через свойство layer.
В этой статье мы увидим как создать 5 известных типов теней:
- Отбрасываемая тень
- Основная контактная тень
- Контактная тень с глубиной
- Плоская контактная тень
- Изогнутая тень
Но сначала, посмотрим на 5 свойств слоя которые мы будем использовать для создания нестандартных теней.
shadowColor
Настройка цвета тени. Предустановленный цвет это UIColor.black.cgColor, который делает темной тень, но вы можете также установить светлый цвет для создания светящегося эффекта, или любой другой цвет.
shadowOpacity
Настройка прозрачности тени, между 0 и 1. Значение 0 означает что тень не будет видна.
shadowRadius
Настройка уровня размытия тени. Значение 0 означает что тень не будет размыта вовсе, она будет полностью плоской.
shadowOffset
Настройка позиции тени из вью. Это свойство особенно полезно когда вы хотите добавить глубины в ваш интерфейс. Значение CGSize.zero означает что тень будет совершенно выровнена с ее родительным вью.
shadowPath
Настройка формы тени. Предустановленное значение этого свойства nil которое означает что UIKit будет определять форму тени от родительной вью.
Не устанавливая shadowPath делает генерацию теней намного медленней, и так это хорошая практика устанавливать путь для этого свойства, даже для основных теней с квадратной формой.
Это свойства особенно интересно если вы хотите сделать тень нестандартной формы.
1. Отбрасываемые тени
Отбрасываемые тени это классические тени которые вы можете видеть в большинстве времени в приложениях и вебсайтах. Оно использует только свойства прозрачности, радиуса и смещения, для создания впечатляющей глубины интерфейса путем имитации высоты компонентов и их позиции от источника света.
Вы можете указать путь для этих базовых теней с помощью создания UIBezierPath из ваших границ вью.
imageView.layer.shadowRadius = 10 imageView.layer.shadowOffset = .zero imageView.layer.shadowOpacity = 0.5 imageView.layer.shadowColor = UIColor.black.cgColor imageView.layer.shadowPath = UIBezierPath(rect: imageView.bounds).cgPath
Вам так же понадобится установить слою свойство maskToBound в True если тень не появляется. Сделая это, вы разрешаете содержимому слоя рисовать вне границ слоя.
imageView.layer.masksToBounds = false
Вы можете установить не нулевое смещение позиции тени для настройки позиции тени. Помните, что для обеспечения гладкости интерфейса обычно лучше установить аналогичное смещение между вью, поскольку предполагается, что тень устанавливается в зависимости от ориентации света.
imageView.layer.shadowOffset = CGSize(width: 0, height: 10)
Свойство shadowRadius позволит вам настроить применимое размытие для тени. Здесь пример с радиусом 1, 10 и 50
Если вы хотите больше узнать больше как определить логику возвышения к теням вашего приложения, есть хорошая документация на material.io. Это было разработано для тем приложения с материальной разработкой, но это все еще актуальная информация и практика которая может быть использована в любом приложении или вебсайте, включая приложения iOS.
2. Контактная тень
Контактная тень описываем тип тени которую вы видите когда объект контактирует в поверхностью или возле нее.
Для добавления настраиваемой контактной тени на вью, нам понадобится создать путь формы которая нам необходима: плоский овал.
let size: CGFloat = 20 let distance: CGFloat = 0 let rect = CGRect( x: -size, y: imageView.frame.height - (size * 0.4) + distance, width: imageView.frame.width + size * 2, height: size ) imageView.layer.shadowColor = UIColor.black.cgColor imageView.layer.shadowRadius = 7 imageView.layer.shadowOpacity = 0.5 imageView.layer.shadowPath = UIBezierPath(ovalIn: rect).cgPath
Отрицательный размер сделает тень более маленькой чем изображение. И дистанция больше 0 сделает вью на расстоянии о других вью.
3. Контактная тень с глубиной
В то время как предыдущая контактная тень создавала впечатление, что свет находится над вью, мы можем добавить больше глубины с помощью этого эффекта, чтобы вью выглядел как трехмерный объект с источником света впереди или позади вида.
Для создания этого эффекта, вам нужно в ручную создать shadowPath представляющий настраиваемую форму. Смотрите код ниже:
let scale = CGSize(width: 1.25, height: 0.5) let offsetX: CGFloat = 0 let shadowPath = UIBezierPath() shadowPath.move(to: CGPoint( x: 0, y: imageView.frame.height ) ) shadowPath.addLine(to: CGPoint( x: imageView.frame.width, y: imageView.frame.height ) ) shadowPath.addLine(to: CGPoint( x: imageView.frame.width * scale.width + offsetX, y: imageView.frame.height * (1 + scale.height) ) ) shadowPath.addLine(to: CGPoint( x: imageView.frame.width * (1 - scale.width) + offsetX, y: imageView.frame.height * (1 + scale.height) ) )
Вы можете изменять значение размера для создания более маленьких или больших теней.
Если вы установите отрицательное значение для scale.height, тень появится за вью, это изменит глубина направления.
Со свойством offset вы можете горизонтально двигать источник света, таким образом скручивая тень, чтобы она выглядела соответственно источнику света.
4. Плоская контактная тень
Этот эффект тени особенно важен в современном дизайне. Это становится все более и более популярным, поскольку плоский дизайн становится нормой.
Для этого эффекта мы будем использовать кодовую базу предыдущего эффекта «Контактная тень с глубиной». На самом деле нам нужно только добавить новое свойство offsetY, чтобы заставить работать наш плоский эффект, и, конечно же, уменьшить радиус тени.
let scale = CGSize(width: 1.5, height: 1.5) let offset = CGPoint(x: imageView.frame.width, y: -imageView.frame.height) let shadowPath = UIBezierPath() shadowPath.move(to: CGPoint( x: 0, y: imageView.frame.height + (copysign(1, scale.height) * copysign(1, offset.x) == 1 ? 0 : offset.y) ) ) shadowPath.addLine(to: CGPoint( x: imageView.frame.width, y: imageView.frame.height + (copysign(1, scale.height) * copysign(1, offset.x) == -1 ? 0 : offset.y) ) ) shadowPath.addLine(to: CGPoint( x: imageView.frame.width * scale.width + offset.x, y: imageView.frame.height * (1 + scale.height) + offset.y ) ) shadowPath.addLine(to: CGPoint( x: imageView.frame.width * (1 - scale.width) + offset.x, y: imageView.frame.height * (1 + scale.height) + offset.y ) ) imageView.layer.shadowPath = shadowPath.cgPath imageView.layer.shadowRadius = 0 imageView.layer.shadowOffset = .zero imageView.layer.shadowOpacity = 0.2 imageView.layer.shadowColor = UIColor.black.cgColor
5. Изогнутые тени
Для данного типа теней мы опять используем свойство shadowPath. Вы можете немного поиграть со значениями ниже, чтобы создать плавную тень, которая будет соответствовать потребностям вашего дизайна.
Чтобы тень выглядела изогнутой, мы используем функцию addCurve из UIBezierPath. Путем установки свойства curve вы можете настроить интенсивность изгибания. Вы можете напрямую использовать свойство слоя shadowOffest, чтобы настроить его в соответствии с вашим вью.
let curve: CGFloat = 100 let shadowPath = UIBezierPath() shadowPath.move(to: CGPoint.zero) shadowPath.addLine(to: CGPoint( x: imageView.frame.width, y: 0 )) shadowPath.addLine(to: CGPoint( x: imageView.frame.width, y: imageView.frame.height + curve )) shadowPath.addCurve( to: CGPoint( x: 0, y: imageView.frame.height + curve ), controlPoint1: CGPoint( x: imageView.frame.width, y: imageView.frame.height ), controlPoint2: CGPoint( x: 0, y: imageView.frame.height ) ) imageView.layer.shadowPath = shadowPath.cgPath imageView.layer.shadowRadius = 10 imageView.layer.shadowOffset = CGSize(width: 0, height: 10) imageView.layer.shadowOpacity = 0.5 imageView.layer.shadowColor = UIColor.black.cgColor
Резюме
Теперь вы знаете как добавить в ваше приложение глубины с помощью добавления красивых и полностью настраиваемых теней с CALayer, и вы выучили как создавать базовые и продвинутые тени со свойством shadowPath. Здесь короткое резюме из 5 типов теней которых мы видели в этой статье.
- Отбрасываемая тень
- Основная контактная тень
- Контактная тень с глубиной
- Плоская контактная тень
- Изогнутая тень