cssfun
cssfun copied to clipboard
CSS3之3d transform
原文地址: Intro to css 3D transforms
前言: 作者的这个introduction已经写了有好几年了,我今年(而且今年都快过去了)才看到...果真是渣渣...那句话,人丑朋友又少真的是要多读书。不过我觉得我还是得厚着大脸皮敲下去...
三维世界的坐标系
文章开始之前先来张坐标系图好让大家有个3D概念
透视,perspective属性
为了激活3D属性,需要对元素声明perspective
属性。有两种声明的方式:
-
作为属性transform的值和transform一起声明,就同如下代码一样
transform: perspective( 600px );
-
直接使用 perspective属性 声明
perspective: 600px;
例子1: 点击访问demo
#red .box {
background-color: red;
transform: perspective( 600px ) rotateY( 45deg ); /*作为transform的值*/
}
#blue {
perspective: 600px; /* 直接声明perspective属性 */
}
#blue .box {
background-color: blue;
transform: rotateY( 45deg );
}
这两种方式都能产生3D效果,看上去是产生了一样的效果,但是其实两者还是不同的。transform值的形式适用于单个元素的3D转换效果,就像上个例子一样。但是如果应用于多个元素的话,发生变换的元素并不会表现出一致的效果。因为如果对每个不同位置的元素声明一样的transform属性值,那么他们就会拥有个各自的3D空间的基点了。为了解决这个问题,需要对父元素声明perspective
属性,使每个子元素共享一个3D空间了。
例子2: 点击访问demo
#red figure {
background: red;
transform: perspective( 400px ) rotateY(45deg);
}
#blue {
perspective: 400px;
}
#blue figure {
background: blue;
transform: rotateY( 45deg );
}
PS: 看不出效果的话,可以改变下perspective的值,这样看到的差别会明显一点
perspective值的大小决定了3D效果的强弱程度。就像人看物体一样,perspective值越大,代表物体离眼睛的距离越远,这样看到的物体就越小。perspective:2000px,产生的效果就像我们用望远镜看一个很远很远的物体,perspective: 100px; 则会让物体看起来很大,就像一只小虫看巨大的物体一样。
元素的3D空间的默认基点坐标位于元素中央。但是可以通过perspective-origin
属性来修改: perspective-origin: 25% 75%;
例子3 : 点击访问demo
浏览器支持情况
目前的浏览器支持情况如下: 详情请点击查看
3D transform functions
废话我就不翻译了。。。
3D转换和2D转换方法基本相同,下面就是3D转换方法:
- rotateX( angle )
- rotateY( angle )
- rotateZ( angle )
- translateZ( tz )
- scaleZ( sz )
但是不同的是, translateX()方法是使一个元素沿着水平X轴坐标旋转,translateZ()则是沿着Z坐标轴,可以使物体在3D空间从前往后移动。值为正数且越大则元素离屏幕越近,负数则代表离屏幕远。
rotate方法使物体在相应的坐标系进行旋转。不过注意哦,rotateX可不是从二维空间中的从左到右的旋转,而是围绕真文章最开头给大家温习的那张3D图中的X轴旋转,具体看下面的例子。
- Transforms例子1: 点击访问demo
3D transform也提供了一些简写方法,使用这些方法需要同时声明三个维度的参数:
- translate3d( tx, ty, tz )
- scale3d( sx, sy, sz )
- rotate3d( rx, ry, rz, angle )
提示: 这些3D方法都能够触发Safari的硬件加速,Dean Jackson, CSS 3D transform 技术规范的作者以及主要的Webkit成员这么写道:
“实际上,任何transform的3D操作都会触发硬件加速,即使实际只做了2D转换或者什么也没有做(就像translate3d(0,0,0))。但是这只是目前如此并不代表将来就不会发生变化,这也就是为什么我们没有形成文档或者鼓励这样做的原因。但是这在有些场景下确实很有帮助,可以显著提高渲染的性能。”
这里作者为了简单起见,例子上都只是用了一些基本的转换方法,但是如果你需要在IOS或者Safari的生产环境下使用CSS的话,最好使用foo3d()(指的3D transform的简写方法)来获取最好的渲染性能。
活学活用
1. 卡片翻转
现在大家应该都知道了如何制作3D效果。那就先实现个简单卡片翻转的例子吧。 先看看效果: 请点击
<!-- html结构 -->
<section class="container">
<div id="card">
<figure class="front">1</figure>
<figure class="back">2</figure>
</div>
</section>
.container 作为舞台元素,声明perspective:800px;
属性
.container {
width: 200px;
height: 260px;
position: relative;
perspective: 800px;
}
现在#card就可以在container的3D空间内进行各种变换了,声明width: 100%; and height: 100%;
是为了保证transform-origin为container的中央位置
#card {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
transition: transform 1s;
}
transform-style属性有两个参数,flat|preserve-3d. 前者flat为默认值,表示平面的;后者preserve-3d表示3D透视。一般而言,该声明应用在3D变换的兄弟元素们的父元素上,也就是舞台元素。
backface-visibility: hidden;
当前面元素遮挡住后面的元素时,声明这个属性就可以产生遮挡的效果。
#card figure {
display: block;
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
首先视觉上我们只能看到.front的卡片,所以需要将.back的卡片沿着Y轴旋转180度至后方,当点击flip按钮的时候,直接让#card再沿着Y轴旋转180度,这个时候front卡片就到视线后方而back卡就被我们看到了。
#card .front {
background: red;
}
#card .back {
background: blue;
transform: rotateY( 180deg );
}
#card.flipped {
transform: rotateY( 180deg );
}
如果我们想要改变旋转轴的位置呢? 这就是transform-origin的作用了,稍作修改就可以达到以下的效果。 我要更炫点: 请点击
#card { transform-origin: right center; }
/* translateX( -100% ) 使元素沿着X轴发生平移 */
#card.flipped {
transform: translateX( -100% ) rotateY( -180deg );
}
2. 立方体
这个例子主要向大家介绍下translateZ()
方法,它可以帮你理解透视位置。demo
对于没有rotateX以及rotateY的元素,translateZ的功能就是让元素在自己的眼前或近或远。比方说,我们设置元素perspective为201像素,如下: perspective: 201px; 则其子元素,设置的translateZ值越小,则子元素大小越小(因为元素远去,我们眼睛看到的就会变小);translateZ值越大,该元素也会越来越大,当translateZ值非常接近201像素,但是不超过201像素的时候(如200像素),该元素的大小就会撑满整个屏幕(如果父辈元素没有类似overflow:hidden的限制的话)。因为这个时候,子元素正好移到了你的眼睛前面,所谓“一叶蔽目,不见泰山”,就是这么回事。当translateZ值再变大,超过201像素的时候,该元素看不见了——这很好理解:我们是看不见眼睛后面的东西的! 引用自 张鑫旭老师的http://www.zhangxinxu.com/wordpress/2012/09/css3-3d-transform-perspective-animate-transition/
**但是这里需要注意的是translateZ 和 rotate 方法的顺序,顺序的不同会产生不一样的效果。**可以通过以下例子好好感受下~ translateZ
3. 旋转木马
这里主要向大家介绍旋转木马效果计算各个面板translateZ值的方法:
- 我们现在只知道两个值:
- rotateY 的旋转角度(等分,通过 360/元素个数 取得)
- 面板的宽
那问题来了,怎么计算translateZ的值呢? 其实很简单,当然不是凭直觉随便选出来的那种简单,因为它还是有公式的,那就用下面这张图来说明吧: 然后我们就可以计算出 r 的值了~