ios - guia - ¿Cómo hacer transformaciones en un CALayer?
qgis manual (1)
Lo esencial
Hay una serie de transformaciones diferentes que puedes hacer en una capa, pero las básicas son
- traducir
- escala
- girar
Para realizar transformaciones en un CALayer
, establezca la propiedad de transform
la capa en un tipo CATransform3D
. Por ejemplo, para traducir una capa, harías algo como esto:
myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)
La palabra Make
se usa en el nombre para crear la transformación inicial: CATransform3D Make Translation. Las transformaciones subsiguientes que se aplican omiten la Make
. Vea, por ejemplo, esta rotación seguida de una traducción:
let rotation = CATransform3DMakeRotation(CGFloat.pi * 30.0 / 180.0, 20, 20, 0)
myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)
Ahora que tenemos la base de cómo hacer una transformación, veamos algunos ejemplos de cómo hacer cada uno. Sin embargo, primero, mostraré cómo configuro el proyecto en caso de que también quieras jugar con él.
Preparar
Para los siguientes ejemplos configuré una aplicación de vista única y agregué una vista UIView
con un fondo azul claro al guión gráfico. Conecté la vista al controlador de vista con el siguiente código:
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 ...
}
}
Hay muchos tipos diferentes de CALayer
, pero elegí usar CATextLayer
para que las transformaciones sean más claras visualmente.
Traducir
La transformación de la traducción mueve la capa. La sintaxis básica es
CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat)
donde tx
es el cambio en las coordenadas x, ty
es el cambio en y, y tz
es el cambio en z.
Ejemplo
En iOS, el origen del sistema de coordenadas está en la parte superior izquierda, por lo que si quisiéramos mover la capa 90 puntos a la derecha y 50 puntos hacia abajo, haríamos lo siguiente:
myLayer.transform = CATransform3DMakeTranslation(90, 50, 0)
Notas
- Recuerde que puede pegar esto en el método
transformExample()
en el código del proyecto anterior. - Ya que vamos a tratar dos dimensiones aquí,
tz
se establece en0
. - La línea roja en la imagen de arriba va desde el centro de la ubicación original hasta el centro de la nueva ubicación. Esto se debe a que las transformaciones se realizan en relación con el punto de anclaje y el punto de anclaje por defecto se encuentra en el centro de la capa.
Escala
La transformación a escala estira o aplasta la capa. La sintaxis básica es
CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat)
donde sx
, sy
y sz
son los números por los cuales escalar (multiplicar) las coordenadas x, y, yz respectivamente.
Ejemplo
Si quisiéramos la mitad del ancho y el triple de la altura, haríamos lo siguiente
myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0)
Notas
- Como solo trabajamos en dos dimensiones, solo multiplicamos las coordenadas z por 1.0 para no afectarlas.
- El punto rojo en la imagen de arriba representa el punto de anclaje. Observe cómo se realiza el escalado en relación con el punto de anclaje. Es decir, todo se estira hacia o desde el punto de anclaje.
Girar
La transformación de rotación gira la capa alrededor del punto de anclaje (el centro de la capa de forma predeterminada). La sintaxis básica es
CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat)
donde angle
es el ángulo en radianes en que se debe rotar la capa y x
, y
y z
son los ejes sobre los cuales rotar. Establecer un eje en 0 cancela una rotación alrededor de ese eje en particular.
Ejemplo
Si quisiéramos rotar una capa en sentido horario 30 grados, haríamos lo siguiente:
let degrees = 30.0
let radians = CGFloat(degrees * Double.pi / 180)
myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0)
Notas
- Como estamos trabajando en dos dimensiones, solo queremos que el plano xy gire alrededor del eje z. Así establecimos
x
ey
a0.0
y establecemosz
a1.0
. - Esto hizo girar la capa en el sentido de las agujas del reloj. Podríamos haber girado en sentido contrario a las manecillas del reloj estableciendo
z
en-1.0
. - El punto rojo muestra dónde está el punto de anclaje. La rotación se realiza alrededor del punto de anclaje.
Transformaciones multiples
Para combinar múltiples transformaciones podríamos usar concatinación como esta
CATransform3DConcat(a: CATransform3D, b: CATransform3D)
Sin embargo, vamos a hacer uno tras otro. La primera transformación utilizará la Make
en su nombre. Las siguientes transformaciones no utilizarán Make
, pero tomarán la transformación anterior como un parámetro.
Ejemplo
Esta vez combinamos las tres transformaciones anteriores.
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
Notas
- El orden en que se realizan las transformaciones en materia.
- Todo se hizo en relación con el punto de anclaje (punto rojo).
Una nota sobre el punto de anclaje y la posición
Hicimos todas nuestras transformaciones anteriores sin cambiar el punto de anclaje. Sin embargo, a veces es necesario cambiarlo, como si desea girar alrededor de otro punto además del centro. Sin embargo, esto puede ser un poco complicado.
El punto de anclaje y la posición están en el mismo lugar. El punto de anclaje se expresa como una unidad del sistema de coordenadas de la capa (el valor predeterminado es 0.5, 0.5
) y la posición se expresa en el sistema de coordenadas de la superapa. Se pueden configurar de esta manera
myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
myLayer.position = CGPoint(x: 50, y: 50)
Si solo establece el punto de anclaje sin cambiar la posición, entonces el marco cambia para que la posición esté en el lugar correcto. O más precisamente, el marco se recalcula en función del nuevo punto de anclaje y la posición anterior. Esto suele dar resultados inesperados. Los siguientes dos artículos tienen una excelente discusión de esto.
Ver también
- Borde, esquinas redondeadas y sombra en un
CALayer
- Usando un borde con una ruta Bezier para una capa
Antes de escribir esta pregunta, he
- Tenía experiencia con Affine Transforms para vistas.
- lea la documentación de Transforms en la Guía de programación de Quartz 2D
- visto este tutorial detallado CALayer
- descargado y ejecutar el proyecto LayerPlayer desde Github
Sin embargo, todavía tengo problemas para entender cómo hacer transformaciones básicas en una capa . Encontrar explicaciones y ejemplos simples para traducir, rotar y escalar ha sido difícil.
Hoy finalmente decidí sentarme, hacer un proyecto de prueba y resolverlos. Mi respuesta está abajo.
Notas:
- Solo hago Swift, pero si alguien más quiere agregar el código de Objective-C, sé mi invitado.
- En este punto, solo me interesa entender las transformaciones 2D.