网站首页 » 前端开发 » CSS3 » CSS3 transform 你知多少?
上一篇:
下一篇:

CSS3 transform 你知多少?

transform 属于CSS3 的新属性。这个属性可以让我们实现很多以前只能通过 JavaScript 来实现的效果。比如元素的运动(缩放、旋转……)。所以这个新属性还是有必要用专门一篇文章来介绍它。毕竟它让我们通过了另一种方式让网页走向多姿多彩的世界。如果你觉得 transform 只能给你带来一点点便利,那么你就大错特错了,因为 transform 除了可以实现 2D 效果外,它还可以实现 3D 效果。现在让我们开始 transform 的未知之旅。

Transform 能做什么?

正如我们前面说到的 Transform 属性可以实现元素的 2D 或 3D 转换。这个属性允许你将元素进行移动,旋转,缩放,倾斜等。

Transform 语法

(2D)-webkit-transform: none | matrix(<number>,<number>,<number>,<number>,<number>,<number>)? translate(<length>[,<length>])? translateX(<length>)? translateY(<length>)? rotate(<angle>)? scale(<number>[,<number>])? scaleX(<number>)? scaleY(<number>)? skew(<angle>[,<angle>])? skewX(<angle>) | skewY(<angle>)?  
(3D)-webkit-transform: matrix3d(<number>,<number>,<number>,<number>,<number>,<number>,<number>,<number>,<number>)? translate3d(<length>,<length>,<length>)? translateZ(<length>)? rotate3d(<length>,<length>,<length>,<angle>)? scale3d(<number>,<number>,<number>)? scaleZ(<number>)? perspective(<number>)?

对于上面的语法你大可不必理会,因为下面这个表格才是你的秘籍。

属性值 详细说明
none 无转换。
matrix(…) 以一个含六值的(a,b,c,d,e,f)变换矩阵的形式指定一个2D变换,相当于直接应用一个[a,b,c,d,e,f]变换矩阵。
translate(<lengtd>[, <lengtd>]) 指定对象的2D translation(2D平移)。第一个参数对应 X 轴,第二个参数对应 Y 轴。如果第二个参数未提供,则默认值为0。
translateX(<lengtd>) 指定对象 X 轴(水平方向)的位移。
translateY(<lengtd>) 指定对象 Y 轴(垂直方向)的位移。
rotate(<angle>) 指定对象的 2D rotation(2D旋转),需先定义 transform-origin 属性。
rotateX(<angle>) 指定对象的沿着 X 轴的旋转
rotateY(<angle>) 指定对象的沿着 Y 轴的旋转
scale(<number>[, <number>]) 指定对象的2D scale(2D缩放)。第一个参数对应 X 轴,第二个参数对应 Y 轴。如果第二个参数未提供,则默认取第一个参数的值。
scaleX(<number>) 指定对象 X 轴的(水平方向)缩放。
scaleY(<number>) 指定对象 Y 轴的(垂直方向)缩放。
skew(<angle> [, <angle>]) 指定对象skew transformation(斜切扭曲)。第一个参数对应 X 轴,第二个参数对应 Y 轴。如果第二个参数未提供,则默认值为0。
skewX(<angle>) 指定对象 X 轴的(水平方向)扭曲。
skewY(<angle>) 指定对象 Y 轴的(垂直方向)扭曲。
matrix3d(…) 以一个含 16 值的 4×4 变换矩阵的形式指定一个 3D 变换。
translate3d(<lengtd>,<lengtd>,<lengtd>) 指定对象的 3D translation(3D 平移)。第一个参数对应X轴,第二个参数对应 Y 轴,第三个参数对应 Y 轴。
translateZ(<lengtd>) 指定对象Z轴(垂直于屏幕平面)的平移。
rotate3d(<lengtd>,<lengtd>,<lengtd>,<angle>) 指定对象的 3D rotation(3D 旋转)。在前三个参数构成的向量上旋转。
rotateZ(<angle>) 指定对象的沿着 Z 轴的旋转
scale3d(<number>,<number>,<number>) 指定对象在 X 轴(水平方向)、Y 轴(垂直方向)、Z 轴(垂直于屏幕平面)的缩放。
scaleZ(<number>) 指定对象 Z 轴的(垂直于屏幕平面)缩放。
perspective(<number>) 指定对象的视角(元素景深:让效果更立体,更接近现实)。根据参数对指定对象在 X 轴和 Y 轴上缩放。

