在不会OpenGL ES的情况下,如何利用CoreAnimation实现一个立方体,并旋转,整体效果如下
整体实现的思路如下
主要分为两部分
- ViewDidLoad函数:初始化工作
- update更新:定时器实现旋转
ViewDidLoad函数
初始化工作包含两部分:
- addFaces:添加6个面,通过变换组合成立方体
- addCADisplayLink:添加定时器,并放入runloop
addFaces函数
这部分主要是将6个面作相应的变换添加到容器中
- OC版本
//添加面 - (void)addFaces{ self.faces = @[_view0, _view1, _view2, _view3, _view4, _view5]; // 主view CATransform3D perspective = CATransform3DIdentity; // 核心动画设置透视投影 perspective.m34 = -1.0 / 500.0; // 围绕x,y分别旋转,M_PI_4 = π/4,π=180° // x:顺时针旋转45°,y:顺时针旋转45° perspective = CATransform3DRotate(perspective, -M_PI_4, 1, 0, 0); perspective = CATransform3DRotate(perspective, -M_PI_4, 0, 1, 0); self.containerView.layer.sublayerTransform = perspective; //添加face1 // z轴平移100 // (除了第一个视图外,其余的视图都是基于第一个视图的位置进行平移+旋转的) CATransform3D transform = CATransform3DMakeTranslation(0, 0, 100); [self addFace:0 withTransform:transform]; //// 添加face2 --平移y+旋转y transform = CATransform3DMakeTranslation(100, 0, 0); transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0); [self addFace:1 withTransform:transform]; // // 添加face3 -- 平移y+旋转x transform = CATransform3DMakeTranslation(0, -100, 0); transform = CATransform3DRotate(transform, M_PI_2, 1, 0, 0); // [self addFace:2 withTransform:transform]; // 添加face4 -- 平移y+旋转x transform = CATransform3DMakeTranslation(0, 100, 0); transform = CATransform3DRotate(transform, -M_PI_2, 1, 0, 0); [self addFace:3 withTransform:transform]; // 添加face5 -- 平移+旋转 transform = CATransform3DMakeTranslation(-100, 0, 0); transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0); [self addFace:4 withTransform:transform]; // 添加face6 -- 平移z+旋转y transform = CATransform3DMakeTranslation(0, 0, -100); transform = CATransform3DRotate(transform, M_PI, 0, 1, 0); [self addFace:5 withTransform:transform]; } - (void)addFace: (NSInteger)index withTransform: (CATransform3D)transform { // 获取face视图,并将其加入容器中 UIView *face = self.faces[index]; [self.containerView addSubview:face]; // 将face视图放在容器的中心 CGSize containerSize = self.containerView.bounds.size; face.center = CGPointMake(containerSize.width/2.0, containerSize.height/2.0); // 添加tansform,tansform就是一个矩阵 face.layer.transform = transform; }
- Swift版本
fileprivate func addFaces(){ faces = [view0, view1, view2, view3, view4, view5] // 父view的layer图层 var perspective: CATransform3D = CATransform3DIdentity perspective.m34 = -1.0 / 500.0 perspective = CATransform3DRotate(perspective, -.pi/4, 1, 0, 0) perspective = CATransform3DRotate(perspective, -.pi/4, 0, 1, 0) self.containerView.layer.sublayerTransform = perspective // 添加face1 var transform = CATransform3DMakeTranslation(0, 0, 100) self.addFaceWithTransform(0, transform) // 添加face2 transform = CATransform3DMakeTranslation(100, 0, 0) transform = CATransform3DRotate(transform, .pi/2, 0, 1, 0) self.addFaceWithTransform(1, transform) // 添加face3 transform = CATransform3DMakeTranslation(0, -100, 0) // transform = CATransform3DRotate(transform, .pi/2, 1, 0, 0) // self.addFaceWithTransform(2, transform) // // 添加face4 transform = CATransform3DMakeTranslation(0, 100, 0) transform = CATransform3DRotate(transform, -.pi/2, 1, 0, 0) self.addFaceWithTransform(3, transform) // // 添加face5 transform = CATransform3DMakeTranslation(-100, 0, 0) // transform = CATransform3DRotate(transform, -.pi/2, 0, 1, 0) self.addFaceWithTransform(4, transform) // //// 添加face6 // transform = CATransform3DMakeTranslation(0, 0, -100) // transform = CATransform3DRotate(transform, .pi, 0, 1, 0) // self.addFaceWithTransform(5, transform) } private func addFaceWithTransform(_ index: Int, _ transform: CATransform3D){ // 获取face,并加入容器中 let face = self.faces[index] self.containerView.addSubview(face) // 将face视图放入容器的中心 let containerSize = self.containerView.bounds.size face.center = CGPoint(x: containerSize.width/2, y: containerSize.height/2) // 添加transform face.layer.transform = transform }
addCADisplayLink函数
这部分主要初始化定时器,并将定时器加入runloop循环中
- OC版本
//添加定时器 - (void)addCADisplayLink{ self.angle = 0; self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)]; [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; }
- Swift版本
fileprivate func addCADisplayLink(){ self.displayLink.add(to: RunLoop.main, forMode: .common) }
update更新
主要是计算旋转度数,并将容器的子layer围绕任意方向旋转
- OC版本
- (void)update{ // 计算旋转度数 self.angle = (self.angle + 5) % 360; // 将度数转化为弧度 float deg = self.angle * (M_PI / 180); CATransform3D temp = CATransform3DIdentity; // 围绕(0.3, 1, 0.7)方向旋转 temp = CATransform3DRotate(temp, deg, 0.3, 1, 0.7); // 旋转容器的子layer self.containerView.layer.sublayerTransform = temp; }
- Swift版本
@objc fileprivate func update(){ self.angle = (self.angle+5).truncatingRemainder(dividingBy: 360) let deg = self.angle * (.pi/180) var temp = CATransform3DIdentity temp = CATransform3DRotate(temp, CGFloat(deg), 0.3, 1, 0.7) self.containerView.layer.sublayerTransform = temp }