原文链接: https://github.com/AlloyTeam/AlloyTouch/wiki/Powerful-transformjs
写在前面上星期在React微信群里,有小伙伴觉得transformjs直接给DOM添加属性太激进,不可取(由于不在那个微信群,不明白为什么React会谈到transformjs?!)。关于这点,其实在一年半前腾讯内部就有相关声音,腾讯内部的小伙伴建议,不要污染那么多吧~~,给个总的namespace,如:
(element)..
在腾讯内部,还有小伙伴建议,包裹一层把:
( dom)
总之,就是不要这样子(transformjs目前的姿势):
(element)
那么上面这种做法会有什么问题?
后来,我找到以前提修改意见的腾讯小伙伴,他给了这样的回答:
如果以后 w3c 需要给DOM元素扩展 translateX, translateY, translateZ, scaleX, scaleY, scaleZ, rotateX, rotateY, rotateZ, skewX, skewY, originX, originY, originZ,这就留下了巨大的隐患~~
对于这点,我认为,既然domElment.style.transform已经有了,扩展translateX, translateY, translateZ, scaleX, scaleY, scaleZ, rotateX, rotateY, rotateZ, skewX, skewY, originX, originY, originZ的可能性几乎没有,因为其实domElment.style.transform已经提供了足够的灵活性。就算扩展了,transformjs打个补丁包或者prolyfill 一下便可。
然后我又问了一些小伙伴,得到一个非常有趣的回答:
反正你污染了DOM,反正你污染了DOM,反正你污染了DOM....
....
条条大路通罗马transformjs不仅仅可以mix CSS3 transform到DOM元素,还能mix到任意的对象字面量,也可以把transformjs当作工具,他提供一些基础的数学能力。
这里需要特别注意,以前的姿势可以继续使用,这里另外三种使用姿势。
语法1Transform(obj, [notPerspective]);
如你所见,其他方式都不用变。只是第一个参数不仅仅可以传DOM元素,也可以传任意对象字面量等。
不卖关子,先看使用姿势
var element = document.querySelector("#test"), obj (obj)......transform;
看到了没有,你不仅可以传DOM元素进去,也可以传对象字面量。你可以把obj.transform打印出来,上面是选择了90度,所以它生成出来的matrix是:
)
你同样也可以关闭透视投影,如:
var element = document.querySelector("#test"), obj (obj.......transform;
生成出来的matrix是:
)
那么运动的姿势呢?这里配合tween.js的示例如下:
var element = document.querySelector("#test"), obj (obj).Tween(obj) .) ......) .(time) .update(time); }
那么如果用传统的姿势是?
(element)...translateY }) .) ...translateY }) .(time) .update(time); }
这里由于 TWEEN.Tween会去遍历所以的属性并且设置初始值,如tween里面的代码:
// Set all starting values present on the target object for (var field in object) { _valuesStart[field] ); }
所以不能直接把 new TWEEN.Tween(element)。
因为在start之前,程序其实已经可以完全收集到所有需要to的属性,去运动便可以。我们可以自己封装一个tween去支持这种简便的方式。如:
..(targetsdurationtargets() ()() targets (var key in targets) { if (targets.hasOwnProperty(key)) { _startValues[key] self .(() ((dt (p dv .) } }
这里为了简便使用setInterval去进行loop,当然可以换成其他方式。现在便可以使用如下方式:
(element)(element) .) .start();
当然这有点跑题了。这里只是对比直接使用DOM挂载和使用第三方对象挂载的区别。第三方挂载有点隔山打牛的感觉。
当然..,还没有完,不仅仅可以上面那个样子。那还可以把transformjs完全当作一个计算工具来用。
); console.log(matrix3d);
打印出来你将得到下面的值:
你想用这个值来干什么就干什么吧。看transformjs源码可以得到 Transform.getMatrix3D一共支持的属性:
(option) (var key in option) { ... ... ... }
语法3Transform.getMatrix2D(option)
不仅仅是3D matrix, transformjs也提供了2D的工具函数支持。
姿势); console.log(matrix2d);
打印出来你将得到下面的值:
那么得到这个Matrix2D有什么用?
看transformjs源码可以得到 Transform.getMatrix2D一共支持的属性:
(option)... ... ... }
特别注意事项Transform.getMatrix2D 和Transform.getMatrix3D都是支持origin特性,请和transform-origin说拜拜
Transform.getMatrix2D 和Transform.getMatrix3D没有使用传统的Math.tan去实现shew,取而代之的是half of rotation
如2d的skew:
.sin(skewX), Math.cos(skewX)
以前腾讯IEG的同学问过为什么使用half of rotation,而不使用Math.tan?
原因很简单,Math.tan扭曲力度特别大,而且会有无穷大的值导致扭曲横跨整个屏幕。
而half of rotation则不会。
getMatrix2D有用吗?用于Dom Transformation时候,可以用于兼容不支持CSS3 3D Transforms的浏览器
如,我们可以很轻松的把一些transformation属性转换成CSS3属性赋给DOM:
)....[.....
用于Canvas和SVG Transformation
什么?还能用于Canvas和SVG?是的,举个例子,在Canvas画一个旋转30度、缩小成0.5倍,并且平移(200,200)的图片: