Ricerca…
Creazione di un CALayer
Puoi creare un CALayer e impostarne la cornice in questo modo:
Swift:
let layer = CALayer()
layer.frame = CGRect(x: 0, y: 0, width: 60, height: 80)
Objective-C:
CALayer *layer = [[CALayer alloc] init];
layer.frame = CGRectMake(0, 0, 60, 80);
È quindi possibile aggiungerlo come sottolivello a un CALayer esistente:
Swift:
existingLayer.addSublayer(layer)
Objective-C:
[existingLayer addSublayer:layer];
Nota:
Per fare questo è necessario includere il framework QuartzCore.
Swift:
@import QuartzCore
Objective-C
#import <QuartzCore/QuartzCore.h>
Creazione di particelle con CAEmitterLayer
La classe CAEmitterLayer fornisce un sistema di emittenti di particelle per Core Animation. Le particelle sono definite da istanze di CAEmitterCell .
Le particelle sono disegnate sopra il colore e il bordo dello sfondo del livello.
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 emettitore con immagine personalizzata
Ad esempio creeremo una vista che contiene il livello di emettitore e anima le particelle.
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
}
}
È necessario aggiungere l'immagine "confetti" o definire rect con confetti.contentsRect
Come aggiungere una UIImage a un CALayer
È possibile aggiungere un'immagine a di una vista layer
semplicemente utilizzando il suo contents
di proprietà:
myView.layer.contents = UIImage(named: "star")?.CGImage
- Si noti che
UIImage
deve essere convertito in unCGImage
.
Se desideri aggiungere l'immagine nel proprio livello, puoi farlo in questo modo:
let myLayer = CALayer()
let myImage = UIImage(named: "star")?.CGImage
myLayer.frame = myView.bounds
myLayer.contents = myImage
myView.layer.addSublayer(myLayer)
Modifica l'aspetto
Il codice precedente produce una vista come questa. L'azzurro è l' UIView
e la stella blu scuro è UIImage
.
Come puoi vedere, però, sembra pixelato. Questo perché UIImage
è più piccolo di UIView
quindi viene ridimensionato per riempire la vista, che è l'impostazione predefinita e non specifica altro.
Gli esempi seguenti mostrano variazioni sulla proprietà contentsGravity
del contentsGravity
del layer. Il codice si presenta così:
myView.layer.contents = UIImage(named: "star")?.CGImage
myView.layer.contentsGravity = kCAGravityTop
myView.layer.geometryFlipped = true
In iOS, potresti voler impostare la proprietà geometryFlipped
su true
se stai facendo qualcosa con gravità superiore o inferiore, altrimenti sarà l'opposto di quello che ti aspetti. (Solo la gravità viene ruotata verticalmente, non il rendering del contenuto. Se riscontri problemi con il contenuto capovolto, consulta questa risposta sull'overflow dello stack .)
Ci sono due UIView
esempi indicati per ogni contentsGravity
impostazione, una vista è maggiore della UIImage
e l'altro è più piccolo. In questo modo puoi vedere gli effetti del ridimensionamento e della gravità.
kCAGravityResize
Questo è l'impostazione predefinita.
kCAGravityResizeAspect
kCAGravityResizeAspectFill
kCAGravityCenter
kCAGravityTop
kCAGravityBottom
kCAGravityLeft
kCAGravityRight
kCAGravityTopLeft
kCAGravityTopRight
kCAGravityBottomLeft
kCAGravityBottomRight
Relazionato
- Proprietà della modalità Contenuto di una vista
- Disegnare una
UIImage
indrawRect
conCGContextDrawImage
- Esercitazione su CALayer: come iniziare
Gli appunti
- Questo esempio proviene originariamente da questa risposta di Overflow dello stack .
Aggiungere trasformazioni a un CALayer (tradurre, ruotare, ridimensionare)
Nozioni di base
Ci sono un certo numero di trasformazioni diverse che puoi fare su un livello, ma quelle di base sono
- tradurre (spostare)
- scala
- ruotare
Per eseguire trasformazioni su un CALayer
, impostare la proprietà di transform
del livello su un tipo CATransform3D
. Ad esempio, per tradurre un livello, si dovrebbe fare qualcosa del genere:
myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)
La parola Make
è usata nel nome per creare la trasformazione iniziale: CATransform3D Make Translation. Le trasformazioni successive che vengono applicate omettono il Make
. Vedi, per esempio, questa rotazione seguita da una traduzione:
let rotation = CATransform3DMakeRotation(CGFloat(30.0 * M_PI / 180.0), 20, 20, 0)
myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)
Ora che abbiamo le basi su come realizzare una trasformazione, diamo un'occhiata ad alcuni esempi su come fare ognuno di essi. Prima, però, mostrerò come ho impostato il progetto nel caso in cui vogliate giocare con esso.
Impostare
Per gli esempi che seguono ho impostato un'applicazione di visualizzazione singola e aggiunto uno UIView
con uno sfondo blu chiaro allo storyboard. Ho collegato la vista al controller della vista con il seguente codice:
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 ...
}
}
Esistono molti tipi diversi di CALayer
, ma ho scelto di utilizzare CATextLayer
modo che le trasformazioni siano visivamente più chiare.
Tradurre
La trasformazione di traduzione sposta il livello. La sintassi di base è
CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat)
dove tx
è il cambiamento nelle coordinate x, ty
è il cambiamento in y, e tz
è il cambiamento in z.
Esempio
In iOS l'origine del sistema di coordinate è in alto a sinistra, quindi se volessimo spostare il livello di 90 punti verso destra e 50 punti verso il basso, faremo quanto segue:
myLayer.transform = CATransform3DMakeTranslation(90, 50, 0)
Gli appunti
- Ricorda che puoi incollarlo nel metodo
transformExample()
nel codice progetto precedente. - Dato che stiamo andando a trattare due dimensioni qui,
tz
è impostato a0
. - La linea rossa nell'immagine qui sopra va dal centro della posizione originale al centro della nuova posizione. Questo perché le trasformazioni vengono eseguite in relazione al punto di ancoraggio e il punto di ancoraggio di default si trova al centro del livello.
Scala
La scala trasforma tratti o schiaccia il livello. La sintassi di base è
CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat)
dove sx
, sy
e sz
sono i numeri con cui ridimensionare (moltiplicare) le coordinate x, y e z rispettivamente.
Esempio
Se volessimo metà della larghezza e triplicare l'altezza, faremmo quanto segue
myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0)
Gli appunti
- Dato che stiamo lavorando solo in due dimensioni, moltiplichiamo le coordinate z per 1.0 per lasciarle inalterate.
- Il punto rosso nell'immagine sopra rappresenta il punto di ancoraggio. Nota come il ridimensionamento è fatto in relazione al punto di ancoraggio. Cioè, tutto è teso verso o lontano dal punto di ancoraggio.
Ruotare
La trasformazione di rotazione ruota lo strato attorno al punto di ancoraggio (il centro del livello di default). La sintassi di base è
CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat)
dove angle
è l'angolo in radianti che lo strato deve essere ruotato e x
, y
e z
sono gli assi su cui ruotare. Impostando un asse su 0 si annulla una rotazione attorno a quel particolare asse.
Esempio
Se volessimo ruotare uno strato in senso orario di 30 gradi, faremmo quanto segue:
let degrees = 30.0
let radians = CGFloat(degrees * M_PI / 180)
myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0)
Gli appunti
- Dato che stiamo lavorando in due dimensioni, vogliamo solo che il piano xy sia ruotato attorno all'asse z. Così abbiamo impostato
x
edy
di0.0
e impostarez
a1.0
. - Questo ha ruotato lo strato in senso orario. Potremmo aver ruotato in senso antiorario impostando
z
su-1.0
. - Il punto rosso indica dove si trova il punto di ancoraggio. La rotazione viene eseguita attorno al punto di ancoraggio.
Trasformazioni multiple
Per combinare più trasformazioni, potremmo usare la concatinazione come questa
CATransform3DConcat(a: CATransform3D, b: CATransform3D)
Tuttavia, faremo solo uno dopo l'altro. La prima trasformazione utilizzerà la Make
nel suo nome. Le seguenti trasformazioni non useranno Make
, ma prenderanno la trasformazione precedente come parametro.
Esempio
Questa volta combiniamo tutte e tre le trasformazioni precedenti.
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
Gli appunti
- L'ordine in cui le trasformazioni sono fatte in materia.
- Tutto è stato fatto in relazione al punto di ancoraggio (punto rosso).
Una nota su punto di ancoraggio e posizione
Abbiamo fatto tutte le nostre trasformazioni sopra senza cambiare il punto di ancoraggio. A volte è necessario cambiarlo, però, come se si volesse ruotare attorno ad un altro punto oltre al centro. Tuttavia, questo può essere un po 'complicato.
Il punto di ancoraggio e la posizione sono entrambi nello stesso punto. Il punto di ancoraggio è espresso come unità del sistema di coordinate del livello (il valore predefinito è 0.5, 0.5
) e la posizione è espressa nel sistema di coordinate del superlayer. Possono essere impostati in questo modo
myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
myLayer.position = CGPoint(x: 50, y: 50)
Se si imposta solo il punto di ancoraggio senza modificare la posizione, la cornice cambia in modo tale che la posizione si trovi nel punto giusto. O più precisamente, la cornice viene ricalcolata in base al nuovo punto di ancoraggio e alla vecchia posizione. Questo di solito dà risultati inaspettati. I seguenti due articoli hanno un'ottima discussione su questo.
Guarda anche
- Bordo, angoli arrotondati e ombra su un
CALayer
- Utilizzo di un bordo con un percorso di Bézier per un livello
Questo esempio deriva originariamente da questo esempio di overflow dello stack .
Disabilita animazioni
CALayer
animazioni delle proprietà CALayer
sono abilitate per impostazione predefinita. Quando questo non è desiderabile, possono essere disabilitati come segue.
veloce
CATransaction.begin()
CATransaction.setDisableActions(true)
// change layer properties that you don't want to animate
CATransaction.commit()
Objective-C
[CATransaction begin];
[CATransaction setDisableActions:YES];
// change layer properties that you don't want to animate
[CATransaction commit];
Angoli arrotondati
layer.masksToBounds = true;
layer.cornerRadius = 8;
Shadows
Puoi usare 5 proprietà su ogni livello per configurare le tue ombre:
-
shadowOffset
: questa proprietà sposta l'ombra a sinistra / a destra o su / giù
self.layer.shadowOffset = CGSizeMake(-1, -1); // 1px left and up
self.layer.shadowOffset = CGSizeMake(1, 1); // 1px down and right
-
shadowColor
: imposta il colore della tua ombra
self.layer.shadowColor = [UIColor blackColor].CGColor;
-
shadowOpacity
: questa è l'opacità dell'ombra, da0
a1
self.layer.shadowOpacity = 0.2;
-
shadowRadius
: questo è il raggio di sfocatura (equivalente alla proprietà sfocatura di Sketch o Photoshop)
self.layer.shadowRadius = 6;
-
shadowPath
: questa è una proprietà importante per le prestazioni, quando unset di iOS non fashadowPath
l'ombra sul canale alfa della vista, che può richiedere prestazioni elevate con un PNG complesso con alfa. Questa proprietà ti consente di forzare una forma per la tua ombra ed essere più performante a causa di essa.
Objective-C
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