一、何为矩阵
矩阵如同现实中的方阵,只不过,方阵中的是人,矩阵中的是数值。
现实中的方阵:
而矩阵则是:
所谓矩阵的计算,就是相当于两个方阵的较量。
CSS3中的矩阵
CSS3中的矩阵指的就是一种算法,书写为matrix()和matrix3d(),前者是元素2D平面的移动变换,后者是元素3D变换。2D变换矩阵是3*3,如同上图一样,3D变换矩阵则是4*4的矩阵。
熟悉transform属性的都知道,transform有以下的属性方法:
.div { transform: translate(20px,30px);}
.div { transform: rotate(60deg);}
.div { transform: skew(35deg);}
.div { transform: scale(1,0.4);}
分别为 translate(偏移)、rotate(旋转)、skew(拉伸)、scale(缩放)等属性方法。
那有没有想过,为什么 transform: rotate(60deg); 会让元素旋转60度呢?它后面运行的机制是什么?
我们可以理解为:
无论是旋转还是拉伸什么的,都是通过matrix()实现的(通过改变固定的值),只是类似于transform: rotate(60deg); 这种表现形式,人们更容易理解,方便记忆而已。
也是就是说,理解transform中的matrix()矩阵方法,更能让人深入理解css3中的transform属性。
二、transform与坐标系统
通过transform旋转的人可以发现,其默认是绕着中心点旋转的,也就是transform-origin对应的点,也是所有矩阵计算的一个重要依据。
transform-origin属性
transform-origin属性设置元素的偏移中心坐标。元素默认的中心坐标是元素的中间位置。
当我们通过transform-origin属性进行设置的,矩阵的相关计算也随之改变,表现出来的效果就是 旋转拉伸中心点的改变。
例如:我们设置以右下角为中心点,那么图片基于右下角缩放:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>2D/3D转换属性</title>
<style>
#pho {
width: 410px;
height: 220px;
border: 1px solid red;
}
#pho img {
width: 410px;
height: 220px;
-webkit-transform-origin: right bottom ; /* 坐标中心为右下角 */
-webkit-transform: scale(0.5); /* 基于右下角缩放 */
}
</style>
</head>
<body>
<div id="pho">
<img src="pho.jpg" alt="pho">
</div>
</body>
</html>
效果如下:
再举一个例子:我们设置
-webkit-transform-origin: 50px 70px ; /* 以像素50px 70px 为中心点 */
效果如下:
此时中心点(0,0)的位置,距离左边50像素,距离顶部70像素,(30,30)后面会用到。
三、matrix()
CSS3中transform的matrix()方法写法如下:
transform: matrix(a,b,c,d,e,f);
注:写法是竖着的。
坐标变换的公式为:
其中,x,y表示转换元素的所有坐标(变量),那么后面的ax + cy + e是怎么来的呢?
很简单,根据矩阵算法:3*3矩阵中第一行的第1个值与后面1*3的第1个值相乘,第2个值与第2个相乘,第3个与第3个,然后相加,如下图同色标注:
ax + cy + e为变换后的水平坐标,bx + dy + f为变换后的垂直坐标。
在进行变换时,需要设置矩阵参数
设置矩阵参数:默认矩阵参数matrix(1,0,0,1,0,0)
transform: matrix(1,0,0,1,30,30); /* a = 1, b =0, c = 0,d =1, e = 30, f = 30 */
现在根据矩阵的中心点,假设为(0,0),即x = 0,y = 0。
变换后的水平坐标 x 是ax + cy + e = 1*0 + 0*0 + 30 = 30,变换后的垂直坐标 y 是bx + dy + f = 0*0 + 1*0 + 30 = 30。
于是,中心坐标由(0,0)变成了(30,30),对照上面的白点(30,30)可以发现,原来(0,0)的位置移动到了(30,30)的位置,是不是向右下偏移了30像素呢。
其实,transform: matrix(1,0,0,1,30,30)就等同于transform: translate(30px,30px),注意:偏移、旋转都需要单位的,而matrix()方法不需要单位。
下面举个实用的例子更好地理解matirx()方法:
用translate()方法将图片向右、向下移动30像素的距离:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>2D/3D转换属性</title>
<style>
#pho {
width: 410px;
height: 220px;
border: 1px solid red;
}
#pho img {
width: 410px;
height: 220px;
-webkit-transform: translate(30px,30px);
-o-transform: translate(30px,30px);
-moz-transform: translate(30px,30px);
-mos-transform: translate(30px,30px);
transform: translate(30px,30px);
}
</style>
</head>
<body>
<div id="pho">
<img src="pho.jpg" alt="pho">
</div>
</body>
</html>
效果如下:
用matrix()方法将图片向右、向下移动30像素:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>2D/3D转换属性</title>
<style>
#pho {
width: 410px;
height: 220px;
border: 1px solid red;
}
#pho img {
width: 410px;
height: 220px;
-webkit-transform: matrix(1,0,0,1,30,30);
-o-transform: matrix(1,0,0,1,30,30);
-moz-transform: matrix(1,0,0,1,30,30);
-mos-transform: matrix(1,0,0,1,30,30);
transform: matrix(1,0,0,1,30,30);
}
</style>
</head>
<body>
<div id="pho">
<img src="pho.jpg" alt="pho">
</div>
</body>
</html>
效果如下:
我们可以看出,这两种方法的效果一样。
那么我们可以得出结论:
transform: matrix(前面,四个,与我,无关,水平偏移距离,垂直偏移距离);
四、matrix与缩放、拉伸和旋转
scale(缩放)
前面提到,偏移只与matrix()方法的e,f参数有关,那么缩放与哪几个参数有关呢?通过前面
transform: matrix(1,0,0,1,30,30);
发现,偏移与e,f参数有关,元素比例与原来一样,可以发现缩放其实与a,d参数有关,其中,a是缩放x轴,d是缩放y轴。
假设缩放比例是m,则有 matrix(m,0,0,m,0,0), 根据公式,就有:
x' = ax + cy + e = m*x + 0*y + 0 = m*x;
y' = bx + dy + f = 0*x + m*y + 0 = m*y;
也就是说,matrix(mx,0,0,my,0,0)就相当于scale(mx,my)。
举例:在水平方向上缩放比例为1,在垂直方向上缩放比例为0.5:
#pho img {
width: 410px;
height: 220px;
-webkit-transform: scale(1,0.5);
-o-transform: scale(1,0.5);
-moz-transform: scale(1,0.5);
-mos-transform: scale(1,0.5);
transform: scale(1,0.5);
}
效果如下:
用matrix()方法:
#pho img {
width: 410px;
height: 220px;
-webkit-transform: matrix(1,0,0,0.5,0,0);
-o-transform: matrix(1,0,0,0.5,0,0);
-moz-transform: matrix(1,0,0,0.5,0,0);
-mos-transform: matrix(1,0,0,0.5,0,0);
transform: matrix(1,0,0,0.5,0,0);
}
效果如下:
再者效果一样。
我们可以得出结论:
scale(缩放)与matrix()方法的a,d参数有关。
rotate(旋转)
旋转就需要用到三角函数:
假设旋转角度为α:
rotate()方法是:
transform: rotate(α + "deg");
matrix(方法)是:
transform: matrix(cosα,sinα,-sinα,cosα,0,0);
根据公式:
x' = a*x + cy + e = x*cosα - y*sinα;
y' = b*x + dy + f = x*sinα + y*cosα;
举例:scale(30deg)
#pho img {
width: 200px;
height: 100px;
-webkit-transform-origin: 50px 255px;
-webkit-transform: rotate(30deg);
}
效果如下:
用matrix()方法:matrix(0.866025,0.500000,-0.500000,0.866025,0,0)
#pho img {
width: 200px;
height: 100px;
-webkit-transform-origin: 50px 255px;
-webkit-transform: matrix(0.866025,0.500000,-0.500000,0.866025,0,0);
}
效果如下:
效果一样。
得出结论:
假设旋转角度为α,scale(α + "deg")就相当于matrix(cosα,sinα,-sinα,cosα,0,0)
对于ie8兼容
ie8兼容写法:
filter:
progid:DXImageTransform.Microsoft.Matrix(enabled=true, sizingMethod='auto expand', M11=0.866025404, M12=0.5, M21=-0.5, M22=0.866025404) ;
四个参数:M11、M12、M21、M22分别表示cos(旋转的角度)、-sin(旋转的角度)、sin(旋转的角度)、cos(旋转的角度)。
enabled: 表示设置或检索滤镜是否激活。true表示激活检索,fale表示不激活检索。
sizingMethod: 表示设置或检索滤镜作用的对象的图片在 对象容器边界内 的显示方式。
crop : 剪切图片以适应对象尺寸。
image : 默认值。增大或减小对象的尺寸边界以适应图片的尺寸。
scale : 缩放图片以适应对象的尺寸边界。
auto : 自动适应容器大小。
skew(拉伸)
拉伸也用到三角函数,不过是tanα,与b,c两个参数有关,(y轴倾斜在前,x轴倾斜在后):
transform: matrix(1,tan(αy),tan(αx),1,0,0);
根据公式:
x' = ax + cy + e = x + tan(αx);
y' = bx + dy + f = tan(αy) + y;
也就相当于skew(αx + 'deg',αy + 'deg')的写法。
其中,αx就是在x轴方向上的倾斜角度,αy就是在y轴方向上的倾斜角度。
举例:skewX(-45deg)
#pho img {
width: 200px;
height: 100px;
-webkit-transform-origin: 50px 255px;
-webkit-transform: skewX(-45deg);
}
效果如下:
用matrix()方法:matrix(1,0.000000,-1.000000,1,0,0)
#pho img {
width: 200px;
height: 100px;
-webkit-transform-origin: 50px 255px;
-webkit-transform: matrix(1,0.000000,-1.000000,1,0,0);
}
效果如下:
得出结论:
拉伸与b,c参数有关,即:
skew(αx + "deg",αy + "deg")相当于matrix(1,tan(αy),tan(αx),1,0,0)
matrix()主要用于镜像
认识三维立体3D
3D立体坐标图:
通过rotateX()、rotateY()、rotateZ()认识3D立体
在现实生活中:
rotateX()就如:
rotateY()就如:
而rotateZ()就如:
perspective属性
perspective意思是透视、视角。这个属性允许你改变3D元素是怎样查看透视图。CSS3 3D transform的透视点是在浏览器的前方。
用translateZ: length;更容易理解,当值越在时,越远离视觉,当值越小时,越接近视觉。
定义时,它是一个元素的子元素,透视图,不是元素本身。
<div-------------元素
<box1---子元素
需为div设置perspective属性,作用于box1,而不是div本身。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>2D/3D转换属性</title>
<style>
#div1{
position: relative;
height: 150px;
width: 150px;
margin: 50px;
padding:10px;
border: 1px solid black;
perspective:90;
-webkit-perspective:90; /* Safari and Chrome */
}
#div2{
padding:50px;
position: absolute;
border: 1px solid black;
background-color: red;
transform: rotateX(45deg);
-webkit-transform: rotateX(45deg); /* Safari and Chrome */
}
</style>
</head>
<body>
<div id="div1">
<div id="div2">HELLO</div>
</div>
</body>
</html>
效果如下:
#div1{
position: relative;
height: 150px;
width: 150px;
margin: 50px;
padding:10px;
border: 1px solid black;
perspective:110;
-webkit-perspective:110; /* Safari and Chrome */
}
效果如下:
perspective-origin属性
perspective-origin属性允许设置3D元素的底部位置,即x轴、y轴的坐标。
定义时的perspective -Origin属性,它是一个元素的子元素,透视图,而不是元素本身。定义在元素,作用于其子元素,不是在元素本身。
transform-style属性
transform-style属性规定 嵌套元素 怎样在三维空间中呈显。在子元素中设置,作用于子元素。
属性值:flat--所有子元素在2D平面显示,默认值。
perverse-3d()--所有子元素在3D空间显示
backface-visibility属性
backface-visibility属性规定当元素不面向屏幕(背面)时,是否可见。当旋转元素时,不想看到其背面时,适用。
属性值:
- visible 背面是可见的。
- hidden 背面不可见。