Как сделать преобразования на CALayer?

Прежде чем написать этот вопрос, я

Тем не менее, мне все еще трудно понять, как выполнять базовые преобразования на слое. Найти объяснения и простые примеры для перевода, поворота и масштабирования было сложно.

Сегодня я наконец решил сесть, сделать тестовый проект и разобраться с ними. Мой ответ ниже.

Заметки:

  • Я делаю только Swift, но если кто-то еще хочет добавить код Objective-C, будь моим гостем.
  • На данный момент меня интересует только понимание 2D-преобразований.

1 ответ

Решение

основы

Есть несколько различных преобразований, которые вы можете сделать на слое, но основные из них:

  • перевести (переместить)
  • масштаб
  • вращаться

Делать преобразования на CALayerВы устанавливаете слой transform собственность на CATransform3D тип. Например, чтобы перевести слой, вы должны сделать что-то вроде этого:

myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)

Слово Make используется в имени для создания исходного преобразования: CATransform3DMake Translation. Последующие преобразования, которые применяются, опускают Make, Посмотрите, например, это вращение с последующим переводом:

let rotation = CATransform3DMakeRotation(CGFloat.pi * 30.0 / 180.0, 20, 20, 0)
myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)

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

Настроить

Для следующих примеров я настроил приложение с одним представлением и добавил 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 это изменение в координатах х, ty это изменение у, и tz это изменение в г.

пример

В 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)

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

Смотрите также

Другие вопросы по тегам