-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
前端中的变换矩阵 #1
Comments
赞!! |
学习了,很棒的文章!!! |
牛逼 |
这里可以举个例子嘛 transform-origin的坐标系变换矩阵是怎么样的 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
在一票教你如何制作立方体的教程之后,在张鑫旭生动的类比讲解1 2之后,我还想重提一次前端中的变换矩阵——它被挖掘得远远不够。
本文里,让我们从W3C标准和浏览器等新角度来重新理解变换矩阵。
变换矩阵的综合应用
在开始前,我们不妨看动画库bouncejs来热身一下。
一个动画如果要给人带来愉悦、动人甚至是惊艳的感觉,它首先要足够贴近我们的经验,否则我们理解不了动画过程;其次,它还要有充沛的细节,否则会显得单调乏味。
bouncejs这个库就同时做到了这两点。
我们知道CSS3中的时间函数其实是非常残缺的,它最复杂也不过是生成一个有四个参数的三次贝塞尔曲线,还远远不够我们对于动画细腻程度的追求。如果细窥bouncejs的实现,我们会发现它用到了线性的时间函数,而在keyframes中表达动画细节,用到了一大堆matrix3d:
如何实现:我们想要的动画中的回弹、硬直等效果如何拆解为这些matrix3d的呢?
背后机制:这些matrix3d是如何组合成我们想要的动画效果的呢?
变换矩阵的用法
先来看看变换矩阵在各处的表现形式吧。
CSS中的变换矩阵
也许是我们第一次接触变换矩阵的地方。
SVG中的变换矩阵
SVG作为可缩放矢量图形,它局限于2D坐标中,因此它只有二维变换:
注意,由于SVG没有transform-origin属性,因此需要自己用translate来模拟。
可参考:
CANVAS中的变换矩阵
首先是2d Context中的变换矩阵。
它跟SVGMatrix接口一样,因此也不支持transform-origin,需要用translate模拟。
可参考:
IE中的filter变换矩阵
一个遗留的接口,不做多介绍。
可见:张鑫旭:IE矩阵滤镜Matrix旋转与缩放及结合transform的拓展。
JS中的变换矩阵
DOM接口
我们可以用
getComputedStyle
来获取到相应的transform参数,获得的值是一个字符串。矩阵包装器
webkit浏览器和IE曾经支持私有的包装器(
WebkitCSSMatrix
和MSCSSMatrix
),可以在得到字符串以后协助我们做一些矩阵运算,但目前已被浏览器废弃。我们可以自己实现一个类似的包装器,可参考github: CSSMatrix。
此外,在THREE.JS中也存在包装器
THREE.Matrix4
。数学中的变换矩阵
变换矩阵的实质为一组线性变换的系数矩阵。变换的目标为坐标。
系数矩阵的应用方式,在于其用于左乘点向量的齐次坐标。
当算出的齐次坐标值不为1的时候,需要完成齐次除法 homogeneous divide,使得第四个值为1,以算出最终的坐标值。
计算过程如下图:
最后,一个变换矩阵不仅仅是描述坐标点变换,其实也描述了坐标系变换(基变换)。
变换矩阵的乘法
需要注意的是,变换矩阵的乘法是不符合乘法交换律的。可参考:
一些特殊情况下,矩阵A乘以矩阵B正好等于矩阵B乘以矩阵A。
常规的例子是单位矩阵E左乘或右乘A,都将得到A。
一个很简单的理解:单位矩阵其实代表了
x'=x
、y'=y
...的方程组的系数矩阵。变换矩阵的局限性
再怎么变换,变换矩阵都是一个线性变换,无法将直线变成曲线。所以鱼眼之类的效果不能简单的用变换矩阵来完成。
标准中的变换矩阵
影响变换矩阵的属性
变换中心点:
transform-origin
上文已有DEMO实例。变换中心点功能是由变换矩阵左乘坐标位移矩阵P,和右乘坐标位移矩阵的逆矩阵P-1,来影响结果的:
变换透视:
perspective
、perspective-origin
从CSSTricks里面借一张图:
上图中眼睛位置相关的三个坐标可以借由这些属性调整:
perspective
perspective-origin
父子坐标系共享:
transform-style
变换:
transform
2d
3d
如何算得最终变换矩阵
变换矩阵的动画
平常动画过程中,有两个概念:
t=f(tNow, tTotal)
tNow:经过时间
tTotal:总时间
s=g(t, xStart, xEnd)
t:插值比例
xStart:开始值
xEnd:结束值
对于变换矩阵,会采用线性的插值方式吗?请参考:
根据标准,矩阵插值的方式是这样的:
浏览器中的变换矩阵
benchmark: transform matrix和transform function哪个更快
to be continued
Chrome中的变换矩阵
了解了数学中的相关概念,我们即可参考源码中变换矩阵的实现方式了。
SK_API::SkMatrix44
包含了对矩阵本身的定义、矩阵相关的数据类型和矩阵的基础计算。
这个类是矩阵相关的最基础的4*4的矩阵数据结构。
源码:
包含:
SkMScalar
类,根据编译选项可用于表示float或double;set*()
为设置当前矩阵为某变换对应的矩阵,而pre*()
和post*()
则为在某项变换之后或之前的变换操作,也可以理解为某个变换矩阵的左乘或右乘;determinant()
为求矩阵的行列式;invert()
求逆矩阵;transpose()
转置矩阵;computeTypeMask()
方法展示了如何通过计算得到一个变换矩阵是否包含如下变换:gfx::transform
这个类映射到CSS中的transform声明。
源码:
包含:
Translate();
Translate3d();
Scale();
Scale3d();
RotateAboutXAxis();
RotateAbout();
ApplyPerspectiveDepth()
PreconcatTransform();
ConcatTransform();
IsScale2d()
IsApproximatelyIdentityOrTranslation()
GetInverse()
Transpose();
Blend()
gfx::transform_util
包含变换相关的一些数学计算功能、除了矩阵以外的数据类型定义。
源码:
包含:
Point
和矩形类Rect
DecomposedTransform
矩阵插值过程中的类,包含各个变换相关的特征值向量:translate[3]
scale[3]
skew[3]
perspective[4]
quaternion[4]
,用于旋转。不用常规的三变量表示方法是为了避免欧拉锁问题。DecomposedTransform
的方法DecomposeTransform()
BlendDecomposedTransforms()
,由DecomposeTransform
参与的插值方法Slerp()
,用于四元数的球面插值方法Length3()
Dot()
Normalize()
TransformAboutPivot
The text was updated successfully, but these errors were encountered: