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;

}

results matching ""

    No results matching ""