CSS3的2D与3D转换
2D和3D转换涉及到数学中的知识,作为一个数学专业的毕业生,不研究一下岂不是对不起自己的专业?
首先来看几个参数:
1、transform-origin:origin(起源,起点),也即变形的起点,在数学上可以理解为坐标原点。
其语法为:transform-origin:[<percentage> | <length> | left | center | right | top | bottom] | [<percentage> | <length> | left | center | right] | [[<percentage> | <length> | left | center | right] && [<percentage> | <length> | top | center | bottom]] <length> ?
描述为普通语言为:
/*只设置一个值的语法*/
transform-origin: x-offset
transform-origin:offset-keyword
/*设置两个值的语法*/
transform-origin:x-offset y-offset
transform-origin:y-offset x-offset-keyword
transform-origin:x-offset-keyword y-offset
transform-origin:x-offset-keyword y-offset-keyword
transform-origin:y-offset-keyword x-offset-keyword
/*设置三个值的语法*/
transform-origin:x-offset y-offset z-offset
transform-origin:y-offset x-offset-keyword z-offset
transform-origin:x-offset-keyword y-offset z-offset
transform-origin:x-offset-keyword y-offset-keyword z-offset
transform-origin:y-offset-keyword x-offset-keyword z-offset
transform-origin属性值可以是百分比、em、px等具体的值,也可以是top、right、bottom、left和center这样的关键词。默认值为50%,50%,0。
- x-offset:用来设置
transform-origin
水平方向X轴的偏移量,可以使用<length>
和<percentage>
值,同时也可以是正值(从中心点沿水平方向X轴向右偏移量),也可以是负值(从中心点沿水平方向X轴向左偏移量)。 - offset-keyword:是
top
、right
、bottom
、left
或center
中的一个关键词,可以用来设置transform-origin
的偏移量。 - y-offset:用来设置
transform-origin
属性在垂直方向Y轴的偏移量,可以使用<length>
和<percentage>
值,同时可以是正值(从中心点沿垂直方向Y轴向下的偏移量),也可以是负值(从中心点沿垂直方向Y轴向上的偏移量)。 - x-offset-keyword:是
left
、right
或center
中的一个关键词,可以用来设置transform-origin
属性值在水平X轴的偏移量。 - y-offset-keyword:是
top
、bottom
或center
中的一个关键词,可以用来设置transform-origin
属性值在垂直方向Y轴的偏移量。 - z-offset:用来设置3D变形中
transform-origin
远离用户眼睛视点的距离,默认值z=0
,其取值可以<length>
,不过<percentage>
在这里将无效。
transform-origin属性值可以是百分比、em、px等具体的值,也可以是top、right、bottom、left和center这样的关键词。默认值为50%,50%,0。
2、transform-style:指定嵌套元素如何在3D空间中呈现。
有两个属性值:flat
和preserve-3d。其中
flat
值为默认值,表示所有子元素在2D平面呈现。preserve-3d
表示所有子元素在3D空间中呈现。
如果对一个元素设置了transform-style
的值为flat
,则该元素的所有子元素都将被平展到该元素的2D平面中进行呈现。沿着X轴或Y轴方向旋转该元素将导致位于正或负Z轴位置的子元素显示在该元素的平面上,而不是它的前面或者后面。如果对一个元素设置了transform-style
的值为preserve-3d
,它表示不执行平展操作,他的所有子元素位于3D空间中。transform-style
属性需要设置在父元素中,并且高于任何嵌套的变形元素。
即transform-style
的值为flat时,其子元素并不会受到rotateX等的影响,而是直接与父元素叠加在一起,和父元素处于同一平面上。当值为preserve-3d时,子元素与父元素分离,受单独的属性控制。
有一点需要注意,如果你的元素设置了transform-style
值为preserve-3d
,就不能为了防止子元素溢出容器而设置overflow
值为hidden
,如果设置了overflow:hidden
同样可以迫使子元素出现在同一平面(和元素设置了transform-style
为flat
一样的效果)。
3、perspective:对于3D变换最重要的属性,意思为透视,透视的。
在两维的平面上利用线和面趋向会合的视错觉原理刻画三维物体的艺术表现手法。
透视图:在人与建筑物之间设立一个透明的铅垂面K作为投影面,人的视线(投射线)透过投影面而与投影面相交所得的图形,称为透视图,或称为透视投影,简称透视。根据透视的原理绘制的图,多用于机械工程和建筑工程。
透视的产生:因为有了光我们才得以看到自然界中的一切,这个过程就是光线照射到物体上并通过眼球内水晶体把光线反射到我们眼内视网膜上而形成图像,我们把光线在眼球水晶体的折射焦点叫做视点,视网膜上所呈现的图像称为画面。只是人脑通过自身的机能处理将倒过来的图像转换成正立图像。如果我们在眼前假定一个平面或放置一透明平面,以此来截获物体反射到眼球内的光线,就会得到与实物一致的图像,这个假定平面,也就是我们平时画画的画面。
相关术语:
基面 | 形体所在的水平面,用字母G表示。基面相当于三投影面体系中的水平投影面H。 |
画面 | 透视图所在的平面,一般为铅垂面,用字母P表示。也可以用倾斜平面做画面。 |
基线 | 基面与画面的交线,用字母gl表示。 |
视点 | 观看者眼睛所在的位置,用字母S表示。 |
站点 | 观看者站定的位置,即视点S的基面上的正投影,用E表示。 |
心点 | 视点S在画面上的正投影,用字母Vc表示。 |
主视线 | 垂直于画面P的视线,也就是过视点S和心点Vc的直线。也叫中心视线。 |
视平面 | 过视点S的水平面。 |
可分为一点透视、两点透视、三点透视。
上面介绍了透视的相关知识,现在开始是正题。
perspective属性会设置查看者的位置,并将可视内容映射到一个视锥上,继而投到一个2D视平面上。如果不指定透视,则Z轴空间中的所有点将平铺到同一个2D视平面中,并且变换结果中将不存在景深概念。
我们可以简单的理解为视距,用来设置用户和元素3D空间Z平面之间的距离。而其效应由他的值来决定,值越小,用户与3D空间Z平面距离越近,视觉效果更令人印象深刻;反之,值越大,用户与3D空间Z平面距离越远,视觉效果就很小。
在3D变形中,对于某些变形,perspective
属性对于查看变形的效果来说必不可少。
perspective
属性包括两个属性:none
和具有单位的长度值。其中perspective
属性的默认值为none
,表示无限的角度来看3D物体,但看上去是平的。另一个值<length>
接受一个长度单位大于0的值。而且其单位不能为百分比值。<length>
值越大,角度出现的越远,从而创建一个相当低的强度和非常小的3D空间变化。反之,此值越小,角度出现的越近,从而创建一个高强度的角度和一个大型3D变化。
比如你站在10英尺和1000英尺的地方看一个10英尺的立方体。在10英尺的地方,你距离立方体是一样的尺寸。因此视角转变远远大于站在1000英尺处的,立体尺寸是你距离立方体距离的百分之一。同样的思维适用于perspective
的<length>
值。
依据上面的介绍,我们可对perspective
取值做一个简单的结论:
- perspective取值为none或不设置,就没有真3D空间。
- perspective取值越小,3D效果就越明显,也就是你的眼睛越靠近真3D。
- perspective的值无穷大,或值为0时与取值为none效果一样。
为了更好的理解perspective
属性,我们很有必要把他和translateZ
的关系结合起来。其实也可以把perspective
的值简单的理解为人的眼睛到显示器的距离,而translate
就是3D物体距离源点的距离,下面引用w3cplus的一张图来解说perspective
和translateZ
的关系。
上图显示了perspective
属性和translateZ
的位置比例。要顶部的图,Z是半个d,为了使用原始圆(轮廓)看起来出现在Z轴上(虚线圆),画布上的实体圆将扩大两部,如浅蓝色的圆。在底部图中显示,圆按比例缩小,致使虚线圆出现在画布后面,并且z的大小是距原始位置三分之一。
perspective是针对父元素的,设置人眼与父元素间距离,父元素可以理解为子元素的投影处,即父元素为子元素的画布。translateZ则是设置子元素与画布的距离的,距离的单位为像素。比方说,一个1680像素宽的显示器中有张美女图片,应用了3D transform,同时,该元素或该元素父辈元素设置的perspective
大小为2000像素。则这张美女多呈现的3D效果就跟你本人在1.2个显示器宽度的地方(1680*1.2≈2000)看到的真实效果一致!!
我们都知道近大远小的道理,对于没有rotateX
以及rotateY
的元素,translateZ
的功能就是让元素在自己的眼前或近或远。比方说,我们设置元素perspective
为201像素,则其子元素,设置的translateZ
值越小,则子元素大小越小(因为元素远去,我们眼睛看到的就会变小);translateZ
值越大,该元素也会越来越大,当translateZ
值非常接近201像素,但是不超过201像素的时候(如200像素),该元素的大小就会撑满整个屏幕(如果父辈元素没有类似overflow:hidden的限制的话)。因为这个时候,子元素正好移到了你的眼睛前面,所谓“一叶蔽目,不见泰山”,就是这么回事。当translateZ
值再变大,超过201像素的时候,该元素看不见了——这很好理解:我们是看不见眼睛后面的东西的!
关于Chrome浏览器以及透视盲区:
在Chrome浏览器下,要想看到完整的3D效果,还需要3D变换元素正好在窗体的垂直居中位置。
透视盲区不难理解,假设前面一排门,每个门都是1米,你距离门2米,显示,当所有门都开了45°角的时候,此时,距离中间门右侧的第二个门正好与你的视线平行,这个门的门面显然就什么也看不到。这就是为什么上面右侧第三个门一片空白的元素——特定的视角以及距离形成的视觉盲区。
在3D变形中,除了perspective
属性可以激活一个3D空间之外,在3D变形的函数中的perspective()
也可以激活3D空间。他们不同的地方是:perspective
用在舞台元素上(变形元素们的共同父元素);perspective()
就是用在当前变形元素上,并且可以与其他的transform
函数一起使用。
虽然perspective
属性和perspective()
函数所起的功能是一样的,但其取值以及以运用的对像有所不同:
-
perspective
属性可以取值为none
或长度值;而perspective()
函数取值只能大于0,如果取值为0或比0小的值,将无法激活3D空间; -
perspective
属性用于变形对像父元素;而perspective()
函数用于变形对像自身,并和transform
其他函数一起使用。
4、perspective-origin:
3D变形中另一个重要属性,主要用来决定perspective
属性的源点角度。它实际上设置了X轴和Y轴位置,在该位置观看者好像在观看该元素的子元素。
perspective-origin:[<percentage> | <length> | left | center | right | top | bottom] | [[<percentage> | <length> | left | center | right] && [<percentage> | <length> | top | center | bottom]]
该属性的默认值为“50% 50%”(也就是center),其也可以设置为一个值,也可以设置为两个长度值。
- 第一个长度值指定相对于元素的包含框的X轴上的位置。它可以是长度值(以受支持的长度单位表示)、百分比或以下三个关键词之一:
left
(表示在包含框的X轴方向长度的0%),center
(表示中间点),或right(表示长度的100%)。 - 第二个长度值指定相对于元素的包含框的Y轴上的位置。它可以是长度值、百分比或以下三个关键词之一:
top
(表示在包含框的Y轴方向长度的0%),center
(表示中间点),或bottom
(表示长度的100%)。
注意,为了指转换子元素变形的深度,perspective-origin
属性必须定义父元素上。通常perspective-origin
属性本身不做任何事情,它必须被定义在设置了perspective
属性的元素上。换句话说,perspective-origin
属性需要与perspective
属性结合起来使用,以便将视点移至元素的中心以外位置。
往往我们看一样东西不可能一直都在中心位置看,想换个角度,换个位置一看究竟,这个时候就离不开perspective-origin
这个属性,下面来自于W3C官网的图可以简单阐述这一观点:
接下来的示例演示了修改perspective-origin
的属性值对立方体的影响:
介绍了这么多复杂的属性了,介绍一个简单的歇歇脚。
5、backface-visibility
很简单的一个属性,visible | hidden两个值可选,相当于是否使元素透明,透明的时候即visible,在转至背面时,也可以看到内容,内容是反的。hidden既不可见。
一个元素的可见性与“backface-visibility:hidden”决定如下:
- 元素在3D环境下渲染上下文,将根据3D变形矩阵来计算,反之元素不在3D环境下渲染上下文,将根据2D变形矩阵来计算。
- 如果组件的矩阵在第3行、3列是负值,那么元素反面是隐藏,反之是可见的。
简单点来说,backface-visibility
属性可用于隐藏内容的背面。默认情况下,背面可见,这意味着即使在翻转后,旋转的内容仍然可见。但当backface-visibility
设置为hidden
时,旋转后内容将隐藏,因为旋转后正面将不再可见。该功能可帮助您模拟多面的对象,您可以轻松确保只有正面可见。
上述内容转自:http://www.w3cplus.com/css3/transform-basic-property.html。
顺便安利一篇文章,关于覆盖内容的知识,CSS Overlay技巧。
介绍完转换的一些属性,就要开始研究两个主要的变换方法了,matrix()和matrix3d()。
6、matrix
该方法有六个参数,matrix(a,b,c,d,e,f),对应的转换关系为:
一个很简单的矩阵变换。
根据数学方面的知识,可以得出:
translate(x,y)=matrix(1,0,0,1,x,y)
scale(x,y)=matrix(x,0,0,y,0,0)
rotate(θdeg)=matrix(cosθ,sinθ,-sinθ,cosθ,0,0)-证明方法:根据中心旋转证明,详细参考解析几何。
skew(θxdeg,θydeg)=matrix(1,tan(θy),tan(θx),1,0,0)-原理:skew是在保证图形在某一个坐标轴上距离不变的情况下,对另外一条坐标轴做倾斜,所以可推出上面的公式。
还有一个只能通过matrix实现的,比如说:
镜面翻转matrix(-1,0,0,1,0,0)
沿y=kx对称:matrix((1-k*k) / (1+k*k), 2k / (1 + k*k), 2k / (1 + k*k), (k*k - 1) / (1+k*k), 0, 0)。
证明方法可以参考数学类里面的内容。
但是matrix还是有所限制的,比如矩形映射为梯形,使用矩阵变换实现不了,因为原来平行的线,在通过矩阵变换后仍然平行。
7、matrix3d
要想实现矩形变换,还是要借助matrix3d。
matrix3d比2d情况下多了z轴,参数也相应的变为了十六个:matrix3d(n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16),矩阵形式为:
可以看到,比2D情况下多了很多参数,特别是最后一行,坐标只有三个点,最后一行是什么呢?很明显,前面的参数里有个透视,最后一个参数就是透视。
translate3d(x,y,z)=matrix3d(1,0,0,x,0,1,0,y,0,0,0,1,z,0,0,0,1)
scale3d(x,y,z)=matrix3d(x,0,0,0,0,y,0,0,0,0,z,0,0,0,0,1)
关于旋转参考:三维旋转矩阵的推导。
rotate3d(x,y,z,angle);略微麻烦。在3D空间,旋转有三个程度的自由来描述一个转动轴。轴的旋转是由一个[x,y,z]向量并经过元素原点。
- x:是一个0到1之间的数值,主要用来描述元素围绕X轴旋转的矢量值;
- y:是一个0到1之间的数值,主要用来描述元素围绕Y轴旋转的矢量值;
- z:是一个0到1之间的数值,主要用来描述元素围绕Z轴旋转的矢量值;
- angle:是一个角度值,主要用来指定元素在3D空间旋转的角度,如果其值为正值,元素顺时针旋转,反之元素逆时针旋转。
三个旋转函数功能等同:
- rotateX(a)函数功能等同于rotate3d(1,0,0,a)
- rotateY(a)函数功能等同于rotate3d(0,1,0,a)
- rotateZ(a)函数功能等同于rotate3d(0,0,1,a)
最后说明一下,上面这些变形都是可以叠加的,叠加的效果之间用空格隔开。
这些矩阵在数学上叫做变换矩阵。关于3D变换更好的说明,可以查看matrix3d。
本文以上内容取自http://www.zhangxinxu.com与http://www.w3cplus.com特此鸣谢