Как определяются позиции sublayers в Core Animation?

Ответ

Позиция sublayer определяется через геометрические свойства CALayer:

Основные свойства:

  • frame — прямоугольник в координатах superlayer (вычисляемое свойство)
  • bounds — прямоугольник в собственных координатах
  • position — точка привязки в координатах superlayer
  • anchorPoint — точка нормированных координат (0.0-1.0) внутри bounds

Пример установки позиции:

let sublayer = CALayer()

// Способ 1: Через frame
sublayer.frame = CGRect(x: 20, y: 20, width: 100, height: 100)

// Способ 2: Через position и bounds (рекомендуется для анимаций)
sublayer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
sublayer.position = CGPoint(x: 70, y: 70) // Центр при anchorPoint (0.5, 0.5)
sublayer.anchorPoint = CGPoint(x: 0.5, y: 0.5) // По умолчанию

Важные взаимосвязи:

// frame вычисляется как:
frame.origin = position - (bounds.size * anchorPoint)
frame.size = bounds.size

// При изменении frame обновляются position и bounds
// При изменении position или bounds обновляется frame

Рекомендации:

  • Для анимаций используйте position и transform (аппаратное ускорение)
  • Избегайте анимации frame — это приводит к пересчёту position и bounds
  • anchorPoint (0, 0) — верхний левый угол, (1, 1) — нижний правый

Ответ 18+ 🔞

Да ты посмотри, на что люди время тратят! Весь этот пиздец с CALayer... Ну ладно, слушай сюда, раз уж начал.

Вот есть у тебя эта sublayer, да? И её, сука, куда-то надо приткнуть. Так вот, позиция её — это не просто "ах, поставь её там, где хочешь". Это, блядь, целая наука, построенная на четырёх китах, которые друг другу мозги ебут.

Смотри, основные игроки на поле:

  • frame — это как бы итоговый прямоугольник, но он вычисляемый, чувак. То есть он сам из других свойств складывается, как пазл. Не ты его задаёшь, а он тебе выдаётся, исходя из всей этой хуйни ниже.
  • bounds — это её личные владения, её внутренняя система координат. Обычно ноль-ноль в левом верхнем углу, но можешь и сдвинуть, если хочешь с ума сойти.
  • position — это, внимание, точка привязки в координатах слоя-родителя (того superlayer). Ключевое слово!
  • anchorPoint — а это, блядь, нормированная точка внутри самого слоя, за которую его таскают. По умолчанию (0.5, 0.5) — центр. Сделаешь (0,0) — будешь таскать за верхний левый угол. Гениально и просто, как хуй в проруби.

Вот как это на практике выглядит:

let sublayer = CALayer() // Родился, сука, ни рыба ни мясо.

// Способ 1: По-деревенски, через frame. Быстро и грубо.
sublayer.frame = CGRect(x: 20, y: 20, width: 100, height: 100) // Готово. Сиди там.

// Способ 2: По-взрослому, как джедай. Для анимаций — самое то.
sublayer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) // Задал свои размеры.
sublayer.position = CGPoint(x: 70, y: 70) // Сказал, где в координатах родителя будет anchorPoint.
sublayer.anchorPoint = CGPoint(x: 0.5, y: 0.5) // А это и есть та самая точка (центр). По умолчанию и так стоит.

А теперь, блядь, магия их взаимоотношений (держись за стул):

// frame — это производная, ёпта! Он вычисляется так:
frame.origin = position - (bounds.size * anchorPoint) // Вот эта хуйня!
frame.size = bounds.size

// И обратная ебля:
// Поменял frame — система за тебя пересчитает position и bounds.
// Поменял position или bounds — система обновит frame.

Итоговые рекомендации, чтобы не выстрелить себе в ногу:

  • Хочешь анимировать движение? Юзай position и transform. Это железо ускоряет, летает, как угорелое.
  • Избегай как чумы анимации самого frame. Это пиздец, потому что система будет на каждом кадре пересчитывать и position, и bounds — производительность накроется медным тазом.
  • Запомни про anchorPoint: (0, 0) — таскаешь за верхний левый угол, (1, 1) — за нижний правый. Поиграйся, почувствуй силу.

Вот и вся философия. Не так страшен чёрт, как его CALayer.