-
1、单一形变
// 旋转
/*
(CGFloat angle) 旋转 45 度,需要输入的参数为弧度,45/180 * M_PI,1 度 = PI/180 弧度
*/
[UIView animateWithDuration:1 animations:^{
self.redView.transform = CGAffineTransformMakeRotation(0.25 * M_PI);
}];
// 缩放
/*
(CGFloat sx, CGFloat sy) (1, 2) 宽度和高度的放大倍数
*/
[UIView animateWithDuration:1 animations:^{
self.redView.transform = CGAffineTransformMakeScale(1, 2);
}];
// 平移
/*
(CGFloat tx, CGFloat ty) (100, 100) 水平和垂直方向的移动距离
*/
[UIView animateWithDuration:1 animations:^{
self.redView.transform = CGAffineTransformMakeTranslation(100, 100);
}];
-
2、 叠加形变
// 旋转 + 缩放
[UIView animateWithDuration:1 animations:^{
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(0.25 * M_PI);
self.redView.transform = CGAffineTransformScale(rotationTransform, 1.5, 1.5);
}];
// 旋转 + 平移
[UIView animateWithDuration:1 animations:^{
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(0.25 * M_PI);
self.redView.transform = CGAffineTransformTranslate(rotationTransform, 100, 0);
}];
// 缩放 + 平移
[UIView animateWithDuration:1 animations:^{
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1, 1.5);
self.redView.transform = CGAffineTransformTranslate(scaleTransform, 100, 0);
}];
// 旋转 + 缩放 + 平移
[UIView animateWithDuration:1 animations:^{
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(0.25 * M_PI);
CGAffineTransform rotationScaleTransform = CGAffineTransformScale(rotationTransform, 1.5, 1.5);
self.redView.transform = CGAffineTransformTranslate(rotationScaleTransform, 100, 0);
}];
-
3、累加形变
// 连续旋转
[UIView animateWithDuration:1 animations:^{
self.redView.transform = CGAffineTransformRotate(self.redView.transform, 0.25 * M_PI);
}];
// 连续缩放
[UIView animateWithDuration:1 animations:^{
self.redView.transform = CGAffineTransformScale(self.redView.transform, 1.5, 1.5);
}];
// 连续平移
[UIView animateWithDuration:1 animations:^{
self.redView.transform = CGAffineTransformTranslate(self.redView.transform, 50, 50);
}];
-
4、还原形变
// 还原所有形变
self.redView.transform = CGAffineTransformIdentity;
-
1、单一形变
// 旋转
/*
(CGFloat angle) 旋转 45 度,需要输入的参数为弧度,45/180 * M_PI,1 度 = PI/180 弧度
*/
[UIView animateWithDuration:1 animations:^{
self.redView.layer.affineTransform = CGAffineTransformMakeRotation(0.25 * M_PI);
}];
// 缩放
/*
(CGFloat sx, CGFloat sy) (1, 2) 宽度和高度的放大倍数
*/
[UIView animateWithDuration:1 animations:^{
self.redView.layer.affineTransform = CGAffineTransformMakeScale(1, 2);
}];
// 平移
/*
(CGFloat tx, CGFloat ty) (100, 100) 水平和垂直方向的移动距离
*/
[UIView animateWithDuration:1 animations:^{
self.redView.layer.affineTransform = CGAffineTransformMakeTranslation(100, 100);
}];
// 还原所有形变
self.redView.layer.affineTransform = CGAffineTransformIdentity;
-
2、快速进行绘图层形变,KVC
// 旋转
[UIView animateWithDuration:1 animations:^{
[self.redView.layer setValue:@(0.25 * M_PI) forKeyPath:@"transform.rotation"];
}];
// 缩放
[UIView animateWithDuration:1 animations:^{
[self.redView.layer setValue:@1.5 forKeyPath:@"transform.scale"];
}];
-
效果
![animation3]()
![animation65]()
-
3、绘图层 3D 形变
// 旋转
/*
(CGFloat angle, CGFloat x, CGFloat y, CGFloat z) 旋转角度,x y z 轴的坐标,为 0 时在此轴上不旋转
*/
[UIView animateWithDuration:1 animations:^{
self.imageView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
}];
// 缩放
/*
(CGFloat sx, CGFloat sy, CGFloat sz),x y z 轴的缩放倍数
*/
[UIView animateWithDuration:1 animations:^{
self.imageView.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1);
}];
// 平移
/*
(CGFloat tx, CGFloat ty, CGFloat tz),x y z 轴的平移量
*/
[UIView animateWithDuration:1 animations:^{
self.imageView.layer.transform = CATransform3DMakeTranslation(100, 100, 0);
}];
在前面已经提到,每一个 UIView 内部都默认关联着一个 CALayer,我们可称这个 Layer 为 Root Layer(根层)。所有的非 Root Layer,也就是手动创建的 CALayer 对象,都存在着隐式动画。
-
当对非 Root Layer 的部分属性进行相应的修改时,默认会自动产生一些动画效果,这些属性称为 Animatable Properties 可动画属性。
![animation38]()
![animation39]()
![animation40]()
![animation41]()
![animation37]()
-
列举几个常见的 Animatable Properties:
bounds :用于设置 CALayer 的宽度和高度。修改这个属性会产生缩放动画。
backgroundColor :用于设置 CALayer 的背景色。修改这个属性会产生背景色的渐变动画。
position :用于设置 CALayer 的位置。修改这个属性会产生平移动画。比如:假设
一开始 CALayer 的 position 为(100, 100),然后在某个时刻修改为
(200, 200),那么整个 CALayer 就会在短时间内从 (100, 100) 这个
位置平移到 (200, 200)
-
1、隐式动画属性设置
self.myLayer.bounds = CGRectMake(0, 0, 100, 100);
self.myLayer.backgroundColor = [UIColor greenColor].CGColor;
self.myLayer.position = CGPointMake(arc4random_uniform(200) + 20, arc4random_uniform(400) + 50);
self.myLayer.transform = CATransform3DMakeRotation(arc4random_uniform(360), 0, 0, 1);
-
2、可以通过动画事务(CATransaction)关闭默认的隐式动画效果。
[CATransaction begin];
[CATransaction setDisableActions:YES];
self.myLayer.position = CGPointMake(10, 10);
[CATransaction commit];
创建一个 CALayer 的子类,然后覆盖 drawInContext: 方法,使用 Quartz2D API 进行绘图。
-
QCLayer.h
@interface QCLayer : CALayer
@end
-
QCLayer.m
@implementation QCLayer
#pragma mark 绘制一个实心三角形
- (void)drawInContext:(CGContextRef)ctx {
// 设置为蓝色
CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);
// 设置起点
CGContextMoveToPoint(ctx, 50, 0);
// 从 (50, 0) 连线到 (0, 100)
CGContextAddLineToPoint(ctx, 0, 100);
// 从 (0, 100) 连线到 (100, 100)
CGContextAddLineToPoint(ctx, 100, 100);
// 合并路径,连接起点和终点
CGContextClosePath(ctx);
// 绘制路径
CGContextFillPath(ctx);
}
@end
-
ViewController.m
QCLayer *layer = [QCLayer layer];
// 设置层的宽高
layer.bounds = CGRectMake(0, 0, 100, 100);
// 设置层的位置
layer.position = CGPointMake(100, 100);
// 开始绘制图层,需要调用这个方法,才会触发 drawInContext: 方法的调用,然后进行绘图
[layer setNeedsDisplay];
[self.view.layer addSublayer:layer];
-
效果
![animation27]()
- 设置 CALayer 的 delegate,然后让 delegate 实现 drawLayer:inContext: 方法,当 CALayer 需要绘图时,会调用 delegate 的 drawLayer:inContext: 方法进行绘图。
-
这里要注意的是:不能再将某个 UIView 设置为 CALayer 的 delegate,因为 UIView 对象已经是它内部根层的 delegate,再次设置为其他层的 delegate 就会出问题。UIView 和它内部 CALayer 的默认关系图:
![animation28]()
-
创建新的层,设置 delegate,然后添加到控制器的 view 的 layer 中。
CALayer *layer = [CALayer layer];
// 设置 delegate,这里的 self 是指控制器
layer.delegate = self;
// 设置层的宽高
layer.bounds = CGRectMake(0, 0, 100, 100);
// 设置层的位置
layer.position = CGPointMake(100, 100);
// 开始绘制图层,需要调用这个方法,才会通知 delegate 进行绘图
[layer setNeedsDisplay];
[self.view.layer addSublayer:layer];
-
让 CALayer 的 delegate(前面设置的是控制器)实现 drawLayer:inContext: 方法
#pragma mark 画一个矩形框
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
// 设置蓝色
CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
// 设置边框宽度
CGContextSetLineWidth(ctx, 10);
// 添加一个跟层一样大的矩形到路径中
CGContextAddRect(ctx, layer.bounds);
// 绘制路径
CGContextStrokePath(ctx);
}
-
效果
![animation29]()