给本身出了一道题以下:css
在某个大矩形中心有一个黄色
的矩形,对该黄色矩形进行一系列transform
变换获得灰色矩形;html
以大矩形中心为坐标原点
,屏幕水平向左为X 轴正方向
,屏幕垂直向上为Y 轴正方向
,黄色矩形初始位置中心在坐标原点,根据其宽高能够获得其初始位置四个顶点的坐标initPoints
;css3
那么求黄色矩形通过一系列变换后新的顶点坐标。git
在线地址:newbieyoung.github.io/CSS_learn/t…github
其实无论 CSS3 transform 属性 有多复杂,都是能够经过getComputedStyle
直接得到最终变换矩阵的,具体方法实现以下:web
//得到transform属性对应的矩阵形式
function getTransformMatrix(transform){
var $div = document.createElement('div');
$div.style.visibility = 'hidden';
$div.style.position = 'fixed';
//处理transform属性的兼容性
var transformProperty = 'transform';
if('transform' in $div.style){
transformProperty='transform'
} else if( 'WebkitTransform' in $div.style ){
transformProperty='webkitTransform'
} else if('MozTransform' in $div.style){
transformProperty='MozTransform'
} else if('OTransform' in $div.style){
transformProperty='OTransform'
}
$div.style[transformProperty] = transform;
document.body.appendChild($div);
var style = window.getComputedStyle($div);
var matrix = style[transformProperty];
document.body.removeChild($div);
return matrix;
}
复制代码
经过getTransformMatrix
函数能够得到如下形式的变换矩阵:bash
matrix(a, b, c, d, e, f);
matrix(0.430963, 1.01542, -0.234879, 1.76697, 5, 40)
复制代码
转换为三阶矩阵:app
[a, c, e,
b, d, f,
0, 0, 1];
复制代码
不知道你们想过没有,明明是2D
变换,转换为三阶
矩阵干啥?wordpress
其实这里是引入了一个齐次坐标
的概念,用N+1
维的向量来表示N
维向量;函数
好比在2D
坐标系中某个点(x, y)
能够在逻辑上表示为(x*w, y*w, w)
,w
即为新增的那个量。
引入齐次坐标的好处在于能够把缩放
、旋转
、平移
等变换都统一转换成矩阵乘法的形式,这样无论进行多少次变换,均可以表示成矩阵连乘的形式了。
若是某个 2D 坐标系中点为(x, y)
,转换为齐次坐标(x, y, 1)
,那么通过上述变换后的新坐标为(nx, ny, nz)
:
nx = a * x + c * y + 1 * e;
ny = b * x + d * y + 1 * f;
nz = 0 + 0 + 1;
复制代码
再把齐次坐标还原,最终坐标为(nx, ny)
。
具体方法实现以下:
//计算矩阵变换后的坐标点
function getMatrixPoints(p,matrix){
var mat = matrixAnalyze(matrix);
// var mat3 = [mat[0],mat[2],mat[4],
// mat[1],mat[3],mat[5],
// 0,0,1];
// var mat3 = [a,c,e,
// b,d,f,
// 0,0,1];
// var newX = a * x + c * y + 1 * e;
// var newY = b * x + d * y + 1 * f;
// var newZ = 0 + 0 +1;
//计算变换后点坐标
var newX = mat[0] * p.x + mat[2] * p.y + 1 * mat[4];
var newY = mat[1] * p.x + mat[3] * p.y + 1 * mat[5];
var newZ = 0 + 0 +1;
return {x:newX/newZ,y:newY/newZ};
}
复制代码
已知初始坐标initPoints
和变换矩阵matrix
相乘便可获得matrixPoints
,到这里我觉得这个题目已经解完了;
直到我尝试着在大矩形中用红色
直线把计算获得的matrixPoints
连起来才发现:新坐标链接获得的图形和 CSS3 transform 变换获得灰色图形并不重合
;
这也就意味着上述计算过程有问题
!
在走了很多弯路以后我才意识到一个问题:CSS3 2D transform 坐标系和题目中设定的坐标系的 Y 轴正方向是相反的
;
题目中设置的坐标系 Y 轴正方向是屏幕垂直向上而 CSS3 2D transform 坐标系的 Y 轴正方向是屏幕垂直向下。
所以在计算新坐标以前,须要对getComputedStyle
获得的变换矩阵进行镜像变换
,从而转换为题目中设定坐标系的变换矩阵,也就是示例中fixedMatrix
,最后计算的新坐标为fixedPoints
。
用蓝色
直线绘制出来就能够看到和灰色图形彻底重合了。
聊矩阵不聊坐标系都是耍流氓!
此外张鑫旭
大神2012
年的这篇文章理解CSS3 transform中的Matrix(矩阵)应该是有比较大问题的。
文中屡次出现方向不明、坐标轴错误
的坐标系,若是有看到建议改下。