Buscar..
Creando un CALayer
Puedes crear un CALayer y establecer su marco de esta manera:
Rápido:
let layer = CALayer()
layer.frame = CGRect(x: 0, y: 0, width: 60, height: 80)
C objetivo:
CALayer *layer = [[CALayer alloc] init];
layer.frame = CGRectMake(0, 0, 60, 80);
Luego puede agregarlo como una subcapa a un CALayer existente:
Rápido:
existingLayer.addSublayer(layer)
C objetivo:
[existingLayer addSublayer:layer];
Nota:
Para hacer esto necesitas incluir el framework QuartzCore.
Rápido:
@import QuartzCore
C objetivo
#import <QuartzCore/QuartzCore.h>
Creando partículas con CAEmitterLayer
La clase CAEmitterLayer proporciona un sistema de emisor de partículas para Core Animation. Las partículas están definidas por instancias de CAEmitterCell .
Las partículas se dibujan sobre el color de fondo y el borde de la capa.
var emitter = CAEmitterLayer()
emitter.emitterPosition = CGPoint(x: frame.size.width / 2.0, y: -20)
emitter.emitterShape = kCAEmitterLayerLine
emitter.emitterSize = CGSize(width: frame.size.width, height: 1)
emitter.emitterCells = cells
layer.addSublayer(emitter)
Vista del emisor con imagen personalizada.
Por ejemplo, crearemos una vista que contenga una capa emisora y anime las partículas.
import QuartzCore
class ConfettiView: UIView {
// main emitter layer
var emitter: CAEmitterLayer!
// array of color to emit
var colors: [UIColor]!
// intensity of appearance
var intensity: Float!
private var active :Bool!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
// initialization
colors = [UIColor.redColor(),
UIColor.greenColor(),
UIColor.blueColor()
]
intensity = 0.2
active = false
}
func startConfetti() {
emitter = CAEmitterLayer()
emitter.emitterPosition = CGPoint(x: frame.size.width / 2.0, y: -20)
emitter.emitterShape = kCAEmitterLayerLine
emitter.emitterSize = CGSize(width: frame.size.width, height: 1)
var cells = [CAEmitterCell]()
for color in colors {
cells.append(confettiWithColor(color))
}
emitter.emitterCells = cells
layer.addSublayer(emitter)
active = true
}
func stopConfetti() {
emitter?.birthRate = 0
active = false
}
func confettiWithColor(color: UIColor) -> CAEmitterCell {
let confetti = CAEmitterCell()
confetti.birthRate = 10.0 * intensity
confetti.lifetime = 180.0 * intensity
confetti.lifetimeRange = 0
confetti.color = color.CGColor
confetti.velocity = CGFloat(350.0 * intensity)
confetti.velocityRange = CGFloat(40.0 * intensity)
confetti.emissionLongitude = CGFloat(M_PI)
confetti.emissionRange = CGFloat(M_PI_4)
confetti.spin = CGFloat(3.5 * intensity)
confetti.spinRange = CGFloat(4.0 * intensity)
// WARNING: A layer can set this property to a CGImageRef to display the image as its contents.
confetti.contents = UIImage(named: "confetti")?.CGImage
return confetti
}
internal func isActive() -> Bool {
return self.active
}
}
Debe agregar una imagen de "confeti" o definir rect con confetti.contentsRect
Cómo agregar un UIImage a un CALayer
Puede agregar una imagen a la layer
una vista simplemente usando su propiedad de contents
:
myView.layer.contents = UIImage(named: "star")?.CGImage
- Tenga en cuenta que el
UIImage
necesita ser convertido aCGImage
.
Si desea agregar la imagen en su propia capa, puede hacerlo de la siguiente manera:
let myLayer = CALayer()
let myImage = UIImage(named: "star")?.CGImage
myLayer.frame = myView.bounds
myLayer.contents = myImage
myView.layer.addSublayer(myLayer)
Modificando la apariencia
El código anterior produce una vista como esta. El azul claro es el UIView
y la estrella azul oscuro es el UIImage
.
Como puedes ver, sin embargo, parece pixelado. Esto se debe a que el UIImage
es más pequeño que el UIView
por lo que se está escalando para completar la vista, que es el valor predeterminado, no se especifica nada más.
Los siguientes ejemplos muestran variaciones en la propiedad contentsGravity
la capa. El código se ve así:
myView.layer.contents = UIImage(named: "star")?.CGImage
myView.layer.contentsGravity = kCAGravityTop
myView.layer.geometryFlipped = true
En iOS, es posible que desee establecer la propiedad geometryFlipped
en true
si está haciendo algo con gravedad superior o inferior, de lo contrario será lo contrario de lo que espera. (Solo la gravedad se invierte verticalmente, no la representación del contenido. Si tiene problemas con el contenido que se invierte, consulte esta respuesta de Desbordamiento de pila ).
Hay dos ejemplos de UIView
continuación para cada configuración de contentsGravity
UIView
, una vista es más grande que el UIImage
y la otra es más pequeña. De esta manera puedes ver los efectos de la escala y la gravedad.
kCAGravityResize
Este es el valor predeterminado.
kCAGravityResizeAspect
kCAGravityResizeAspectFill
kCAGravityCenter
kCAGravityTop
kCAGravityBottom
kCAGravityLeft
kCAGravityRight
kCAGravityTopLeft
kCAGravityTopRight
kCAGravityBottomLeft
kCAGravityBottomRight
Relacionado
- Propiedad de modo de contenido de una vista
- Dibujando un
UIImage
endrawRect
conCGContextDrawImage
- Tutorial de CALayer: Primeros pasos
Notas
- Este ejemplo proviene originalmente de esta respuesta de desbordamiento de pila .
Agregar transformaciones a un CALayer (traducir, rotar, escalar)
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(30.0 * M_PI / 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. Primero, sin embargo, mostraré cómo configuro el proyecto en caso de que también quieras jugar con él.
Preparar
Para los siguientes ejemplos, configuro 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.blueColor().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 está 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 y z, 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 * M_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 establecimosz
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 * M_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 algún 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 basándose en el 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
Este ejemplo proviene originalmente de este ejemplo de desbordamiento de pila .
Deshabilitar animaciones
CALayer
animaciones de propiedades de CALayer
están habilitadas por defecto. Cuando esto no es deseable, se pueden desactivar de la siguiente manera.
Rápido
CATransaction.begin()
CATransaction.setDisableActions(true)
// change layer properties that you don't want to animate
CATransaction.commit()
C objetivo
[CATransaction begin];
[CATransaction setDisableActions:YES];
// change layer properties that you don't want to animate
[CATransaction commit];
Esquinas redondeadas
layer.masksToBounds = true;
layer.cornerRadius = 8;
Oscuridad
Puedes usar 5 propiedades en cada capa para configurar tus sombras:
-
shadowOffset
- esta propiedad mueve tu sombra a la izquierda / derecha o arriba / abajo
self.layer.shadowOffset = CGSizeMake(-1, -1); // 1px left and up
self.layer.shadowOffset = CGSizeMake(1, 1); // 1px down and right
-
shadowColor
- esto establece el color de tu sombra
self.layer.shadowColor = [UIColor blackColor].CGColor;
-
shadowOpacity
- esta es la opacidad de la sombra, de0
a1
self.layer.shadowOpacity = 0.2;
-
shadowRadius
: este es el radio de desenfoque (equivalente a la propiedad de desenfoque en Sketch o Photoshop)
self.layer.shadowRadius = 6;
-
shadowPath
: esta es una propiedad importante para el rendimiento, cuando el iOS no configurado basa la sombra en el canal alfa de la vista, que puede ser intensivo en el rendimiento con un PNG complejo con alfa. Esta propiedad te permite forzar una forma para tu sombra y tener más rendimiento gracias a ella.
C objetivo
self.layer.shadowPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,100,100)]; //this does a circular shadow
Swift 3
self.layer.shadowPath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100)).cgPath