Transform 基本套路

在使用 transform 时最好同时添加如下前缀:

-webkit-transform: translate(10px, 10px); /* Safari 和 Chrome */
-moz-transform: translate(10px, 10px); /* Firefox */
-ms-transform: translate(10px, 10px); /* IE 9 */
-o-transform: translate(10px, 10px); /* Opera */
transform: translate(10px, 10px); /* 标准 */

而在移动端,我们只需要两个就可以了:

-webkit-transform: translate(10px, 10px);
transform: translate(10px, 10px);

下面所有的例子我们都使用移动端的兼容方式。也就是说只留一个-webkit-transform 和 一个 transform。

基本结构及样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="widtd=device-widtd, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>transform 详解-云库网</title>
    <meta name="description" content="transform 详解,translate(),scale(),skew(),rotate(),perspective()" />
    <meta name="keywords" content="transform 里的 translate、scale、skew、rotate、perspective 属性详解" />
    <link rel="stylesheet" href="./css/index.css">
</head>
<style>
    * {
        padding: 0;
        margin: 0;
    }

    .box {
        background: #ccc;
        height: 200px;
        width: 200px;
    }
</style>
<body>
    <div class="box"></div>
</body>
</html>

 CSS 方式添加

添加单个属性

.box {
    background: #ccc;
    height: 200px;
    width: 200px;
    -webkit-transform: translate(10px, 10px);
    transform: translate(10px, 10px);
}

同时添加多个属性

.box {
    background: #ccc;
    height: 200px;
    width: 200px;
    -webkit-transform: translate(10px, 10px) scale(0.5) skew(30deg, 30deg);
    transform: translate(10px, 10px) scale(0.5) skew(30deg, 30deg);
}

要想同时添加多个属性,你就可以像上面那样处理:属性间用空格隔开。

授课时间

如果 transform 中有多个属性,那么会从最后一个属性开始执行,比如上面的例子,执行顺序为:skey – scale – translate,正好跟书写样式的顺序反过来。

JavaScript 方式添加

在 JavaScript 中如何设置 transform 呢?其实跟在CSS 中设置的方法是差不多的,不过在这里也有必要贴出一个例子来,以便加深你对transform 的印象。

<script>
    var oBox = document.querySelector(".box");

    // 单属性设置
    oBox.style.webkitTransform = oBox.style.transform = "translate(10px, 10px)";

    // 多属性设置 
    oBox.style.webkitTransform = oBox.style.transform = "translate(10px, 10px) scale(0.5) skew(30deg, 30deg)";
</script>

上在上 oBox.style.webkitTransform = oBox.style.transform 这个写法你不要觉得奇怪,如果你觉得看起来不舒服,其实你也可以改成下面的形式:

<script>
    var oBox = document.querySelector(".box");

    // 单属性设置
    oBox.style.webkitTransform = "translate(10px, 10px)";
    oBox.style.transform = "translate(10px, 10px)";

    // 多属性设置 
    oBox.style.webkitTransform = "translate(10px, 10px) scale(0.5) skew(30deg, 30deg)";
    oBox.style.transform = "translate(10px, 10px) scale(0.5) skew(30deg, 30deg)";
</script>

没有对比就没有伤害,如果你把这两种写法放在一起你就会发现,第一种方法更加精简,所以在这里推荐使用第一种方法。

transform 2D

关于原点

对于 scale()、skew()、rotate() ,它们还有一个叫做原点的东西,你可以通过 transform-origin 来设置这个原点的位置。原点的默认值为 transform-origin: center center; 即围绕着元素的中心点来变化(如:rotate() 在默认的情况下就是围绕着元素的中心点来旋转的。),其它两个也同样道理。

