Zoeken…
Een CALayer maken
U kunt een CALayer maken en het frame als volgt instellen:
Snel:
let layer = CALayer()
layer.frame = CGRect(x: 0, y: 0, width: 60, height: 80)
Doelstelling C:
CALayer *layer = [[CALayer alloc] init];
layer.frame = CGRectMake(0, 0, 60, 80);
U kunt het vervolgens als een sublaag toevoegen aan een bestaande CALayer:
Snel:
existingLayer.addSublayer(layer)
Doelstelling C:
[existingLayer addSublayer:layer];
Notitie:
Om dit te doen, moet u het QuartzCore-framework opnemen.
Snel:
@import QuartzCore
Doelstelling C
#import <QuartzCore/QuartzCore.h>
Deeltjes maken met CAEmitterLayer
De CAEmitterLayer- klasse biedt een deeltjesemittersysteem voor Core Animation. De deeltjes worden gedefinieerd door instanties van CAEmitterCell .
De deeltjes worden boven de achtergrondkleur en rand van de laag getekend.
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)
Zenderweergave met aangepaste afbeelding
We zullen bijvoorbeeld een weergave maken die een emitterlaag bevat en deeltjes animeert.
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
}
}
U moet een afbeelding "confetti" toevoegen of rect definiëren met confetti.contentsRect
Een UII-afbeelding toevoegen aan een CALayer
U kunt een afbeelding eenvoudig aan de layer
van een weergave toevoegen met de eigenschap contents
:
myView.layer.contents = UIImage(named: "star")?.CGImage
- Merk op dat de
UIImage
moet worden geconverteerd naar eenCGImage
.
Als u de afbeelding in zijn eigen laag wilt toevoegen, kunt u dit als volgt doen:
let myLayer = CALayer()
let myImage = UIImage(named: "star")?.CGImage
myLayer.frame = myView.bounds
myLayer.contents = myImage
myView.layer.addSublayer(myLayer)
Het uiterlijk wijzigen
De bovenstaande code produceert een dergelijke weergave. Het lichtblauw is de UIView
en de donkerblauwe ster is de UIImage
.
Zoals je ziet, ziet het er echter korrelig uit. Dit komt omdat de UIImage
afbeelding kleiner is dan de UIView
zodat deze wordt geschaald om de weergave te vullen. Dit is de standaardinstelling die u niets anders opgeeft.
De voorbeelden hieronder tonen variaties op de laag contentsGravity
objecten. De code ziet er zo uit:
myView.layer.contents = UIImage(named: "star")?.CGImage
myView.layer.contentsGravity = kCAGravityTop
myView.layer.geometryFlipped = true
In iOS wilt u misschien de eigenschap geometryFlipped
op true
als u iets doet met zwaartekracht boven of onder, anders is dit het tegenovergestelde van wat u verwacht. (Alleen de zwaartekracht wordt verticaal omgedraaid, niet de weergave van de inhoud. Als u problemen ondervindt met de inhoud die wordt omgedraaid, zie dan dit antwoord Stack Overflow .)
Er zijn twee UIView
voorbeelden hieronder voor elke contentsGravity
Zwaartekrachtinstelling, één weergave is groter dan de UIImage
afbeelding en de andere is kleiner. Op deze manier kunt u de effecten van de schaalverdeling en de zwaartekracht zien.
kCAGravityResize
Dit is de standaardinstelling.
kCAGravityResizeAspect
kCAGravityResizeAspectFill
kCAGravityCenter
kCAGravityTop
kCAGravityBottom
kCAGravityLeft
kCAGravityRight
kCAGravityTopLeft
kCAGravityTopRight
kCAGravityBottomLeft
kCAGravityBottomRight
Verwant
- Inhoudsmoduseigenschap van een weergave
- Een
UIImage
indrawRect
metCGContextDrawImage
- CALayer Zelfstudie: Aan de slag
Notes
- Dit voorbeeld komt oorspronkelijk uit dit Stack Overflow-antwoord .
Transformaties toevoegen aan een CALayer (vertalen, roteren, schalen)
Basics
Er zijn een aantal verschillende transformaties die je op een laag kunt doen, maar de basis zijn dat
- vertalen (verplaatsen)
- schaal
- draaien
Als u transformaties op een CALayer
, stelt u de eigenschap transform
de laag in op een CATransform3D
type. Als u bijvoorbeeld een laag wilt vertalen, zou u zoiets doen:
myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)
Het woord Make
wordt gebruikt in de naam voor het maken van de eerste transformatie: CATransform3D Make Translation. Latere transformaties die worden toegepast weglaten de Make
. Zie bijvoorbeeld deze rotatie gevolgd door een vertaling:
let rotation = CATransform3DMakeRotation(CGFloat(30.0 * M_PI / 180.0), 20, 20, 0)
myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)
Nu we de basis hebben voor het maken van een transformatie, laten we eens kijken naar enkele voorbeelden van hoe je ze allemaal kunt doen. Eerst zal ik echter laten zien hoe ik het project heb opgezet voor het geval je er ook mee wilt spelen.
Opstelling
Voor de volgende voorbeelden heb ik een Single View-applicatie opgezet en een UIView
met een lichtblauwe achtergrond aan het storyboard toegevoegd. Ik heb de weergave gekoppeld aan de weergavecontroller met de volgende code:
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 ...
}
}
Er zijn veel verschillende soorten CALayer
, maar ik heb ervoor gekozen CATextLayer
te gebruiken zodat de transformaties visueel duidelijker worden.
Vertalen
De vertaaltransformatie verplaatst de laag. De basissyntaxis is
CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat)
waarbij tx
de verandering in de x-coördinaten is, ty
de verandering in y is en tz
de verandering in z.
Voorbeeld
In iOS bevindt de oorsprong van het coördinatensysteem zich linksboven, dus als we de laag 90 punten naar rechts en 50 punten naar beneden wilden verplaatsen, zouden we het volgende doen:
myLayer.transform = CATransform3DMakeTranslation(90, 50, 0)
Notes
- Vergeet niet dat u dit in de methode
transformExample()
in de bovenstaande projectcode kunt plakken. - Omdat we hier slechts twee dimensies gaan behandelen, is
tz
ingesteld op0
. - De rode lijn in de bovenstaande afbeelding gaat van het midden van de oorspronkelijke locatie naar het midden van de nieuwe locatie. Dat komt omdat transformaties worden uitgevoerd in relatie tot het ankerpunt en het ankerpunt standaard in het midden van de laag staat.
Schaal
De schaaltransformatie rekt de laag uit of squishet. De basissyntaxis is
CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat)
waarbij sx
, sy
en sz
de getallen zijn waarmee respectievelijk de x-, y- en z-coördinaten kunnen worden geschaald (vermenigvuldigd).
Voorbeeld
Als we de helft van de breedte en de hoogte zouden verdrievoudigen, zouden we het volgende doen
myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0)
Notes
- Omdat we slechts in twee dimensies werken, vermenigvuldigen we gewoon de z-coördinaten met 1.0 om ze onaangetast te laten.
- De rode stip in de bovenstaande afbeelding vertegenwoordigt het ankerpunt. Merk op hoe de schaling wordt uitgevoerd in relatie tot het ankerpunt. Dat wil zeggen, alles is ofwel uitgerekt naar of weg van het ankerpunt.
Draaien
De rotatietransformatie roteert de laag rond het ankerpunt (standaard het midden van de laag). De basissyntaxis is
CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat)
waarbij angle
de hoek in radialen is die de laag moet worden geroteerd en x
, y
en z
de assen zijn waarover moet worden geroteerd. Als u een as op 0 instelt, wordt een rotatie rond die specifieke as geannuleerd.
Voorbeeld
Als we een laag 30 graden rechtsom zouden willen draaien, zouden we het volgende doen:
let degrees = 30.0
let radians = CGFloat(degrees * M_PI / 180)
myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0)
Notes
- Omdat we in twee dimensies werken, willen we alleen dat het xy-vlak rond de z-as wordt gedraaid. Dus stellen we
x
eny
op0.0
en stellenz
op1.0
. - Dit roteerde de laag met de klok mee. We hadden tegen de klok in kunnen draaien door
z
te stellen op-1.0
. - De rode stip geeft aan waar het ankerpunt is. De rotatie gebeurt rond het ankerpunt.
Meerdere transformaties
Om meerdere transformaties te combineren, kunnen we concatinatie als deze gebruiken
CATransform3DConcat(a: CATransform3D, b: CATransform3D)
We zullen echter gewoon de een na de ander doen. De eerste transformatie zal het Make
in zijn naam gebruiken. De volgende transformaties gebruiken Make
, maar ze nemen de vorige transformatie als parameter.
Voorbeeld
Deze keer combineren we alle drie de vorige transformaties.
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
Notes
- De volgorde waarin de transformaties worden uitgevoerd in zaken.
- Alles werd gedaan in relatie tot het ankerpunt (rode stip).
Een opmerking over ankerpunt en positie
We hebben al onze transformaties hierboven uitgevoerd zonder het ankerpunt te wijzigen. Soms is het echter nodig om het te wijzigen, bijvoorbeeld als u rond een ander punt naast het midden wilt roteren. Dit kan echter een beetje lastig zijn.
Het ankerpunt en de positie bevinden zich beide op dezelfde plaats. Het ankerpunt wordt uitgedrukt als een eenheid van het coördinatensysteem van de laag (standaard is 0.5, 0.5
) en de positie wordt uitgedrukt in het coördinatensysteem van de superlaag. Ze kunnen zo worden ingesteld
myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
myLayer.position = CGPoint(x: 50, y: 50)
Als u alleen het ankerpunt instelt zonder de positie te wijzigen, verandert het frame zodat de positie op de juiste plek staat. Of beter gezegd, het frame wordt opnieuw berekend op basis van het nieuwe ankerpunt en de oude positie. Dit geeft meestal onverwachte resultaten. In de volgende twee artikelen wordt dit uitstekend besproken.
Zie ook
- Rand, afgeronde hoeken en schaduw op een
CALayer
- Een rand gebruiken met een Bezier-pad voor een laag
Dit voorbeeld komt oorspronkelijk uit dit Stack Overflow-voorbeeld .
Animaties uitschakelen
CALayer
eigenschapanimaties zijn standaard ingeschakeld. Wanneer dit ongewenst is, kunnen ze als volgt worden uitgeschakeld.
Snel
CATransaction.begin()
CATransaction.setDisableActions(true)
// change layer properties that you don't want to animate
CATransaction.commit()
Doelstelling C
[CATransaction begin];
[CATransaction setDisableActions:YES];
// change layer properties that you don't want to animate
[CATransaction commit];
Afgeronde hoeken
layer.masksToBounds = true;
layer.cornerRadius = 8;
Shadows
U kunt op elke laag 5 eigenschappen gebruiken om uw schaduwen te configureren:
-
shadowOffset
- deze eigenschap verplaatst je schaduw naar links / rechts of omhoog / omlaag
self.layer.shadowOffset = CGSizeMake(-1, -1); // 1px left and up
self.layer.shadowOffset = CGSizeMake(1, 1); // 1px down and right
-
shadowColor
- dit bepaalt de kleur van je schaduw
self.layer.shadowColor = [UIColor blackColor].CGColor;
-
shadowOpacity
- dit is de dekking van de schaduw, van0
tot1
self.layer.shadowOpacity = 0.2;
-
shadowRadius
- dit is de vervagingsradius (equivalent van de vervagingseigenschap in Sketch of Photoshop)
self.layer.shadowRadius = 6;
-
shadowPath
- dit is een belangrijke eigenschap voor prestaties, wanneer uitgeschakeld iOS de schaduw baseert op het alfakanaal van de weergave, dat prestatie-intensief kan zijn met een complexe PNG met alpha. Met deze eigenschap kunt u een vorm voor uw schaduw afdwingen en daardoor beter presteren.
Doelstelling 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