CSS3属性之transform 矩阵转换深入讨论(2D)

一、何为矩阵

矩阵如同现实中的方阵,只不过,方阵中的是人,矩阵中的是数值。

现实中的方阵:


而矩阵则是:

所谓矩阵的计算,就是相当于两个方阵的较量。

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);

其6个参数对应的矩阵是:


注:写法是竖着的。


坐标变换的公式为:


其中,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(前面,四个,与我,无关,水平偏移距离,垂直偏移距离);

translate方法只与matrix()方法的e,f参数有关。即:translate(e,f)



四、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  背面不可见。




  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值