美文网首页Reports
CATransform3D笔记

CATransform3D笔记

作者: HuangJn | 来源:发表于2016-08-15 13:45 被阅读302次

    CATransform3D是一个结构体

    struct CATransform3D{  
      CGFloat     m11(x缩放),   m12(y切变),   m13(旋转),   m14();
      CGFloat     m21(x切变),   m22(y缩放),   m23,        m24;
      CGFloat     m31(旋转),    m32,         m33,         m34(透视效果,要有旋转角度才能看出效果);
      CGFloat     m41(x平移),   m42(y平移),   m43(z平移),  m44;
    };
    

    github上有个demo可以直接更改m11~m44的值,直观的看到效果

    红色的点就是锚点(anchorPoint)的位置:默认为(0.5,0.5)。在对图像进行变换时,都是围绕这个点来进行缩放,偏移等。

    timeline.gif
    • CATransform3DIdentity
      CATransform3DIdentity是单位矩阵,该矩阵没有缩放、旋转、歪斜、透视。把该矩阵应用到图层上面,会把图层几何属性修改为默认值。
      可以用CATransform3DIsIdentity方法判断是否为单位矩阵。
      bool CATransform3DIsIdentity ( CATransform3D t );

    平移变换(Translation)

    //返回一个平移变换的transform3D对象 tx,ty,tz对应x,y,z轴的平移
    CATransform3D CATransform3DMakeTranslation ( CGFloat tx, CGFloat ty, CGFloat tz ); 
    //在某个transform3D变换的基础上进行平移变换,t是上一个transform3D,其他参数同上
    CATransform3D CATransform3DTranslate ( CATransform3D t, CGFloat tx, CGFloat ty, CGFloat tz );
    
    F086A392-C96F-4473-B1EB-53EF6B37700D.png
     // 左边是初始状态,右边是经过下列代码处理后的结果
    CATransform3D transform3D = CATransform3DMakeTranslation(100, 100, 10);
    self.translateCatImgView.layer.transform = transform3D;
    
    • tx:X轴偏移位置,往下为正数。
      ty:Y轴偏移位置,往右为正数。
      tz:Z轴偏移位置,往外为正数。对于tz来说,值越大,那么图层就越往外(接近屏幕),值越小,图层越往里(屏幕里)

    缩放变换(Scale)

     //x,y,z分别对应x轴,y轴,z轴的缩放比例
    CATransform3D CATransform3DMakeScale ( CGFloat sx, CGFloat sy, CGFloat sz );
    //在一个transform3D变换的基础上进行缩放变换,其他参数同上
    CATransform3D CATransform3DScale ( CATransform3D t, CGFloat sx, CGFloat sy, CGFloat sz );
    
    6162FB6E-35F5-4316-885E-8B78F3C95545.png
    CATransform3D transform3D = CATransform3DMakeScale(0.5, 0.5, 0);
    self.scaleCatImgView.layer.transform = transform3D;
    

    旋转变换(Rotation)

    /*angle参数是旋转的角度,为弧度制 0-2π
      x,y,z决定了旋转围绕的中轴,取值为-1——1之间*/
    CATransform3D CATransform3DMakeRotation ( CGFloat angle, CGFloat x, CGFloat y, CGFloat z );
    CATransform3D CATransform3DRotate ( CATransform3D t, CGFloat angle, CGFloat x, CGFloat y, CGFloat z );
    
    C3F3D5B0-51B9-4A2E-9128-B4008F658BB9.png
    CATransform3D xRotation = CATransform3DMakeRotation(45*M_PI/180.0, 1.0, 0, 0);
    
    CATransform3D yRotation = CATransform3DIdentity;
    CGFloat zDistance = 1000;
    yRotation.m34 = - 1.0 / zDistance;// (-1.0 / zDistance),zDistance越小,透视效果越明显  必须先设置m34再设置旋转角度
    yRotation = CATransform3DRotate(yRotation,-30*M_PI/180.0, 0.0, 1.0, 0);
    
    CATransform3D xYRotation = CATransform3DConcat(xRotation, yRotation);//合并xRotation, yRotation
    self.rotationCatImgView.layer.transform = xYRotation;
    

    旋转的单位采用弧度(radians) [0-2π],而不是角度(degress)。以下两个函数,你可以在弧度和角度之间切换。

    CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
    CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180 / M_PI;};
    
    • 按我的理解说下X,Y,Z 取值大于0的旋转效果,小于0即反过来
      X:视图的上边沿往屏幕里靠拢旋转
      Y:视图的右边沿往屏幕里靠拢旋转
      Z:视图平面顺时针旋转

    合并两个CATransform3D(CATransform3DConcat)

    CATransform3D CATransform3DConcat ( CATransform3D a, CATransform3D b );
    

    CATransform3DInvert效果反转(反效果,比如原来扩大,就变成缩小)

    CATransform3D CATransform3DInvert ( CATransform3D t );
    

    CATransform3D与CGAffineTransform的转换

    //将一个CGAffinrTransform转化为CATransform3D
    CATransform3D CATransform3DMakeAffineTransform (CGAffineTransform m);
    //判断一个CATransform3D是否可以转换为CAAffineTransform
    bool CATransform3DIsAffine (CATransform3D t);
    //将CATransform3D转换为CGAffineTransform
    CGAffineTransform CATransform3DGetAffineTransform (CATransform3D t);
    
    • CGAffineTransform(仿射变换)是作用于UIViews的2D操作,而CATransform3D是作用于CALayers的更复杂的3D操作,
      struct CGAffineTransform {
      CGFloat a, b, c, d;
      CGFloat tx, ty;
      };
      CGAffineTransform CGAffineTransformMake(CGFloat a, CGFloat b,CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)

       /*各个参数的定义可以理解成
         sx,sy:缩放因子
         shx,shy:斜切因子
         tx,ty:移动因子
         CGAffineTransformMake (sx,shx,shy,sy,tx,ty)
       */
      

    到这斜切的概念还没搞清楚,具体看iOS动画和特效(七)仿射变换-CGAffineTransform,里面有详解,CGAffineTransform其他方法与CATransform3D基本类似


    通过键值路径修改变换

    核心动画扩展了键-值编码协议,允许通过关键路径获取和设置一个图层的CATransform3D矩阵的值。表4描述了图层的transform和sublayerTransform属性的相应关键路径。

    CDD718FD-F229-4A60-8DA0-97D8AB387660.png
    [myLayer setValue:[NSNumber numberWithInt:0] forKeyPath:@"transform.rotation.x"];
    

    结合上述基础做个动画

    hebao.gif

    写了个Demo模仿荷包App的启动动画
    里面用了三种方法实现 1.改变frame 2.改变transform3.用动画库JHChainableAnimations
    还涉及到frame,position,anchorPoint的关系,这篇文章容易理解些

    参考文章

    CATransform3D 特效详解
    CoreAnimation编程指南(三)几何变换
    iOS开发CoreAnimation解读之六——CATransform3D变换的应用
    iOS动画和特效(七)仿射变换-CGAffineTransform

    相关文章

      网友评论

      • Micro同学:大神求问一个问题。。。以下是对一个立方体的拖拽动作:
        - (void)panOnView: (UIPanGestureRecognizer *)pan {
        NSLog(@"Panned!!!");
        if (self.animationHappening) {
        return;
        }


        CATransform3D transform = CATransform3DIdentity;
        transform.m34 = -1.0/2000;
        CGPoint translation = [pan translationInView:self.mView];
        // CATransform3D transform = MakePerspetiveTransform();
        transform = CATransform3DRotate(transform, kPanScale * translation.x, 0, 1, 0);
        transform = CATransform3DRotate(transform, -kPanScale * translation.y, 1, 0, 0);

        [UIView animateWithDuration:0
        animations:^{
        // self.mainLayer.transform = transform;
        self.mView.layer.sublayerTransform = transform;
        // self.lastScale = pinch.scale;
        } completion:^(BOOL finished) {
        self.animationHappening = NO;
        }];
        }

        但是每次再触发的时候他会复位。。请问如何能够在前一次的情况下再继续呢?谢谢!!!

      本文标题:CATransform3D笔记

      本文链接:https://www.haomeiwen.com/subject/anrssttx.html