transform-origin 的取值有三种:关键字(center、top、bottom、left 的两两组合)、百分比或者固定单位(px、rem、em等)。

如果是百分比或者固定单位,就会从元素的左上角开始计算原点的位置,比如:想把元素左上角设置为原点那么就可以这样写 transform-origin :0 0。你可以像下面这样使用它:

.box {
    background: #ccc;
    height: 200px;
    width: 200px;
    margin: 0 auto;
    -webkit-transform: rotate(30deg);
    transform: rotate(30deg);
    -webkit-transform-origin: 0 0;
    transform-origin: 0 0;
}

transform 获取

transform 的获取不像一般的 CSS 样式那么可以直接通过 getComputedStyle(oBox)[“transform”]来获取,为什么?请运行下面的代码:

<script>
    var oBox = document.querySelector(".box");
    console.log(getComputedStyle(oBox)["transform"]);
</script>

此时你会看到控制台里打印出来的是一个矩阵,如:

matrix(1, 0, 0.57735, 1, 0, 0)

至于这个结果里面的数值分别是什么,我们在后面会讲到,但是也不是无法获取。比如我们可以直接在元素上通过 style=”-webkit-transform: skew(30deg); transform: skew(30deg);” 来添加样式,然后再通过 oBox.style.transform 来获取这个属性的值,这种方法是可以获取到正常的值的,可以看看这个DEMO:http://yunkus.com/demo/transform/transform-get-style-inline.html,切换到控制台端就可以看到打印出“skew(30deg, 30deg) scale(0.5)”的字样了。

但这显示不是一个明智的做法,比如:你可能不喜欢给元素添加行内样式,还有当transform 里添加了多个值后,你还得通过一定的方法(如:正则表达式)来分别获取到这些属性值,所以笨的方法其实也不简单。那么有没有其实方法呢?答案是肯定的,后面就会有。

matrix

matrix(a, b, c, d, e, f),对于 2D 来说 matrix 有六个参数:a、b、c、d、e、f,互相组合实现不同的变换效果。

参数说明

a:水平缩放绘图

b:垂直倾斜绘图

c:水平倾斜绘图

d:垂直缩放绘图

e:水平移动绘图

f:垂直移动绘图

scale()[scaleX 和 scaleY ]:对应修改 a、c、e、f  四个值。

translate() [translateX 和 translateY]:对应修改 e、f 两个值。

skew()[skewX 和 skewY]:对应修改的是 b、c、e、f 四个值。

在 transform 2D 中矩阵的默认值为 matrix(1, 0, 0, 1, 0, 0),现在我们用 transform 的几个属性来说明下属性与matrix 之间的转换。

translateX()

水平移动50px

-webkit-transform: translateX(50px); 
/* 结果:matrix(1, 0, 0, 1, 50, 0) */

DEMO:http://yunkus.com/demo/transform/transform-translateX.html

translateY()

垂直移动50px

-webkit-transform: translateY(50px);
/* 结果:matrix(1, 0, 0, 1, 0, 50) */

DEMO:http://yunkus.com/demo/transform/transform-translateY.html

scaleX()

水平缩放为原来的 0.5 倍

-webkit-transform: scaleX(0.5);
/* 结果:matrix(0.5, 0, 0, 1, 0, 0) */

DEMO:http://yunkus.com/demo/transform/transform-scaleX.html

scaleY()

垂直缩放为原来的 0.5 倍

-webkit-transform: scaleY(0.5);
/* 结果: matrix(1, 0, 0, 0.5, 0, 0)*/

DEMO:http://yunkus.com/demo/transform/transform-scaleY.html

scaleX | translateX()

如果同时进行两个变换,这个值又是什么呢?

-webkit-transform: scaleX(0.5) translateX(100px);
/* 结果:matrix(0.5, 0, 0, 1, 50, 0) */

DEMO:http://yunkus.com/demo/transform/transform-scaleX-translateX.html

有意思的是当我们把这两个属性的顺序调换一个后, matrix 的值竟然还不一样

