css3 2d/3d变换——实现超炫的特效
声明:所有结论都是经过实际代码运行的效果证实的,如果有不同的情况发生,请核对浏览器版本以及内核(360浏览器,webkit内核)是否与本人试验的时候一致,同时非常感觉读者阅读本文,如有错误之处,欢迎大家留言指出。
css3的2d/3d变换是一个很强大的功能,以前想要做到图片的倾斜或者旋转某个角度,都无法简单的做到,更别说3d效果的实现,这里的3d效果其实也是一种2d变换之后给人的一种视觉欺骗达到的,浏览器这个“平面”客户端确实无法做到真正的3d效果,现在css3就给我们提供了一种简单的方法来做到2d/3d效果。下面我给大家分享一下我的学习心得。
一、坐标轴和参考点(旋转基点)
1、参考点(旋转基点)
相信大家对于参考点这个概念并不会陌生,见名知意的一个词语,css的参考点就是元素所围绕其旋转的点,在css中用一个属性设置旋转基点,如下所示:
transform-origin: left top; // 设置该元素的旋转基点为该元素的左上角
transform-origin属性是css变换的一个重要的属性,一般需要设置2个值:
第一个值为偏移x轴方向的距离,可以用关键字left|right|center或者百分比以及具体的距离值描述。
第二个值为偏移y轴方向的距离,可以用关键字top|bottom|center或者百分比以及具体的距离值描述。
第三个值为偏移z轴方向的距离,只能使用具体的距离值描述,这个值是使用在开启了3d模式下使用的,并且不怎么常用,第三个值默认值为0。
Tips:当只设置一个值的时候,那就意味着第二个值默认为center,第三个值默认为0
2、坐标轴
要想理解变换,那么必须要有一个参考点和参考坐标系,想必大家已经对html元素的x和y轴已经有了一定的认知,没错:x轴的正方法是水平向右,y轴正方形是垂直向下的。那么3d坐标轴又是什么样的呢?
我从网上扣了一张图下来:
我们可以将黑色网看做我们的屏幕平面,x、y轴的方向跟上面所讲的是一致的,z轴正方形是垂直屏幕面向我们的。
当我们旋转一个元素的时候,怎么确定其正方向和负方向呢?就那绕着z轴做旋转的元素来说,旋转10deg (deg是css的角度单位)和旋转-10deg应该是什么样子的呢?如下图所示:
对于一些新手来说,很难记住其旋转的正负方向,这里教给大家一个技巧:
css旋转的左手定律:拿出你们的左手,用大拇指指向旋转所围绕的坐标轴的正方向,4指弯曲所围绕的方向就为旋转的正方向——Hu渣渣
读者可以拿上面一张图片的俩个元素来比对试验一下。上面那张图是以中心为旋转基点的,可能不太容易观察,下面贴出一张以左上角为旋转基点围绕着z轴旋转的图,读者可以再使用左手定律再试一下:
二、2d变换
说完了坐标轴和参考点之后,我们就进入正题,说说2d变换。
2d变换一共有2个属性、4个方法,这是什么意思呢?意思其实很简单,意思是:能够控制元素做2d变换的style样式属性只有2个,一个是transform-origin(前面说的旋转基点)、transform(变换方法)。旋转基点在上面已经说过了,在这里就不做重复了,接下来就聊一聊4种变换方法。
1、2d变换中的4中变换方法
a. translate(位移,单位px等)
translate(x,y) 沿着x轴正方向移动x距离 y轴正方向移动y距离
translateX(n) 沿着x轴正方向移动n距离
translateY(n) 沿着y轴正方向移动n距离
b. scale(缩放,无单位)
scale(x,y) 更改元素的宽度和高度,将元素的宽度变为原来的x倍,将高度变为原来的y倍
scaleX(n) 更改元素的宽度
scaleY(n) 更改元素的高度
当取值为负数的时候,得到的效果如下:
首先将元素绕着x、y(取决于你的缩放方向)旋转180deg,然后再进行缩放。
如果是scaleX参数为负,则将元素绕y轴翻个面。如下图所示:
如果是scaleY参数为负,则将元素绕x轴翻个面。如下图所示:
c. rotate(旋转,单位为deg)
rotate(x) 围绕z轴旋转,只接受一个参数,并且这个是2d方面的旋转,但是和后面的3d旋转中的围绕z轴旋转有着本质区别
rotateX(n) 围绕x轴旋转
rotateY(n) 围绕y轴旋转
可以用左手定律来判断正负方向。
d. skew(斜切,单位deg)
skew(x-angle,y-angle) 定义2d倾斜旋转 沿着x轴和y轴
skewX(angle) 如果angle是正值,则沿着x轴正方向偏移斜切,负值则相反
skewY(angle) 如果angle是正值,则沿着y轴正方向偏移斜切,负值则相反
网上大家都把skew叫做斜切,这么喊可能不容易理解,我习惯把它叫做拉伸。
skewX(angel) 就是将元素以旋转基点为坐标原点沿着x轴方向拉伸一定角度
skewY(angel) 就是将元素以旋转基点为坐标原点沿着y轴方向拉伸一定角度
给大家上图解释一下:
按照图解思路,大家可以将旋转基点设置为其他值试一试,上图的旋转基点是默认值。
3d变换
3d属性
一个物体看起来如果要有3d效果,那么就需要给它加上一个属性
transform-style: preserve-3d /*开启3d空间*/
视距(perspective)和translateZ
在这里为什么要将translateZ和视距一起说呢?因为他们的联系很大。视距就是眼睛距离物体原本位置的距离,而translateZ()就是用来改变 物体当前位置 离 物体原本所在位置距离的方法。可以用一张图来描述一下:
图解:从上面这个图可以了解到,当视距为0的时候,你是看不到这个物体的,因为你的眼睛和物体平行,你是看不到的,当视距小于0的时候,那你更看不到了,因为它都跑到你的脑门后面了。当translateZ的值大于或者很接近视距的时候,就跟一个成语描述的那样,一叶障目,那整个屏幕都被这个元素占满了。
景深基点(perspective-origin)
perspective-origin属性定义3D元素所基于的X轴和Y轴。该属性允许您改变3D元素的底部位置。s说白了就是你移动到不同的地方看这个元素,默认值是正对着元素看,即 perspective-origin: 50% 50% 0;
第一个值可以为left|right|center|百分比|length,表示向x轴方向移动视角(眼睛所在的位置)的距离。
第二个值可以为top|bottom|center|百分比|length,表示向y轴方向移动视角(眼睛所在的位置)的距离。
第三个值只能是具体的length,表示视角向z轴方向移动的距离。
背面隐藏(backface-visibility)
属性定义当元素不面向屏幕时是否可见。如果在旋转元素不希望看到其背面时,该属性很有用。默认值是visible,背面可见。
当设置了backface-visibility:hidden;的时候,当一个元素旋转知道完全翻了一个面的时候,那么这个元素将会不可见。
3d方法
3d方法有三个,分别为位移、缩放、旋转。
1、translate3d(位移)
translate3d(x位移,y位移,z位移)
或者分开写:translateX()、translateY()、translateZ(),注意translate后面不跟3d
2、scale3d(缩放)
scale3d(x 宽缩放的倍数,y 高缩放的倍数,z 元素在z轴的缩放倍数[注意:缩放的是translateZ的值])
当然也可以分开写,如位移的写法一致。
tip:当scaleZ() 或者scale3d单独使用的时候,没有任何的效果。需要和其他的属性搭配使用
3、rotate3d(旋转)
rotate3d(x,y,z,angle)中,x,y,z值分别为矢量值,分别用来描述元素围绕x/y/z轴旋转, 取值范围在0-1之间。 angle代表元素在3D空间旋转的角度,正值的话为顺时针,负值的话为逆时针。一般不建议合起来写。
如何通过rotate3d转换成rotateX() rotateY() rotateZ() ?
rotateX(a)函数功能等同于rotate3d(1,0,0,a)
rotateY(a)函数功能等同于rotate3d(0,1,0,a)
rotateZ(a)函数功能等同于rotate3d(0,0,1,a)
总结
前面已经说过了,其实css3里面没有真正的3d,只有通过一些平面元素做一些3d的转换得到伪3d效果,然后将各个元素拼一块,这样就得到了一个看起来是3d物体的元素。
下面展示一下正方体的效果:
接下来上代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>正方体</title>
<style>
body {
position: relative;
width: 1000px;
margin: 100px auto;
background-color: #00CCFF;
perspective: 1300px;
}
#cube {
left: 50%;
margin-left: -150px;
margin-top: 150px;
width: 200px;
height: 200px;
position: absolute;
transform-style:preserve-3d;
transform: rotateX(52deg) rotateY(42deg) rotateZ(68deg);
}
#cube div {
width: 100%;
height: 100%;
position: absolute;
/*left: 0;
top: 0;*/
text-align: center;
line-height: 200px;
font-size: 40px;
color: #000;
border: 1px #000 solid;
opacity: 0.5;
transform-origin: top left;
}
.top {
background-color: red;
transform: rotateX(90deg);
}
.bottom {
background-color: blue;
transform: translateY(200px) rotateX(90deg);
}
.left {
background-color: teal;
transform: rotateY(-90deg);
}
.right {
background-color: yellow;
transform: translateX(200px) rotateY(-90deg);
}
.front {
background-color: green;
transform: translateZ(200px);
}
.back {
background-color: brown;
}
</style>
</head>
<body>
<div id="cube">
<div class="top">top</div>
<div class="bottom">bottom</div>
<div class="left">left</div>
<div class="right">right</div>
<div class="front">front</div>
<div class="back">back</div>
</div>
</body>
</html>