CATransform3D 矩阵变换之立方体旋转实现细节 (转)
原文地址
http://blog.csdn.net/ch_soft/article/details/7351896
第一部分、前几天做动画,使用到了CATransform3D ,由于没有学过计算机图形学,矩阵中m11--m44的各个含义都不清楚,经过几天研究总结如下:(供和我一样的菜鸟学习)
{
CGFloat m11(x缩放), m12(y切变), m13(), m14();
CGFloat m21(x切变), m22(y缩放), m23(), m24();
CGFloat m31(), m32(), m33(), m34(透视效果,要操作的这个对象要有旋转的角度,否则没有效果。当然,z方向上得有变化才会有透视效果);
CGFloat m41(x平移), m42(y平移), m43(z平移), m44();
};
ps:
- 整体比例变换时,也就是m11==m22时,若m33>1,图形整体缩小,若0<m33<1,图形整体放大,若m33<0,发生关于原点的对称等比变换。
- 单设m12或m21的时候是切变效果,当【m12=角度】和【m21=-角度】的时候就是旋转效果了。两个角度值相同。
- ()空的地方以后补充。
- 还有,要想使用CATransform3D,必须在工程里导入QuartzCore.framework。然后在文件中
#import <QuartzCore/CATransform3D.h>。
iphone 透视效果(perspective)
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 0.0005; // 透视效果
transform = CATransform3DRotate(transform,(M_PI/*), , , );
[piece.layer setTransform:transform];
第二行一定要写在第三行的前面!自己理解!
第二部分 . CATransform3D结构成员的意义。
?
structCATransform3D
{
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();
}; ps:整体比例变换时,也就是m11==m22时,若m33>,图形整体缩小,若0<m33<,图形整体放大,若s<,发生关于原点的对称等比变换。 ()空的地方以后补充。 . CATransform3DMakeTranslation CATransform3DMakeTranslation(, , ) 创建了一个4*4的单位矩阵。 . CATransform3DMakeRotation And CATransform3DRotate CATransform3DMakeRotation()
[objc] view plaincopy _transformedLayer = [CALayer layer];
_transformedLayer.frame = self.bounds;
_transformedLayer.anchorPoint = CGPointMake(0.5f, 0.5f);
CATransform3D sublayerTransform = CATransform3DIdentity;
// Set perspective
sublayerTransform.m34 = kPerspective;
[_transformedLayer setSublayerTransform:sublayerTransform]; [self.layer addSublayer:_transformedLayer];
//init Sublayers
CATransform3D t = CATransform3DMakeTranslation(, , );
// take snapshot of the current view
[_transformedLayer addSublayer:[self snapshot:t
withView:_contentView
isMasked:YES]];
// 暂时先支持一个方向翻转
RotateDirection direction = RotateFromBottom;
if (YES || direction == RotateFromBottom)
{
CGFloat height = self.bounds.size.height;
//CGFloat cubeSize = 100.0f;
t = CATransform3DRotate(t, D2R(90.0), , , );【】
t = CATransform3DTranslate(t, , height, );
CALayer *subLayer = [self snapshot:t withView:view isMasked:YES];
[_transformedLayer addSublayer:subLayer];
}
else
{
} _newContentView = view; [self animationCubeRotate:direction withDuration:duration]; . 翻转的动画
[objc] view plaincopy - (void)animationCubeRotate:(RotateDirection)direction
withDuration:(float)duration
{
[CATransaction flush];
CGFloat height = self.bounds.size.height;
CABasicAnimation *rotation;
// CABasicAnimation *translationX; // 如果沿X轴翻转,则用不到这个变量.
CABasicAnimation *translationY; // 如果沿Y轴翻转,则用不到这个变量.
CABasicAnimation *translationZ;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.delegate = self;
animationGroup.duration = duration; if ( direction == RotateFromBottom )
{
// 创建(某方向)关键帧动画.
translationY = [CABasicAnimation animationWithKeyPath:
@"sublayerTransform.translation.y"];
translationY.toValue = [NSNumber numberWithFloat:-(height / )];【】
rotation = [CABasicAnimation animationWithKeyPath:
@"sublayerTransform.rotation.x"];
rotation.toValue = [NSNumber numberWithFloat:D2R(-90.0f)];
}
else if ( direction == RotateFromTop )
{
} // 处理Z轴
translationZ = [CABasicAnimation animationWithKeyPath:
@"sublayerTransform.translation.z"];
translationZ.toValue = [NSNumber numberWithFloat:height / ];【】
animationGroup.animations =
[NSArray arrayWithObjects: rotation, translationY, translationZ, nil nil];
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion = NO;
[_transformedLayer addAnimation:animationGroup forKey:kAnimationKey];
} made, 我发现这个东西确实很难讲清楚,主要是因为我理论薄弱, 【】针对X轴旋转,就是1,,,针对Y轴旋转,就是0,,...下面那行也要进行正确的转换。 【】此处应该是和 anchorPoint有关系的。 【】这个值会影响类似于深度的东西,比如说Cube会离我们更近,或者是更远。(但是,似乎不算是透视关系) 第三部分、实例开发:
一般情况下我们不必对IOS窄哦的这个矩阵进行直接操作,SDK为我们提供了现成的转换方法。这里我们将使用core animation 利用这个矩阵进行立方体旋转的实现,这是我从网上down下来代码之后,自己进行摸索后总结的笔记,难免有不足之处,希望没有误导看到本文的同学。 这里用到的转换喊着主要包括旋转函数和移动函数 : CATransform3DRotate CATransform3DMakeTranslation 原理说明:
旋转类型:从当前显示旋转到顶部
具体操作:.将旋转分为一段段的,组成路径,由CAKeyframeAnimation保存,每一段都由旋转的角度确定,比如角度为a(旋转完成应该是有90度); .将当前视图(后加入的)进行偏移变换,产生一个偏移矩阵,也就是将视图中心点转移到旋转该角度后预定位置; .将上面的结果进行a角度旋转变换;
说明:旋转的方式有:从当前向顶上,向底部,向左,向右,以及从这些所有位置旋转回来。只是形成立方体旋转的基本组成方式。由于所有方式过程相似,只要修改旋转轴(后文会提到)和偏移即可,所以只是叙述其中的一个。 具体实现:
.加入两个子view
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
view.backgroundColor = [UIColor redColor];
view.center = self.view.center;
[self.view addSubview:view]; UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
view1 .backgroundColor = [UIColor redColor];
view1 .center = self.view.center;
[self.view addSubview:view1]; .进行旋转
某次旋转的核心变换:(重点理解两次变换,为什么要这么变?需要一定的空间几何思维)
CGFloat radius = DEGREE_TO_RADIUS(*(float)(count - - index)/(float)(count -));//计算旋转的角度;其中count是旋转路径节点数目,index是第几个节点 (一共旋转90度)
CATransform3D transform3d = CATransform3DMakeTranslation(, -r*sinf(radius), -r*(-cosf(radius)));//计算偏移矩(表示在Y轴上偏移量为-r*sinf(radius),Z轴上为后者)
transform3d = CATransform3DRotate(transform3d, radius, .f, , );//在上述基础上计算旋转矩阵
NSValue *value = [NSValue valueWithCATransform3D:transform3d];
[values addObject:value];//将矩阵值加入路径中
if (index > ) {
[timingFunctions addObject:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];//将时间控制加入 NOTE:CATransform3DRotate()方法制造旋转矩阵,控制旋转角度和方向。这里有一个诀窍就是向量值某个坐标值的正负影响向量的指向方向也影响视图的旋转方向。 创建路径:
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:keyPath];
NSMutableArray *values = [NSMutableArray array]; //矩阵表示的路径
NSMutableArray *timingFunctions = [NSMutableArray array];//对应的时间控制
for (int i = ; i< count; i ++)
{
//执行上面的代码快
}
animation.values = values;
animation.timingFunctions = timingFunctions;
animation.duration = duration; .至此,路径创建成功,最难的部分已经过去。继续我们的旅程:
创建 CAAnimationGroup :
CAAnimationGroup *cubicAnimation = [CAAnimationGroup animation];
cubicAnimation.duration = duration;
cubicAnimation.delegate = delegate;
cubicAnimation.animations = [NSArray arrayWithObjects:transform,nil]; //transform就是上一个部分我们辛苦创造的CAKeyframeAnimation *animation .组装,实现动画
CATransform3D transform = CATransform3DIdentity;
[self.layer setSublayerTransform:transform]; //还原3D设置(没有试过不还原,官方要求必须还原)
[CATransaction begin];
[CATransaction setAnimationDuration:duration]; //设置动画运行时长
[CATransaction setCompletionBlock:completionBlock]; //完成后执行的动作
[subViewIn.layer addAnimation:inAnimation forKey:@"cubeIn"]; //在层里加入动画,系统会自动将他开始
[CATransaction commit]; .重要:最后的最后,黎明前总是最黑暗的时刻,这次也不例外。我们所做的只是将一个面转了一下,要想形成立方体效果,我们还得把另外的面跟着做对应旋转。晕了吧,慢慢回来,再苦逼的做一遍工作吧。不过幸好我们有电脑帮我们做那些烦人的重复的事情,写个函数体,copy,修改参数值,OK! 第四部分
CATransform3D myTransform;
myTransform = CATransform3DMakeRotation(angle, x, y, z); 该CATransform3DMakeRotation函数创建了一个转变,将在三维轴坐标系以任意弧度旋转层。x-y-z轴的有个确定的范围(介于- 和+1之间) 。相应的坐标轴指定的值告诉系统在该轴上旋转。例如,如果X轴是设置为-1或1 ,该对象将的X轴的方向上旋转,这意味着将把它垂直旋转。把这些值看做是插入在图像每个坐标轴上的秸秆(Think of these values as inserting straws through the image for each axis.)。如果秸秆插过x轴,图像将沿着秸秆垂直旋转。您可以使用坐标轴角度值创建更复杂的旋转。。对于大多数的用途,但是,值介于-1和+1已经足够。 要水平(垂直)旋转45度,您可以使用下面的代码: myTransform = CATransform3DMakeRotation(0.78, 1.0, 0.0, 0.0); 要在Y轴上旋转相同的值:
myTransform = CATransform3DMakeRotation(0.78, 0.0, 1.0, 0.0); 0.78 ,用在前面的例子,是由角度值经计算转化为弧度值。要把角度值转化为弧度值,可以使用一个简单的公式Mπ/ 。例如, 45π/ = ( 3.1415 ) / = 0.7853 。如果你打算在你的程序里面一直都用角度值的话,你可以写一个简单的转化方法,以帮助保持您的代码是可以理解的: double radians(float degrees) {
return ( degrees * 3.14159265 ) / 180.0;
} 当你创建一个转换的时候,你将要调用这个方法: myTransform = CATransform3DMakeRotation(radians(45.0), 0.0, 1.0, 0.0); 当变换(transformation)被创建好了以后,应用在你正在操作的层上。CALayer对象提供了一个transform属性来连接转换。层将执行分配给transform属性的转换: imageView.layer.transform = myTransform; 当对象被显示后,将会显示应用到它的转换效果。在你的代码中,你任然把它当做是个2D对象。但是它根据提供的转换类型来渲染。
CATransform3D 矩阵变换之立方体旋转实现细节 (转)的更多相关文章
- 【转】 CATransform3D 矩阵变换之立方体旋转实现细节
原文网址:http://blog.csdn.net/ch_soft/article/details/7351896 第一部分.前几天做动画,使用到了CATransform3D ,由于没有学过计算机图形 ...
- 关于CATransform3D矩阵变换的简单解析
关于CATransform3D矩阵变换的简单解析 效果图: 我能能够用上的CATransform3D其实很简单,并不复杂. CATransform3D有着4种东西我们可以设置. 1. 透视效果(由m3 ...
- 网页特效:用CSS3制作3D图片立方体旋转特效
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- osg矩阵变换节点-----平移旋转缩放
osg矩阵变换节点-----平移旋转缩放 转自:http://www.cnblogs.com/ylwn817/articles/1973396.html 平移旋转缩放这个三个是osg矩阵操作中,最常见 ...
- css3-实现3D立方体旋转
核心内容: 1.CSS3 中 animation.perspective 属性的熟练运用. 2.CSS3 中的变形属性 transform,在 3D 立体效果中的运用. 3.3D 立方体旋转实现原理. ...
- 制作3D图片立方体旋转特效
<!DOCTYPE html><html><head><meta charset="utf-8" /><title>CS ...
- 基于css3的3D立方体旋转特效
今天给大家分享一款基于css3的3D立方体旋转特效.这款特效适用浏览器:360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗. 不支持IE8及以下浏览器.效果图如下 : ...
- 基于css3新属性transform及原生js实现鼠标拖动3d立方体旋转
基于css3新属性transform,实现3d立方体的旋转 通过原生JS,点击事件,鼠标按下.鼠标抬起和鼠标移动事件,实现3d立方体的拖动旋转,并将旋转角度实时的反应至界面上显示 实现原理:通过获取鼠 ...
- 超绚丽CSS3多色彩发光立方体旋转动画
CSS3添加了几个动画效果的属性,通过设置这些属性,可以做出一些简单的动画效果而不需要再去借助JavaScript.css3动画的属性主要分为三类:transform.transition以及anim ...
随机推荐
- 【zabbix】zabbix忘记密码,重置密码
忘记密码这种事经常会发生,这里我们介绍一种zabbix忘记用户密码的处理方式. 原理: zabbix存储在数据库中用户名密码是经过32位,小写,md5加密过的.我们可以手动修改数据库中用户的密码. 实 ...
- 编译安装 nginx的http_stub_status_module监控其运行状态
步骤: 1 编译nginx,加上参数 --with-http_stub_status_module 以我自己的编译选项为例: #配置指令 ./configure --prefix=/usr/local ...
- 算法寒假实习面试经过之 滴滴(电话一面二面 offer)
一面:1h 介绍比赛项目. lr与xgb的区别? xgb 为什么不用归一化,onehot? xgb 与 gbdt的区别. 做这些比赛你们的优势在哪,既然全是相同的套路. RCNN的原理, CNN的原理 ...
- vagrant搭建
1.在官网下载对应的vagrant版本 https://www.vagrantup.com/downloads.html (下载最新版本) https://releases.hashicorp.com ...
- Raspberry Pi开发之旅-实现云平台监控
一.基本设置 1 sudo raspi-config 移动到第五项“Enable Camera”,回车进入,按tab键切换到“Enable”回车确认.回到主菜单,tab键切换到“Finish”回车确认 ...
- 使用jsp+javabean完成用户登陆功能
User.java package com.po; public class User implements java.io.Serializable { private String usernam ...
- R中的数据重塑函数
1.去除重复数据 函数:duplicated(x, incomparables = FALSE, MARGIN = 1,fromLast = FALSE, ...),返回一个布尔值向量,重复数据的第一 ...
- 20145231 《Java程序设计》第一周学习总结
20145231 <Java程序设计>第一周学习总结 教材学习内容总结 Java三大平台Java SE,Java EE,Java ME.其中,Java SE是我们学习的基础. Java S ...
- 20145240 《Java程序设计》第十周学习总结
20145240 <Java程序设计>第十周学习总结 教材学习内容总结 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据. 程序员所作的事情就是把数据发送到指定的位置 ...
- MVC6 (ASP.NET5) 自定义TagHelper
1) 在 _ViewImports.cshtml 中引入TagHelper类所在的 Assembly . (注意不是namespace) : @addTagHelper "*, WebAp ...