-webkit-transform: translateX(100px) scaleX(0.5);
/* 结果:matrix(0.5, 0, 0, 1, 100, 0) */

DEMO:http://yunkus.com/demo/transform/transform-translateX-scaleX.html

skewX()

水平倾斜30度

-webkit-transform: skewX(30deg);
/* matrix(1, 0, 0.57735, 1, 0, 0) */

DEMO:http://yunkus.com/demo/transform/transform-skewX.html

skewY()

垂直倾斜30度

-webkit-transform: skewY(30deg);
/* matrix(1, 0.57735, 0, 1, 0, 0) */

DEMO:http://yunkus.com/demo/transform/transform-skewY.html

说到 skew,我们不得不回味下前面表格里的对于它的定义:指定对象skew transformation(斜切扭曲)。第一个参数对应 X 轴,第二个参数对应 Y 轴。如果第二个参数未提供,则默认值为0。skew() 与 scale() 两个函数都只传一个参数时,它们的处理方式是不一样的,这一点我们应该要记住。

这里的斜切其实就是我们数学里的正切(tan),由于tan 要传的是弧度,所以我们得先把上面的角度30转换成弧度(弧度 = deg * Math.PI / 180),然后再用Math.tan()函数处理下就可以得到同样的值了:

DEMO:http://yunkus.com/demo/transform/transform-matrix-and-tangent.html

查看上面的这个例子你就会看到两个一样的结果了,只是 Math.tan() 讲算出来的值保留了更多的小数位。

// ---transform 计算出来的值---
matrix(1, 0, 0.57735, 1, 0, 0)
// ---Math.tan() 直接计算出来的值---
0.5773502691896257

下面我们分别通过计算matrix 的值与 直接设置transform 后所得出的matrix值进行比较,用以说明transform 的执行顺序问题:后写先执行。

-webkit-transform: scale(0.5) translate(100px,100px);
-webkit-transform: translate(100px, 100px) scale(0.5);
/*
---webkit-transform: scale(0.5) translate(100px, 100px);---
matrix(0.5, 0, 0, 0.5, 50, 50)
---webkit-transform: translate(100px, 100px) scale(0.5);---
matrix(0.5, 0, 0, 0.5, 100, 100)
*/

DEMO:http://yunkus.com/demo/transform/transform-scale-translate.html

现在我们结合前面说到的 matrix 里各个参数与属性之间的关系来计算出 -webkit-transform: scale(0.5) translate(100px, 100px); 和 -webkit-transform: translate(100px, 100) scale(0.5);所对应的 matrix 值。我们按照先写后执行来进行计算。

-webkit-transform: scale(0.5) translate(100px, 100px);  
/* 
 * translate(100px, 100px):在 maxtrix(1, 0, 0, 1, 0, 0)默认值的基础上参数 e、f 分别加100
 * 结果:matrix(1, 0, 0, 1, 100, 100) 
 * scale(0.5):在 matrix(1, 0, 0, 1, 100, 100) 的基础上 a、b、c、d、e、f 六个参数分别乘以0.5 ,六个参数都乘以 0.5 是因为水平垂直方向都进行了缩放。
 * 结果:matrix(0.5, 0, 0, 0.5, 50, 50)
*/
-webkit-transform: translate(100px, 100px) scale(0.5);  
/*
 * scale(0.5):在 maxtrix(1, 0, 0, 1, 0, 0)默认值的基础上 a、b、c、d、e、f 六个参数分别乘以0.5。
 * 结果:matrix(0.5, 0, 0, 0.5, 0, 0) 
 * translate(100px, 100px):在 matrix(0.5, 0, 0, 0.5, 0, 0) 的基础上参数 e、f 分别加100
 * 结果:matrix(0.5, 0, 0, 0.5, 100, 100)
*/
提示

scale(0.5) 等价于 scale(0.5,0.5),因为前面的表格中有这么一句话:。第一个参数对应 X 轴,第二个参数对应 Y 轴。如果第二个参数未提供,则默认取第一个参数的值。所以当只有一个值时,相当于x=y=0.5

