TAT.dnt transformjs 污染了 DOM?
In Web开发 on 2016年12月28日 by view: 2,153
5

原文链接: https://github.com/AlloyTeam/AlloyTouch/wiki/Powerful-transformjs

写在前面

上星期在 React 微信群里,有小伙伴觉得 transformjs 直接给 DOM 添加属性太激进,不可取(由于不在那个微信群,不明白为什么 React 会谈到 transformjs?!)。关于这点,其实在一年半前腾讯内部就有相关声音,腾讯内部的小伙伴建议,不要污染那么多吧~~,给个总的 namespace,如:

在腾讯内部,还有小伙伴建议,包裹一层把:

总之,就是不要这样子(transformjs 目前的姿势):

那么上面这种做法会有什么问题?

  • 既然 JS 里提供了动态属性并监听变更进行 callback 的能力为什么不能用?
  • 违反哪条 JS 最佳实践?
  • 违反哪条 Web 最佳实践?
  • 违反哪条 DOM 最佳实践?

后来,我找到以前提修改意见的腾讯小伙伴,他给了这样的回答:

如果以后 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 当作工具,他提供一些基础的数学能力。

这里需要特别注意,以前的姿势可以继续使用,这里另外三种使用姿势。

语法 1

如你所见,其他方式都不用变。只是第一个参数不仅仅可以传 DOM 元素,也可以传任意对象字面量等。

不卖关子,先看使用姿势

看到了没有,你不仅可以传 DOM 元素进去,也可以传对象字面量。你可以把 obj.transform 打印出来,上面是选择了 90 度,所以它生成出来的 matrix 是:

你同样也可以关闭透视投影,如:

生成出来的 matrix 是:

那么运动的姿势呢?这里配合 tween.js 的示例如下:

那么如果用传统的姿势是?

这里由于 TWEEN.Tween 会去遍历所以的属性并且设置初始值,如 tween 里面的代码:

所以不能直接把 new TWEEN.Tween(element)。
因为在 start 之前,程序其实已经可以完全收集到所有需要 to 的属性,去运动便可以。我们可以自己封装一个 tween 去支持这种简便的方式。如:

这里为了简便使用 setInterval 去进行 loop,当然可以换成其他方式。现在便可以使用如下方式:

当然这有点跑题了。这里只是对比直接使用 DOM 挂载和使用第三方对象挂载的区别。第三方挂载有点隔山打牛的感觉。
当然..,还没有完,不仅仅可以上面那个样子。那还可以把 transformjs 完全当作一个计算工具来用。

语法 2

姿势

打印出来你将得到下面的值:

你想用这个值来干什么就干什么吧。看 transformjs 源码可以得到 Transform.getMatrix3D 一共支持的属性:

语法 3

不仅仅是 3D matrix, transformjs 也提供了 2D 的工具函数支持。

姿势

打印出来你将得到下面的值:

  • a 水平缩放
  • b 水平拉伸
  • c 垂直拉伸
  • d 垂直缩放
  • tx 水平位移
  • ty 垂直位移

那么得到这个 Matrix2D 有什么用?

  • 缩放:scale(sx, sy) 等同于 matrix(sx, 0, 0, sy, 0, 0);
  • 平移:translate(tx, ty) 等同于 matrix(1, 0, 0, 1, tx, ty);
  • 旋转:rotate(deg) 等同于 matrix(cos(deg), sin(deg), -sin(deg), cos(deg), 0, 0);
  • 拉伸:skew(degx, degy) 等同于 matrix(1, tan(degy), tan(degx), 1, 0, 0);

看 transformjs 源码可以得到 Transform.getMatrix2D 一共支持的属性:

特别注意事项

Transform.getMatrix2D 和 Transform.getMatrix3D 都是支持 origin 特性,请和 transform-origin 说拜拜
Transform.getMatrix2D 和 Transform.getMatrix3D 没有使用传统的 Math.tan 去实现 shew,取而代之的是 half of rotation

如 2d 的 skew:

以前腾讯 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)的图片:

上面是我们传统的姿势。使用 Transform.getMatrix2D 之后,变成这个样子:

可以看到,这里让开发者不用自己去拼凑 matrix。SVG 的粒子就不再举例,和用于 DOM 的例子差不多,相信大家能够很快搞定。

开始使用吧

最后,多谢大家对 transformjs 的建议,有了你们中肯建议和意见,才让它变得更好更灵活更强大。


原创文章转载请注明:

转载自AlloyTeam:http://www.alloyteam.com/2016/12/transformjs-polluting-the-dom/

  1. alice 2017 年 6 月 28 日

    安卓 4.4 默认浏览器不支持 hasOwnProperty,这个怎么解决啊

  2. 徐志伟 2017 年 1 月 17 日

    大神,数学真好啊。transform.js 库简单的说,就是利用了 es5 的 Object.defineProperty 方法给对象的属性, 当然这里大神自己重写了添加属性的 set 和 get 方法,通过那 15 个属性 ([“translateX”, “translateY”, “translateZ”, “scaleX”, “scaleY”, “scaleZ”, “rotateX”, “rotateY”, “rotateZ”, “skewX”, “skewY”, “originX”, “originY”, “originZ”, “perspective”]), 当然透视可以关闭, 只要设置,必然会触发 set 中的回调函数,这个回调函数就是三维矩阵各种计算后的值,之后赋给 dom。那个腾讯小伙伴说是污染,其实这 15 个属性也不是保留字,并无大碍,很是同意大神的观点。说了这么多了,大神,能不能拉我进你们 162225981 那个群啊,加了管理员不给进啊,代码都已经开源了,也不差把人拉进去了吧。

    • TAT.dnt

      TAT.dnt 2017 年 1 月 30 日

      赞。我不是管理员。申请应该就能进吧~~

      • 徐志伟 2017 年 2 月 6 日

        大神,您写的 observejs 是个好东西,但是需要配合什么用才能发挥到极致啊,难道只是简单的监听任意对象,其属性发生改变则触发相应的回掉函数(由开发者决定观察什么,决定响应什么)。我目前只能觉得 observejs 能做的就是当对象的属性改变时,可以触发回掉;写动画也可以不需要 requestAnimationFrame,只要对象的属性改变就调用回调函数 (如果回调函数执行的时间比较长(>100ms),函数只能放在主线程,等待前一个执行完毕挨个执行, 这样好吗?requestAnimationFrame 起码是个异步的)。希望大神,指点一下 observerjs 的其它用途,感觉你们团队内部,还配合这其它高大上的库。

  3. exoticknight 2016 年 12 月 31 日

     越来越好啦

发表评论