本文共 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绘画介绍(第二部分)]()
在这个教程中,创建一个类似旋转木马类似的场景,可以通过拖动手势来交互。效果如下:
THE CAROUSEL –概述
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
。
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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!