当你把人工计算了来的 matrix 结果与 DEMO 在浏览器中打印出来的 matrix 结果进行对比,你就会发现 结果是一样的。

transform 3D

transform 3D 对应的matrix 参数就不是6个,而是变成了16个。

这里需要注意的是:rotate() 方法为属于 2D 属性,但rotateX()、rotateY() 、rotateZ() 这三个就属于 3D 属性。如果你不信可以分别试试这几个属性。rotate() 对应的matrix()的参数只有6个,而不是像后面的那三个属性的参数都是16个。由于30度太小,演示效果不明显,为了更好的说明问题,所以后面的几个例子是在 60 度下测试的。

rotate3d() 属性

-webkit-transform: rotateX(60deg);
/* matrix3d(1, 0, 0, 0, 0, 0.5, 0.866025, 0, 0, -0.866025, 0.5, 0, 0, 0, 0, 1) */

DEMO:http://yunkus.com/demo/transform/transform-rotateX.html

-webkit-transform: rotateY(60deg);
/* matrix3d(0.5, 0, -0.866025, 0, 0, 1, 0, 0, 0.866025, 0, 0.5, 0, 0, 0, 0, 1) */

DEMO:http://yunkus.com/demo/transform/transform-rotateY.html

-webkit-transform: rotateZ(60deg);
/* matrix(0.5, 0.866025, -0.866025, 0.5, 0, 0) */

DEMO:http://yunkus.com/demo/transform/transform-rotateZ.html

transform-perspective 属性

但单单只有这样的旋转是不够的,为了让元素变换看起来更逼真,我们可以给元素的父元素添加一个 perspective 属性。这个属性可以让元素有一个近大近小的景深效果,请看下面的例子:

DEMO:http://yunkus.com/demo/transform/transform-perspective.html

除了rotate 外,上面的表格中有带 3D 的属性,都可以实现 3D 效果变换。对于 3D 效果,你可以通过给父级添加 perspective 属性来让元素展现得更加逼真。

当父级元素和子元素同时添加了3D 效果时,我们还得给父元素添加一个属性:transform-style,这个属性有两个值:preserve-3d(保留主子元素的3D效果)和 flat(不保留子元素 3D 效果)

请看这个美美的DEMO:http://yunkus.com/demo/transform/transform-style.html,画面太动感,宝宝表示备受感动。

perspective-origin 属性

我们还可以从不同的角度来看3D效果,只需要给添加了-webkit-perspective  的元素添加  perspective-origin 属性就可以了。

来看看这个DEMO 跟上面那个有什么不同:http://yunkus.com/demo/transform/transform-perspective-origin.html

backface-visibility 属性

backface-visibility 属性可以让相对于父级的背景面元素隐藏,这个属性在做一些变换时用得也比较多,为了说明问题请看下面这个简单的例子。

DEMO:http://yunkus.com/demo/transform/transform-backface-visibility.html

代码中我们通过给两个 div.item 添加 -webkit-backface-visibility: hidden; 属性来实现隐藏背面的效果。在这里我们需要注意的是,这个属性是对当前正处于背面的元素起作用,也就是这个属性需要加在如:-webkit-transform: rotateY(180deg); 的元素上,即此元素 rotateY 值等于 180 度(成为父级背面) 时隐藏此元素。如果你的目的性比较明确只想隐藏一个面时,你可以单独设置 div.item 元素。

transform 获取|与设置

关于 transform 的样式我们是不能够通过 常规的方法来获取到 transfrom 的属性的,因为它返回来的是一个不可逆的矩阵。所以我们需要别找方法来获取对象的 transform 属性。下面是一个例子,你可以打开浏览器的控制台-查看元素来获取结果。这个方法虽然可以获取到“像样”的属性及属性值了,但是有一点必需得有一个前提:所要获取的属性必需也是通过这个函数设置的。

DEMO:http://yunkus.com/demo/transform/transform-cssTransfrom.html

 

 

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/transform/

Leave a Reply

Your email address will not be published. Required fields are marked *

评论 END