CGAffineTransform和CATransform3D
这里对CGAffineTransform和CATransform3D的使用做个记录,比较简单的实现2D和3D的旋转,位移,缩放,锚点相关的有一些问题后续更新
CGAffineTransform是作用于View的主要为2D变换,而CATransform3D主要作用于Layer,为3D变换使用,这两种变换可以转换
CGAffineTransform
cgAffineTransform本身是一个仿射变换矩阵
1.矩阵的基本知识:
struct CGAffineTransform
{
CGFloat a, b, c, d;
CGFloat tx, ty;
};
CGAffineTransform CGAffineTransformMake( CGFloat a,CGFloat b,CGFloat c,CGFloat d,CGFloat tx,CGFloat ty);
为了把二维图形的变化统一在一个坐标系里,引入了齐次坐标的概念,即把一个图形用一个三维矩阵表示,其中第三列总是(0,0,1),用来作为坐标系的标准。 所以所有的变化都由前两列完成。
以上参数在矩阵中的表示为:
|a b 0|
|c d 0|
|tx ty 1|
运算原理:原坐标设为(X,Y,1);
|a b 0|
[X,Y, 1] |c d 0| = [aX + cY + tx bX + dY + ty 1] ;
| tx ty 1|
通过矩阵运算后的坐标[aX + cY + tx bX + dY + ty 1],我们对比一下可知:
第一种: 设a=d=1, b=c=0.
[aX + cY + tx bX + dY + ty 1] = [X + tx Y + ty 1];
可见,这个时候,坐标是按照向量(tx,ty)进行平移,其实这也就是函数
CGAffineTransform CGAffineMakeTranslation(CGFloat tx,CGFloat ty)的计算原理。
第二种: 设b=c=tx=ty=0.
[aX + cY + tx bX + dY + ty 1] = [aX dY 1];
可见,这个时候,坐标X按照a进行缩放,Y按照d进行缩放,a,d就是X,Y的比例系数,其实这也就是函数
CGAffineTransform CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)的计算原理。a对应于sx,d对应于sy。
第三种: 设tx=ty=0,a=cosɵ,b=sinɵ,c=-sinɵ,d=cosɵ。
[aX + cY + tx bX + dY + ty 1] = [Xcosɵ - Ysinɵ Xsinɵ + Ycosɵ 1] ;
可见,这个时候,ɵ就是旋转的角度,逆时针为正,顺时针为负。其实这也就是函数
CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle)的计算原理。angle即ɵ的弧度表示。
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
//旋转
- (IBAction)doRotate:(id)sender
{
// transformItem.transform = CGAffineTransformIdentity;
// transformItem.layer.anchorPoint = CGPointMake(1,0);
// transformItem.center = CGPointMake(CGRectGetWidth(transformItem.bounds), 0.0);
// transformItem.center = CGPointMake(transformItem.center.x-transformItem.frame.size.width*0.5, transformItem.center.y-transformItem.frame.size.height*0.5);
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
// transformItem.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-90));
transformItem.transform = CGAffineTransformRotate(transformItem.transform, DEGREES_TO_RADIANS(-90));
} completion:^(BOOL finished){
}];
}
//缩放
- (IBAction)doScale:(id)sender
{
CGAffineTransform tr = CGAffineTransformScale(transformItem.transform, 2, 2);
CGFloat h = transformItem.frame.size.height;
[transformItem.layer setAnchorPoint:CGPointMake(0, 1)];
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
// transformItem.transform = CGAffineTransformScale(transformItem.transform, 0.5, 0.5);
transformItem.transform = tr;
// transformItem.center = CGPointMake(0,h);
} completion:^(BOOL finished){
}];
}
//位移
- (IBAction)doTranslate:(id)sender
{
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
transformItem.transform = CGAffineTransformTranslate(transformItem.transform,100, 0);
} completion:^(BOOL finished){
}];
}
CATransform3D
CATransform3D也是个矩阵,多了一些切变和Z轴的值,这里通过CABasicAnimation来实现
#define ANIM_ROTATE @"animationRotate"
#define ANIM_FALLING @"animationFalling"
#define ANIM_GROUP @"animationFallingRotate"
- (IBAction)do3dRotate:(id)sender
{
CAAnimation* myAnimationRotate = [self animationRotate];
[transformItem.layer addAnimation:myAnimationRotate forKey:ANIM_ROTATE];
}
-(IBAction)do3dFalling:(id)sender
{
CAAnimation* myAnimationFalling = [self animationFallingDown];
[transformItem.layer addAnimation:myAnimationFalling forKey:ANIM_FALLING];
}
-(IBAction)do3dShrink:(id)sender
{
CAAnimation* myAnimationShrink = [self animationShrink];
[transformItem.layer setAnchorPoint:CGPointMake(1, 1)];
[transformItem.layer addAnimation:myAnimationShrink forKey:ANIM_FALLING];
}
//- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
//{
// //这边为什么是nil? :(
// NSLog(@"anim = %@", [m_pMyImageView.layer valueForKey:ANIM_GROUP]);
//#if 1
// //识别动画
// //?debug发现两者的地址不一样,这个问题很纠结
// if ([anim isEqual:m_pGroupAnimation])//[m_pMyImageView.layer valueForKey:ANIM_GROUP])
// {
// NSLog(@"removeFromSuperview...");
// [m_pMyImageView removeFromSuperview];
// [m_pMyImageView release];
//
// }
//#else
// //这种方法,虽然能解决方法,但是处理多个CAAnimationGroup动画或者CAAnimation动画时,就不能有效处理,方法待定
// //这组动画结束,移除视图
// if ([anim isKindOfClass:[CAAnimationGroup class]])
// {
// //这边为什么是nil? :(
// NSLog(@"anim = %@", [m_pMyImageView.layer valueForKey:ANIM_GROUP]);
//
// [m_pMyImageView removeFromSuperview];
// [m_pMyImageView release];
//
// }
//#endif
//}
- (CAAnimation *)animationShrink
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.toValue = [NSNumber numberWithDouble:2.0];
animation.duration = 3.0;
animation.autoreverses = YES;
animation.repeatCount = FLT_MAX; //"forever"
animation.removedOnCompletion = NO;
//设置动画代理
animation.delegate = self;
return animation;
}
- (CAAnimation *)animationFallingDown
{
//falling down animation:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
animation.duration = 5.0;
animation.autoreverses = NO;
animation.removedOnCompletion = NO;
animation.repeatCount = FLT_MAX; //"forever"
animation.fromValue = [NSNumber numberWithInt: 0];
animation.toValue = [NSNumber numberWithInt: 1024];
//设置动画代理
animation.delegate = self;
return animation;
}
- (CAAnimation *)animationRotate
{
// rotate animation
CATransform3D rotationTransform = CATransform3DMakeRotation(M_PI, 0, 1.0, 0.0);
CABasicAnimation* animation;
animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:rotationTransform];
animation.duration = 1.5;
animation.autoreverses = NO;
animation.cumulative = YES;
animation.repeatCount = FLT_MAX; //"forever"
//设置开始时间,能够连续播放多组动画
animation.beginTime = 0.5;
//设置动画代理
animation.delegate = self;
return animation;
}