CoreGraphics框架下的CGAffineTransform结构体,可以实现对视图或图层的旋转、缩放、平移及组合变换。
实现原理
public struct CGAffineTransform {
public var a: CGFloat
public var b: CGFloat
public var c: CGFloat
public var d: CGFloat
public var tx: CGFloat
public var ty: CGFloat
public init()
public init(a: CGFloat, b: CGFloat, c: CGFloat, d: CGFloat, tx: CGFloat, ty: CGFloat)
}
复制代码
可以看到CGAffineTransform是一个结构体,它会被组装成如下矩阵
x' = ax+cy+tx
y' = bx+dy+ty
1. 平移
平移初始化方法如下
/* Return a transform which translates by `(tx, ty)':
t' = [ 1 0 0 1 tx ty ] */
public init(translationX tx: CGFloat, y ty: CGFloat)
复制代码
经过坐标变换,可以得到 x' = x+tx y' = y+ty
平移看起来非常简单,tx为正值则向x轴正向平移,反之向负向平移,ty值同理(x轴向右为正向,y轴向下为正向)
2. 缩放
缩放初始化方法如下
/* Return a transform which scales by `(sx, sy)':
t' = [ sx 0 0 sy 0 0 ] */
public init(scaleX sx: CGFloat, y sy: CGFloat)
复制代码
经过坐标变换,可以得到 x' = x*sx y' = y*sy
根据传入sx, sy进行缩放,传入负值可进行水平或垂直镜像
3. 旋转
旋转初始化方法如下
/* Return a transform which rotates by `angle' radians:
t' = [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] */
public init(rotationAngle angle: CGFloat)
复制代码
这里入参是一个弧度值,角度x转换为弧度angle = x*Double.pi/180
旋转是绕着视图中心点进行,angle为正值则视图绕着中心点顺时针旋转
下面推导一下这个变换矩阵
x=rcosϕ, y=rsinϕ
x′=rcos(θ+ϕ), y′=rsin(θ+ϕ)
通过三角函数展开得到
x′=rcosθcosϕ−rsinθsinϕ
y′=rsinθcosϕ+rcosθsinϕ
带入x和y表达式得到
x′=xcosθ−ysinθ
y′=xsinθ+ycosθ
写成矩阵的形式即:
Demo
我们用一个ImageView来演示一下
1. 平移
jfImageView.transform = CGAffineTransform(translationX: 50, y: -50)
复制代码
2. 缩放
jfImageView.transform = CGAffineTransform(scaleX: 2, y: 2)
复制代码
3. 旋转
jfImageView.transform = CGAffineTransform(rotationAngle: -.pi/4)
复制代码
4. 组合变换(重点展开说明)
- 先逆时针旋转45度,再放大两倍。
jfImageView.transform = CGAffineTransform(rotationAngle: -.pi/4).scaledBy(x: 2, y: 2)
复制代码
- 先逆时针旋转45度,再放大两倍,再沿x轴正向移动50,y轴负向移动50。
jfImageView.transform = CGAffineTransform(rotationAngle: -.pi/4).scaledBy(x: 2, y: 2).translatedBy(x: 50, y: -50)
复制代码
- 先逆时针旋转45度,再沿x轴正向移动50,y轴负向移动50,再放大两倍。
jfImageView.transform = CGAffineTransform(rotationAngle: -.pi/4).translatedBy(x: 50, y: -50).scaledBy(x: 2, y: 2)
复制代码
后面两种组合变换得到的结果是不一样的 先来看三种变换后的视图frame(4英寸屏幕大小下)
当对图层做变换的时候,比如旋转或者缩放,frame实际上代表了覆盖在图层旋转之后的整个轴对齐的矩形区域,也就是说frame的宽高可能和bounds的宽高不再一致了,就如我们的图片一样,frame = {6.56, 130.56, 306.88, 306.88},bounds = {0, 0, 128, 89}
组合变换2的translatedBy(x: 50, y: -50)被逆时针旋转了45度,放大了两倍,因此竖直向上移动了100√2≈141.42
组合变换3的translatedBy(x: 50, y: -50)只是被逆时针旋转了45度,因此竖直向上移动了50√2≈70.71
复制代码
参考资料:
《iOS Core Animation》
本文详细介绍了CoreGraphics框架下的CGAffineTransform结构体,包括平移、缩放、旋转和组合变换的实现原理,并通过实例演示了如何使用CGAffineTransform进行视图变换。
9820

被折叠的 条评论
为什么被折叠?



