CATransformLayer
发布日期:2022-03-18 08:27:36 浏览次数:49 分类:技术文章

本文共 5005 字,大约阅读时间需要 16 分钟。

关于CATransformLayer的介绍请参考。

中有介绍WORK WITH CATRANSFORMLAYER,大致的翻译下:

坦白的讲,CALayer并不是3D层级的root的合适选择。函数E_multiplePlanesZAxis将会告诉我们为什么会是这样。

在这个场景中,我们在相同的X,Y坐标系中创建4个平面(plane),但是却对应有不同的Z坐标。
purplePlane是最靠近你的view,而YellowPlane是最远的。

//给planes应用变换t = CATransform3DIdentity;t = CATransform3DTranslate(t, 0, 0, -10);purplePlane.transform = t;t = CATransform3DIdentity;t = CATransform3DTranslate(t, 0, 0, -50);redPlane.transform = t;t = CATransform3DIdentity;t = CATransform3DTranslate(t, 0, 0, -90);orangePlane.transform = t;t = CATransform3DIdentity;t = CATransform3DTranslate(t, 0, 0, -130);yellowPlane.transform = t;

在创建这些planes之前,给container 应用一个rotation变换(这里的container是一个CALayer)。

//给container应用变化CATransform3D t = CATransform3DIdentity;t.m34 = 1.0/-500;t = CATransform3DRotate(t, 80.0f * M_PI / 180.0f, 0, 1, 0);container.transform = t;

你期望的结果可能是这样的:

这里写图片描述

但最终的结果却是这样的:

这里写图片描述

这是因为CALayer不能够管理3D层级的深度,它只是flattens the scene to a single Z level.

为了修正这个问题,获得正确的结果,要选择CATransformLayers作为root object。

在函数F_multiplePlanesZAxis中修改这个问题:

//Create the container as a CATransformLayerCATransformLayer *container = [CATransformLayer layer];container.frame = CGRectMake(0, 0, 640, 300);[self.view.layer addSublayer:container];

CATransformLayer是一个特殊的layer。与CALayers不同的是,只有它的子layer才会被渲染,其它的属性,比如backgroundColor、contents、border等等,都会被忽略。

[Core Animation中的3D绘画介绍(第二部分)]()

在这个教程中,创建一个类似旋转木马类似的场景,可以通过拖动手势来交互。效果如下:

这里写图片描述


We go 3D!

为了创建carousel,我们需要创建3D层级,使用CATransformLayer作为层级的root是个好方法。

The planes平面

Carousel由一系列平面组成。我们使用CAGradientLayer来描述这些对象,它是CALayer的子类,让我们可以使用渐变的颜色来定义背景颜色。
plane需要移动和旋转来围成一个圆形。

手势

使用了一个手势,来追踪用户的的动作,把手势的数据转为角度值,来执行carousel的旋转。

LET’S CODE!


打开ViewController.m,从viewDidLoad:函数开始:

- (void)viewDidLoad{    [super viewDidLoad];    //初始化TransformLayer    transformLayer = [CATransformLayer layer];    transformLayer.frame = self.view.bounds;    [self.view.layer addSublayer:transformLayer];    angle = 0;    XPanOffset = 0;    //创建5个planes    [self addPlane];    [self addPlane];    [self addPlane];    [self addPlane];    [self addPlane];    //强制开始第一个动画,来设置plane的位置    [self animate];    //初始化拖动手势    UIPanGestureRecognizer *panGesture =  [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];    [self.view addGestureRecognizer:panGesture];   }

绘制Planes

addPlane函数是很简单明了的。它创建CAGradientLayer,并把它作为transformLayer的sublayer。

/**创建一个CAGradientLayer**/-(void)addPlane{    CGSize planeSize = CGSizeMake(250, 150);    //初始化图层    CAGradientLayer *layer = [CAGradientLayer layer];    //设置frame和锚点    layer.frame = CGRectMake(480/2 - planeSize.width/2, 320/2 - planeSize.height/2 -20, planeSize.width, planeSize.height);    layer.anchorPoint = CGPointMake(0.5, 0.5);    //设计边框和圆角    layer.borderColor = [[UIColor colorWithWhite:1.0 alpha:0.3]CGColor];    layer.cornerRadius = 10;    layer.borderWidth = 4;    //设置渐变的颜色    layer.colors = [NSArray arrayWithObjects:                    (id)[UIColor purpleColor].CGColor,                    (id)[UIColor redColor].CGColor,                    nil];    layer.locations = [NSArray arrayWithObjects:                       [NSNumber numberWithFloat:0.0f],                       [NSNumber numberWithFloat:1.0f],                       nil];    //设置阴影    layer.shadowColor = [[UIColor blackColor]CGColor];    layer.shadowOpacity = 1;    layer.shadowRadius = 20;    //doubleSided设为yes,如果想在face被转过去的时候能被看见    layer.doubleSided = YES;    //添加到transformLayer上    [transformLayer addSublayer:layer];}

这里写图片描述

定位Planes POSITIONING THE PLANES


在plane被创建后,在viewDidLoad方法中,我们调用了animate

这个方法的主要功能是更新Plane的位置。在我们第一次调用animate时,触摸事件并没有发生。

/** This function performs the transformation on each plane **/-(void)animate{    //每个plane对应的角度    float degForPlane = 360 / [[transformLayer sublayers] count];    //当前角度的偏移量    float degX = angle;    for (CALayer *layer in [transformLayer sublayers]) {        //Create the Matrix identity        CATransform3D t = CATransform3DIdentity;        //Setup the perspective modifying the matrix elementat [3][4]        t.m34 = 1.0f / - 1000.0f;        //旋转        t = CATransform3DRotate(t, degToRad(degX), 0.0f, 1.0f, 0.0f);        //移动        t = CATransform3DTranslate(t, 0.0f, 0.0f,  250.0f);        //禁止动画        [CATransaction setAnimationDuration:0.0];        //在当前的layer上执行动画        layer.transform = t;        //Add the degree needed for the next plane        degX += degForPlane;    }}

defForPlane变量是每一个plane要在先前的plane上旋转的角度值,来形成一个360的圈。用图片解释如下:

这里写图片描述

如果仅仅是添加了旋转,结果是这样的:

这里写图片描述

拖动手势

-(void)pan:(UIPanGestureRecognizer*)gesture{    //获取x方向上的位移    float xOffset = [gesture translationInView:self.view].x;    //在手势开始的时候,offset重置为0    if(gesture.state == UIGestureRecognizerStateBegan){        XPanOffset = 0;    }    //the distance covered since the last gesture event (I slow down a bit the final rotation multiplying by 0.5)    float movedBy = xOffset * 0.5 - XPanOffset;    //Calculate the offset from the previous gesture event    XPanOffset += movedBy;    //Add the offset to the current angle    angle += movedBy;    //Update the plane    [self animate];}

转载地址:https://windzen.blog.csdn.net/article/details/49361565 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:iOS开源项目学习——开源中国iOS客户端
下一篇:CAReplicatorLayer

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年03月11日 01时13分11秒