如何在CALayer上进行转换?
在写这个问题之前,我已经
- 有Affine转换观点的经验
- 阅读Quartz 2D Programming Guide中的Transforms文档
- 看到这个详细的CALayer教程
- 从Github下载并运行LayerPlayer项目
不过,我仍然无法理解如何在图层上进行基本的变换。 寻找翻译,旋转和缩放的解释和简单的例子已经很困难。
今天,我终于决定坐下来,做一个testing项目,并把它们弄清楚。 我的答案在下面。
笔记:
- 我只做Swift,但如果别人想要添加Objective-C代码,请成为我的客人。
- 在这一点上,我只关心理解二维变换。
基本
在图层上可以进行多种不同的转换,但基本的转换是
- 翻译(移动)
- 规模
- 回转
要在CALayer
上进行转换,可以将图层的transform
属性设置为CATransform3D
types。 例如,要翻译一个图层,你可以这样做:
myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)
Make
这个词用于创build初始转换的名称:CATransform3D Make Translation。 随后应用的转换省略了Make
。 例如,请看这个旋转,然后翻译:
let rotation = CATransform3DMakeRotation(CGFloat.pi * 30.0 / 180.0, 20, 20, 0) myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)
现在我们已经有了如何进行转换的基础,接下来我们来看看如何进行转换的一些例子。 但是,首先,我将展示如何设置该项目,以防止您想要使用它。
build立
对于下面的例子,我设置了一个单一的视图应用程序,并添加了一个淡蓝色背景的UIView
到故事板。 我用以下代码将视图连接到视图控制器:
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 ... } }
CALayer
有很多不同的types ,但是我select了使用CATextLayer
以便视觉更清晰。
翻译
翻译变换移动图层。 基本的语法是
CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat)
其中tx
是x坐标的变化, ty
是y的变化, tz
是z的变化。
例
在iOS中,坐标系的原点位于左上方,所以如果我们想要将图层90点向右移动50点,我们将执行以下操作:
myLayer.transform = CATransform3DMakeTranslation(90, 50, 0)
笔记
- 请记住,您可以将其粘贴到上述项目代码中的
transformExample()
方法中。 - 既然我们要在这里处理两个维度,
tz
被设置为0
。 - 上图中的红线从原始位置的中心到新位置的中心。 这是因为转换是相对于锚点完成的,并且默认情况下锚点位于图层的中心。
规模
缩放变换拉伸或挤压图层。 基本的语法是
CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat)
其中sx
, sy
和sz
分别是对x,y和z坐标进行缩放(乘)的数字。
例
如果我们想要宽度的一半和高度的三倍,我们会做以下的事情
myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0)
笔记
- 由于我们只是在两个维度上工作,所以我们只需将z坐标乘以1.0就可以不受影响。
- 上图中的红点表示锚点。 请注意缩放是如何与锚点相关的。 也就是说,一切都要么拉向或远离定位点。
旋转
旋转变换旋转锚点周围的图层(默认为图层的中心)。 基本的语法是
CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat)
其中angle
是以弧度表示的层应该旋转的angular度,而x
, y
和z
是围绕其旋转的轴。 将坐标轴设置为0将取消围绕该特定坐标轴的旋转。
例
如果我们想要顺时针旋转一层30度,我们可以这样做:
let degrees = 30.0 let radians = CGFloat(degrees * Double.pi / 180) myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0)
笔记
- 由于我们在两个维度上工作,我们只希望xy平面围绕z轴旋转。 因此,我们将
x
和y
设置为0.0
,并将z
设置为1.0
。 - 这顺时针方向旋转该层。 我们可以通过将
z
设置为-1.0
来逆时针旋转。 - 红点显示了锚点的位置。 旋转是在锚点周围完成的。
多重转换
为了组合多个转换,我们可以像这样使用连接
CATransform3DConcat(a: CATransform3D, b: CATransform3D)
但是,我们只会一个接一个地做。 第一个转换将使用Make
作为其名称。 下面的转换不会使用Make
,但是它们会将之前的转换作为参数。
例
这一次,我们结合了以前所有的三个转换。
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
笔记
- 事情的转换完成的顺序。
- 一切都是根据锚点(红点)完成的。
关于锚点和位置的一个注记
我们在不改变锚点的情况下完成了上面的所有转换。 有时候有必要改变它,但是,如果你想围绕除了中心之外的其他点旋转。 但是,这可能有点棘手。
定位点和位置都在同一个地方。 锚点表示为图层坐标系统的单位(默认值为0.5,0.5),位置表示在上层坐标系统中。 他们可以像这样设置
myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0) myLayer.position = CGPoint(x: 50, y: 50)
如果您只在不改变位置的情况下设置定位点,则框架会发生变化,以使位置位于正确的位置。 或者更确切地说,基于新的锚点和旧的位置重新计算框架。 这通常会带来意想不到的结 以下两篇文章有很好的讨论。
- 关于anchorPoint
- 翻译旋转翻译?
也可以看看
- 边框,圆angular和
CALayer
上的阴影 - 使用具有贝塞尔path的边框作为图层
- 如何使用UICollectionViewTransitionLayout插入自定义的UICollectionViewLayoutAttributes属性
- 如何在Swift中应用多个转换
- iOS – 这个UIPageViewController由UISegmentedControl控制,或者这是什么?
- CGAffineTransform缩放和平移 – 在animation之前跳转
- iOS:有关GLKMatrix4MakeLookAt结果内相机信息的问题
- ios ipad:在横向模式下将TabBar旋转到左侧,并进行变换和约束更新
- 如何将UIView的右上angular90度旋转/旋转?
- iOS AssistiveTouch使用自定义键盘时animation较慢
- “魔术移动”效果自定义转换