CGAffineTransform和CATransform3D基础使用

来源:互联网 发布:以色列巴勒斯坦知乎 编辑:程序博客网 时间:2024/06/05 07:46

原文:http://www.cnblogs.com/wfwenchao/articles/4844476.html

这里对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;}
0 0