Avant d'écrire cette question, j'ai
Cependant, j'ai toujours du mal à comprendre comment effectuer des transformations de base sur une couche . Il a été difficile de trouver des explications et des exemples simples pour traduire, faire pivoter et mettre à l'échelle.
Aujourd'hui, j'ai finalement décidé de m'asseoir, de faire un projet de test et de les comprendre. Ma réponse est ci-dessous.
Remarques:
Il existe un certain nombre de transformations différentes que vous pouvez effectuer sur un calque, mais les
Pour effectuer des transformations sur un CALayer
, vous définissez la propriété transform
du calque sur un type CATransform3D
. Par exemple, pour traduire un calque, vous feriez quelque chose comme ceci:
myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)
Le mot Make
est utilisé dans le nom pour créer la transformation initiale: CATransform3D Make Translation. Les transformations suivantes qui sont appliquées omettent le Make
. Voir, par exemple, cette rotation suivie d'une traduction:
let rotation = CATransform3DMakeRotation(CGFloat.pi * 30.0 / 180.0, 20, 20, 0)
myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)
Maintenant que nous avons la base de la façon de faire une transformation, regardons quelques exemples de comment faire chacun. Mais d'abord, je vais montrer comment j'ai configuré le projet au cas où vous voudriez aussi jouer avec.
Pour les exemples suivants, j'ai configuré une application à vue unique et ajouté un UIView
avec un fond bleu clair au storyboard. J'ai connecté la vue au contrôleur de vue avec le code suivant:
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 ...
}
}
Il existe différents types de CALayer
, mais j'ai choisi d'utiliser CATextLayer
pour que les transformations soient plus claires visuellement.
La transformation de translation déplace le calque. La syntaxe de base est
CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat)
où tx
est le changement des coordonnées x, ty
est le changement en y et tz
est le changement en z.
Exemple
Dans iOS, l'origine du système de coordonnées est en haut à gauche, donc si nous voulions déplacer le calque de 90 points vers la droite et 50 points vers le bas, nous ferions ce qui suit:
myLayer.transform = CATransform3DMakeTranslation(90, 50, 0)
Remarques
transformExample()
dans le code de projet ci-dessus.tz
est réglé sur 0
.La transformation d'échelle étire ou écrase le calque. La syntaxe de base est
CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat)
où sx
, sy
et sz
sont les nombres par lesquels mettre à l'échelle (multiplier) les coordonnées x, y et z respectivement.
Exemple
Si nous voulions réduire de moitié la largeur et tripler la hauteur, nous ferions ce qui suit
myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0)
Remarques
La transformation de rotation fait pivoter le calque autour du point d'ancrage (le centre du calque par défaut). La syntaxe de base est
CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat)
où angle
est l'angle en radians que le calque doit faire pivoter et x
, y
et z
sont les axes autour desquels tourner. La définition d'un axe sur 0 annule une rotation autour de cet axe particulier.
Exemple
Si nous voulions faire pivoter un calque de 30 degrés dans le sens des aiguilles d'une montre, nous procéderions comme suit:
let degrees = 30.0
let radians = CGFloat(degrees * Double.pi / 180)
myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0)
Remarques
x
et y
sur 0.0
Et définissons z
sur 1.0
.z
sur -1.0
.Afin de combiner plusieurs transformations, nous pourrions utiliser la concatination comme celle-ci
CATransform3DConcat(a: CATransform3D, b: CATransform3D)
Cependant, nous ferons juste l'un après l'autre. La première transformation utilisera Make
dans son nom. Les transformations suivantes n'utiliseront pas Make
, mais elles prendront la transformation précédente comme paramètre.
Exemple
Cette fois, nous combinons les trois transformations précédentes.
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
Remarques
Nous avons fait toutes nos transformations ci-dessus sans changer le point d'ancrage. Parfois, il est toutefois nécessaire de le modifier, comme si vous souhaitez faire pivoter un autre point en plus du centre. Cependant, cela peut être un peu délicat.
Le point d'ancrage et la position sont tous deux au même endroit. Le point d'ancrage est exprimé sous la forme d'une unité du système de coordonnées de la couche (la valeur par défaut est 0.5, 0.5
) Et la position est exprimée dans le système de coordonnées de la super couche. Ils peuvent être définis comme ceci
myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
myLayer.position = CGPoint(x: 50, y: 50)
Si vous définissez uniquement le point d'ancrage sans modifier la position, le cadre change de sorte que la position soit au bon endroit. Ou plus précisément, le cadre est recalculé en fonction du nouveau point d'ancrage et de l'ancienne position. Cela donne généralement des résultats inattendus. Les deux articles suivants en ont une excellente discussion.