先看下效果图:
(备注: 上面GIF 是Mac 下录制视频的并转化成gif 的而成,工具为GIF Brewery 3 【这款软件挺不错的】)
那么主题来了如何实现上面效果呢?
1、创建自定义CALayer子类
KBSpinnyMcSpinface
构造函数如下:
-(instancetype)initWithNumberOfItems:(NSUInteger)number { if (self = [self init]) { self.masksToBounds = NO; self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.height); for (NSUInteger index = 0; index < number; index++) { //创建子layer CALayer *layer = [self generLayerWithSize:CGSizeMake(100, 100) index:index]; [self insertSublayer:layer atIndex:0];
//每个子类设置不同的层级(z坐标) [self setZPosition:(CGFloat)index forLayer:layer]; } } return self; }
创建子类cugangenerLayerWithSize方法如下:
-(CAShapeLayer*)generLayerWithSize:(CGSize)size index:(NSInteger)index { CAShapeLayer *square = [CAShapeLayer layer]; square.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, size.width, size.height) cornerRadius:size.width/4 ].CGPath; square.bounds = CGPathGetBoundingBox(square.path); square.fillColor = [self randColor].CGColor;//我这里设置了随时颜色 square.position = CGPointMake(150,200); [self setAnchorPoint:CGPointMake(0.5, 0.5) forLayer:square];//设置锚点坐标 return square; }
指定的CALayer设置锚点坐标方法如下
// Because adjusting the anchorPoint itself adjusts the frame, this is needed to avoid it, and keep the layer stationary. -(void)setAnchorPoint:(CGPoint)anchorPoint forLayer:(CALayer*)layer { CGPoint newPoint = CGPointMake(layer.bounds.size.width * anchorPoint.x, layer.bounds.size.height * anchorPoint.y); CGPoint oldPoint = CGPointMake(layer.bounds.size.width * layer.anchorPoint.x, layer.bounds.size.height * layer.anchorPoint.y); CGPoint position = layer.position; position.x -= oldPoint.x; position.x += newPoint.x; position.y -= oldPoint.y; position.y += newPoint.y; layer.position = position; layer.anchorPoint = anchorPoint; }
获取随机颜色方法如下:
-(UIColor*)randColor { CGFloat red =0.0 ,green = 0.0,blue = 0.0 ; red = (CGFloat)(1+arc4random()%99)/100; green = (CGFloat)(1+arc4random()%99)/100; blue = (CGFloat)(1+arc4random()%99)/100; UIColor *randColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0]; return randColor; }
子类CALayer zPosition 设置方法
-(void)setZPosition:(CGFloat)zPosition forLayer:(CALayer*)layer { layer.zPosition = zPosition * (-20); }
2、创建动画
-(void)startAnimation{ CGFloat offsetTime = 0.0; CATransform3D transform = CATransform3DIdentity; transform.m34 = 1.0 / -500.0; transform = CATransform3DRotate(transform,M_PI, 0, 0, 1); [CATransaction begin]; for (CALayer *layer in self.sublayers) { CABasicAnimation *animation = [self getPinForTranform:transform]; animation.beginTime = [layer convertTime:CACurrentMediaTime() toLayer:nil] + offsetTime; [layer addAnimation:animation forKey:nil]; offsetTime += 0.1; } [CATransaction commit]; } -(void)stopAnimation { for (CALayer *layer in self.sublayers) { [layer removeAllAnimations]; } } -(CABasicAnimation*)getPinForTranform:(CATransform3D )transform { CABasicAnimation *basic =[CABasicAnimation animationWithKeyPath:@"transform"]; basic.toValue = [NSValue valueWithCATransform3D:transform]; basic.duration = 1.0; basic.fillMode = kCAFillModeForwards; basic.repeatCount = HUGE; basic.autoreverses = YES; basic.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; basic.removedOnCompletion = NO; return basic; }
开始运行 ,结果如下:
不是我们的结果啊。。。。。其实这里是因为我们自定义Layer还是2D情况
3、为自定义类添加 3D属性
设置旋转角度方法
//设置本layer 在父layer 中展示3D效果 -(void)rotateParentLayer:(CGFloat)toDegree { CATransform3D transform = CATransform3DIdentity; transform.m34 = 1.0 / -500.0; transform = CATransform3DRotate(transform, [self degreesToRadians:toDegree], 1, 0, 0);//以x 坐标旋转制定的角度 self.transform = transform; } //角度转弧度 -(CGFloat)degreesToRadians:(CGFloat)degrees { return ((M_PI * (degrees)) / 180.0); }
然后构造函数中调用:
-(instancetype)initWithNumberOfItems:(NSUInteger)number { if (self = [self init]) { ······ [self rotateParentLayer:60];//X 轴旋转60 度 } return self; }
运行结果如下图:
我去还不是我们想要的。。。
那么我们到最后一步吧。。。。
4、更改继承 CATransformLayer
@interface KBSpinnyMcSpinface : CATransformLayer
结束:完美运行。 其实我想说的是老外的创意真的无极限。。。。
(我是参考老外的swift版本翻译过来的:https://medium.com/ios-os-x-development/effervescent-calayer-transfigurations-on-ios-c5e78781db17#.3mrahw54q)