Ответ 1
основы
Есть несколько различных преобразований, которые вы можете сделать на слое, но основные из них:
- перевести (переместить)
- масштаб
- вращаться
Для преобразования на более CALayer
, вы установите слой transform
недвижимости CATransform3D
типа. Например, чтобы перевести слой, вы должны сделать что-то вроде этого:
myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)
Слово Make
используется в имени для создания исходного преобразования: CATransform3D Make Translation. Последующие преобразования, которые применяются, опускают Make
. Посмотрите, например, это вращение с последующим переводом:
let rotation = CATransform3DMakeRotation(CGFloat.pi * 30.0 / 180.0, 20, 20, 0)
myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)
Теперь, когда у нас есть основы того, как сделать преобразование, давайте рассмотрим несколько примеров того, как это сделать. Однако сначала я покажу, как настроить проект на случай, если вы тоже захотите поиграть с ним.
Настроить
Для следующих примеров я настроил приложение Single View и добавил в UIView
с голубым фоном. Я подключил представление к контроллеру представления с помощью следующего кода:
import UIKit
class ViewController: UIViewController {
var myLayer = CATextLayer()
@IBOutlet weak var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// setup the sublayer
addSubLayer()
// do the transform
transformExample()
}
func addSubLayer() {
myLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
myLayer.backgroundColor = UIColor.blue.cgColor
myLayer.string = "Hello"
myView.layer.addSublayer(myLayer)
}
//******** Replace this function with the examples below ********
func transformExample() {
// add transform code here ...
}
}
Существует много разных типов CALayer
, но я решил использовать CATextLayer
чтобы преобразования были более четкими визуально.
Переведите
Трансляционное преобразование перемещает слой. Основной синтаксис
CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat)
где tx
- изменение координат x, ty
- изменение y, а tz
- изменение z.
пример
В iOS источник системы координат находится в верхнем левом углу, поэтому, если мы хотим переместить слой на 90 пунктов вправо и на 50 пунктов вниз, мы сделаем следующее:
myLayer.transform = CATransform3DMakeTranslation(90, 50, 0)
Заметки
- Помните, что вы можете вставить это в метод
transformExample()
в приведенном выше коде проекта. - Так как мы собираемся здесь иметь дело с двумя измерениями,
tz
установлен в0
. - Красная линия на изображении выше идет от центра исходного местоположения к центру нового местоположения. Это потому, что преобразования выполняются относительно точки привязки, а точка привязки по умолчанию находится в центре слоя.
Масштаб
Преобразование масштаба растягивает или сжимает слой. Основной синтаксис
CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat)
где sx
, sy
и sz
- числа, на которые можно масштабировать (умножать) координаты x, y и z соответственно.
пример
Если бы мы хотели вдвое уменьшить ширину и утроить высоту, мы бы сделали следующее
myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0)
Заметки
- Поскольку мы работаем только в двух измерениях, мы просто умножаем координаты z на 1,0, чтобы оставить их без изменений.
- Красная точка на изображении выше представляет точку привязки. Обратите внимание на то, как масштабирование делается по отношению к точке привязки. То есть все либо растягивается в направлении, либо от точки привязки.
Поворот
Преобразование поворота поворачивает слой вокруг опорной точки (центр слоя по умолчанию). Основной синтаксис
CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat)
где angle
- это угол в радианах, что слой должен вращаться, а x
, y
и z
- оси, вокруг которых вращается. Установка оси в 0 отменяет вращение вокруг этой конкретной оси.
пример
Если бы мы хотели повернуть слой по часовой стрелке на 30 градусов, мы бы сделали следующее:
let degrees = 30.0
let radians = CGFloat(degrees * Double.pi / 180)
myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0)
Заметки
- Поскольку мы работаем в двух измерениях, мы хотим, чтобы плоскость xy вращалась вокруг оси z. Таким образом, мы устанавливаем
x
иy
в0.0
и устанавливаемz
в1.0
. - Это повернуло слой по часовой стрелке. Мы могли бы повернуть против часовой стрелки, установив
z
на-1.0
. - Красная точка показывает, где находится точка привязки. Вращение осуществляется вокруг точки привязки.
Несколько преобразований
Чтобы объединить несколько преобразований, мы могли бы использовать конкатенацию, как это
CATransform3DConcat(a: CATransform3D, b: CATransform3D)
Однако мы будем просто делать одно за другим. Первое преобразование будет использовать Make
в своем имени. Следующие преобразования не будут использовать Make
, но они будут принимать предыдущее преобразование в качестве параметра.
пример
На этот раз мы объединяем все три предыдущих преобразования.
let degrees = 30.0
let radians = CGFloat(degrees * Double.pi / 180)
// translate
var transform = CATransform3DMakeTranslation(90, 50, 0)
// rotate
transform = CATransform3DRotate(transform, radians, 0.0, 0.0, 1.0)
// scale
transform = CATransform3DScale(transform, 0.5, 3.0, 1.0)
// apply the transforms
myLayer.transform = transform
Заметки
- Порядок, что преобразования сделаны в вопросах.
- Все было сделано относительно точки привязки (красная точка).
Примечание о точке привязки и установках
Мы сделали все наши преобразования выше, не меняя опорную точку. Однако иногда необходимо изменить его, например, если вы хотите вращаться вокруг какой-либо другой точки, кроме центра. Однако это может быть немного сложнее.
Якорная точка и положение находятся в одном и том же месте. Точка привязки выражается в единицах системы координат слоя (по умолчанию 0.5, 0.5
), а позиция выражается в системе координат суперслоя. Они могут быть установлены так
myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
myLayer.position = CGPoint(x: 50, y: 50)
Если вы устанавливаете только опорную точку, не меняя положение, то рамка изменится так, что положение будет в правильном месте. Точнее, кадр пересчитывается на основе новой точки привязки и старой позиции. Это обычно дает неожиданные результаты. Следующие две статьи отлично обсуждают это.