CGAffineTransform
CGAffineTransform — это структура данных в операционной системе Apple, используемая для представления аффинных преобразований двумерной графики. Она применяется в фреймворках Core Graphics, UIKit и SwiftUI для выполнения операций перемещения (трансляции), масштабирования, поворота и сдвига (skewing) графических объектов, таких как изображения, слои и текстовые элементы.
Математическая основа
CGAffineTransform базируется на линейной алгебре и представляет собой матрицу размером 3×3, в которой последняя строка всегда фиксирована как [0, 0, 1]. Это позволяет выполнять аффинные преобразования, сохраняющие параллельность прямых и отношение расстояний на прямой. Матрица имеет следующий вид:
`` [ a b 0 ] [ c d 0 ] [ tx ty 1 ] ``
Где:
aиd— коэффициенты масштабирования по осям X и Y соответственно;bиc— коэффициенты сдвига (skew) по осям X и Y;txиty— коэффициенты перемещения (трансляции) по осям X и Y.
Преобразование точки с координатами (x, y) в новую точку (x', y') выполняется по формулам:
x' = a x + c y + txy' = b x + d y + ty
Структура и свойства
В языках программирования Swift и Objective-C структура CGAffineTransform определена как набор из шести значений типа CGFloat:
a— масштаб по оси X;b— сдвиг по оси Y;c— сдвиг по оси X;d— масштаб по оси Y;tx— смещение по оси X;ty— смещение по оси Y.
Структура также включает предопределённую константу CGAffineTransformIdentity, представляющую единичную матрицу, которая не вносит никаких изменений в объект.
Основные операции
CGAffineTransform поддерживает несколько базовых аффинных преобразований, каждое из которых создаётся с помощью специализированных функций.
Перемещение (трансляция)
Функция CGAffineTransformMakeTranslation(tx, ty) создаёт преобразование, сдвигающее объект на заданное количество точек по осям X и Y. Матрица при этом принимает вид:
`` [ 1 0 0 ] [ 0 1 0 ] [ tx ty 1 ] ``
Масштабирование
Функция CGAffineTransformMakeScale(sx, sy) изменяет размер объекта в sx раз по горизонтали и в sy раз по вертикали. Матрица:
`` [ sx 0 0 ] [ 0 sy 0 ] [ 0 0 1 ] ``
Поворот
Функция CGAffineTransformMakeRotation(angle) вращает объект на заданный угол в радианах вокруг начала координат. Матрица поворота:
`` [ cos(angle) sin(angle) 0 ] [ -sin(angle) cos(angle) 0 ] [ 0 0 1 ] ``
Сдвиг (skew)
Функции CGAffineTransformMakeSkewX(shx) и CGAffineTransformMakeSkewY(shy) деформируют объект, наклоняя его по одной из осей. Сдвиг по оси X задаётся значением shx, по оси Y — shy. Матрица:
`` [ 1 shx 0 ] [ shy 1 0 ] [ 0 0 1 ] ``
Композиция преобразований
CGAffineTransform поддерживает последовательное применение нескольких преобразований через функции CGAffineTransformConcat и CGAffineTransformTranslate, CGAffineTransformScale, CGAffineTransformRotate. При конкатенации порядок операций имеет значение: преобразования применяются в порядке, обратном их добавлению. Например, сначала выполняется поворот, затем масштабирование, и только потом перемещение.
Функция CGAffineTransformInvert позволяет получить обратное преобразование, которое отменяет эффект исходного. Она полезна для вычисления координат точки в исходной системе отсчёта после преобразования.
Применение в графических фреймворках
Core Graphics
В Core Graphics CGAffineTransform используется для управления контекстом рисования. Функции CGContextConcatCTM и CGContextGetCTM позволяют применять преобразования к текущему графическому контексту, что влияет на все последующие операции рисования. Это используется для реализации масштабирования, поворота и сдвига изображений при рендеринге.
UIKit
В UIKit CGAffineTransform применяется к объектам UIView через свойство transform. Это позволяет анимировать изменения положения, размера и ориентации элементов интерфейса. Например, с помощью UIView.animate можно плавно повернуть кнопку или увеличить изображение. Также структура используется в UIGestureRecognizer для обработки жестов масштабирования и поворота.
SwiftUI
В SwiftUI CGAffineTransform используется реже, так как декларативный подход предлагает собственные модификаторы .rotationEffect, .scaleEffect и .offset. Однако при работе с Canvas или Path разработчик может напрямую применять CGAffineTransform через методы transform и concatenating.
Примеры использования
Поворот изображения в UIImageView
``swift let imageView = UIImageView() imageView.transform = CGAffineTransform(rotationAngle: .pi / 4) ``
Масштабирование с анимацией
``swift UIView.animate(withDuration: 0.5) { view.transform = CGAffineTransform(scaleX: 1.5, y: 1.5) } ``
Комбинированное преобразование
``swift var transform = CGAffineTransform.identity transform = transform.translatedBy(x: 100, y: 50) transform = transform.rotated(by: .pi / 6) transform = transform.scaledBy(x: 2, y: 2) view.transform = transform ``
Ограничения и особенности
CGAffineTransform поддерживает только аффинные преобразования, то есть не может выполнять перспективные искажения (например, создание эффекта 3D-перспективы). Для таких задач используется структура CATransform3D из Core Animation, работающая с матрицами 4×4.
Также следует учитывать, что при многократном применении преобразований может накапливаться погрешность вычислений с плавающей точкой, особенно при работе с анимациями. Для минимизации ошибок рекомендуется сбрасывать преобразование к единичной матрице перед созданием нового.
История и версии
CGAffineTransform была введена в операционной системе NeXTSTEP в 1989 году и затем перенесена в macOS (ранее OS X) и iOS. Структура остаётся неизменной на протяжении всех версий, однако в Swift она была адаптирована для работы с типами CGFloat и Double. В iOS 13 и macOS 10.15 появилась поддержка преобразований через протокол Animatable в SwiftUI.
Источники
- Apple Inc. «CGAffineTransform» — документация для разработчиков.
- Apple Inc. «Core Graphics Programming Guide» — руководство по графическому программированию.
- Foley, J. D. et al. «Computer Graphics: Principles and Practice» — учебник по компьютерной графике.
- Документация SwiftUI и UIKit на официальном сайте Apple Developer.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →