<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      transformjs污染了DOM?是你不了解它的強大

      2016-12-26 09:24  【當耐特】  閱讀(1735)  評論(1)    收藏  舉報

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

      寫在前面

      上星期在React微信群里,有小伙伴覺得transformjs直接給DOM添加屬性太激進,不可取(由于不在那個微信群,不明白為什么React會談到transformjs?!)。關于這點,其實在一年半前騰訊內部就有相關聲音,騰訊內部的小伙伴建議,不要污染那么多吧~~,給個總的namespace,如:

      var element = document.querySelector("#test");
      Transform(element);
      element.transform.scaleX =2;
      element.transform.translateX = 100;
      element.transform.rotateX = 30;
      

      在騰訊內部,還有小伙伴建議,包裹一層把:

      var transform = new Transform( dom, {
      	scaleX: 1,
          skewY:30,
          translateY:200
      
      })
      
      transform.translateY = 100;
      

      總之,就是不要這樣子(transformjs目前的姿勢):

      var element1= document.querySelector("#test");
      Transform(element);
      element.rotateZ = 45;
      

      那么上面這種做法會有什么問題?

      • 既然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

      Transform(obj, [notPerspective]);
      

      如你所見,其他方式都不用變。只是第一個參數不僅僅可以傳DOM元素,也可以傳任意對象字面量等。

      不賣關子,先看使用姿勢

      var element = document.querySelector("#test"),
          obj = {};
      
      Transform(obj);
      
      obj.rotateZ = 90;
      
      element.style.transform = element.style.msTransform = element.style.OTransform = element.style.MozTransform = element.style.webkitTransform = obj.transform;
      

      看到了沒有,你不僅可以傳DOM元素進去,也可以傳對象字面量。你可以把obj.transform打印出來,上面是選擇了90度,所以它生成出來的matrix是:

      perspective(500px) matrix3d(0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1)
      

      你同樣也可以關閉透視投影,如:

      var element = document.querySelector("#test"),
          obj = {};
      //關閉透視投影
      Transform(obj, true);
      
      obj.rotateZ = 90;
      
      element.style.transform = element.style.msTransform = element.style.OTransform = element.style.MozTransform = element.style.webkitTransform = obj.transform;
      

      生成出來的matrix是:

      matrix3d(0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1)
      

      那么運動的姿勢呢?這里配合tween.js的示例如下:

      var element = document.querySelector("#test"),
          obj = { translateX: 0, translateY: 0 };
      
      Transform(obj);
      
      var tween = new TWEEN.Tween(obj)
          .to({ translateX: 100, translateY: 100 }, 1000)
          .onUpdate(function () {
              element.style.transform = element.style.msTransform = element.style.OTransform = element.style.MozTransform = element.style.webkitTransform = obj.transform;
          })
          .start();
      
      requestAnimationFrame(animate);
      
      function animate(time) {
          requestAnimationFrame(animate);
          TWEEN.update(time);
      }
      

      那么如果用傳統的姿勢是?

      var element = document.querySelector("#test");
      
      Transform(element);
      
      var tween = new TWEEN.Tween({ translateX: element.translateX, translateY: element.translateY })
          .to({ translateX: 100, translateY: 100 }, 1000)
          .onUpdate(function () {
              element.translateX = this.translateX
              element.translateY = this.translateY
          })
          .start();
      
      requestAnimationFrame(animate);
      
      function animate(time) {
          requestAnimationFrame(animate);
          TWEEN.update(time);
      }
      

      這里由于 TWEEN.Tween會去遍歷所以的屬性并且設置初始值,如tween里面的代碼:

       // Set all starting values present on the target object
      for (var field in object) {
          _valuesStart[field] = parseFloat(object[field], 10);
      }
      

      所以不能直接把 new TWEEN.Tween(element)。
      因為在start之前,程序其實已經可以完全收集到所有需要to的屬性,去運動便可以。我們可以自己封裝一個tween去支持這種簡便的方式。如:

      var Tween = function (obj) {
          this.obj = obj;
          return this;
      }
      
      Tween.prototype = {
          to: function (targets, duration, easing) {
              this.duration = duration;
              this.targets = targets;
              return this;
          },
          start: function () {
              this.startTime = new Date();
              this._beginTick();
          },
          _beginTick: function () {
              var _startValues = {},
                  targets = this.targets;
              for (var key in targets) {
                  if (targets.hasOwnProperty(key)) {
                      _startValues[key] = this.obj[key];
                  }
              }
              var self  = this;
              this._interval = setInterval(function () {
                  var dt = new Date() - self.startTime;
                  for (var key in targets) {
                      if (targets.hasOwnProperty(key)) {
                          if (dt >= self.duration) {
                              clearInterval(self._interval);
                          } else {
                              var p = dt / self.duration;
                              var dv = targets[key] - self.obj[key];
                              self.obj[key] += dv * p;
                          }
                      }
                  }
              }, 15)
      
          }
      }
      

      這里為了簡便使用setInterval去進行loop,當然可以換成其他方式。現在便可以使用如下方式:

      var element = document.querySelector("#test");
      Transform(element);
      var tween = new Tween(element)
          .to({ translateX: 100, translateY: 100 }, 1000)
          .start();
      

      當然這有點跑題了。這里只是對比直接使用DOM掛載和使用第三方對象掛載的區別。第三方掛載有點隔山打牛的感覺。
      當然..,還沒有完,不僅僅可以上面那個樣子。那還可以把transformjs完全當作一個計算工具來用。

      語法2

       Transform.getMatrix3D(option)
      

      姿勢

      var matrix3d = Transform.getMatrix3D({
          translateX: 0,
          translateY: 100,
          scaleX:2
      });
      console.log(matrix3d);
      

      打印出來你將得到下面的值:

      你想用這個值來干什么就干什么吧。看transformjs源碼可以得到 Transform.getMatrix3D一共支持的屬性:

      Transform.getMatrix3D = function (option) {
          var defaultOption = {
              translateX: 0,
              translateY: 0,
              translateZ: 0,
              rotateX: 0,
              rotateY: 0,
              rotateZ: 0,
              skewX: 0,
              skewY: 0,
              originX: 0,
              originY: 0,
              originZ: 0,
              scaleX: 1,
              scaleY: 1,
              scaleZ: 1
          };
          for (var key in option) {
          ...
          ...
          ...
      
      }
      

      語法3

       Transform.getMatrix2D(option)
      

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

      姿勢

      var matrix2d = Transform.getMatrix2D({
          translateX: 0,
          translateY: 100,
          scaleX:2
      });
      console.log(matrix2d);
      

      打印出來你將得到下面的值:

      • 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 = function(option){
          var defaultOption = {
              translateX: 0,
              translateY: 0,
              rotation: 0,
              skewX: 0,
              skewY: 0,
              originX: 0,
              originY: 0,
              scaleX: 1,
              scaleY: 1
          };
          ...
          ...
          ...
      }
      

      特別注意事項

      Transform.getMatrix2D 和Transform.getMatrix3D都是支持origin特性,請和transform-origin說拜拜
      Transform.getMatrix2D 和Transform.getMatrix3D沒有使用傳統的Math.tan去實現shew,取而代之的是half of rotation

      如2d的skew:

      Math.cos(skewY), Math.sin(skewY), -Math.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:

      var matrix = Transform.getMatrix2D({
          rotation: 30,
          scaleX: 0.5,
          scaleY: 0.5,
          translateX: 100
      });
      ele.style.transform = ele.style.msTransform = ele.style.OTransform = ele.style.MozTransform = ele.style.webkitTransform = "matrix(" + [matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty].join(",") + ")";
      

      用于Canvas和SVG Transformation

      什么?還能用于Canvas和SVG?是的,舉個例子,在Canvas畫一個旋轉30度、縮小成0.5倍,并且平移(200,200)的圖片:

      var canvas = document.getElementById("ourCanvas"),
          ctx = canvas.getContext("2d"),
          img = new Image(),
          rotation = 30 * Math.PI / 180;
      
      img.onload = function () {
          ctx.sava();
          ctx.setTransform(
              0.5 * Math.cos(rotation), 0.5 * Math.sin(rotation),
              -0.5 * Math.sin(rotation), 0.5 * Math.cos(rotation),
              200, 200
          );
          ctx.drawImage(img, 0, 0);
          ctx.restore();
      };
      
      img.src = "asset/img/test.png";
      

      上面是我們傳統的姿勢。使用Transform.getMatrix2D 之后,變成這個樣子:

      var canvas = document.getElementById("ourCanvas"),
          ctx = canvas.getContext("2d"),
          img = new Image();
      
      var matrix = Transform.getMatrix2D({
          rotation: 30,
          scaleX: 0.5,
          scaleY: 0.5,
          translateX: 200,
          translateY: 200
      });
      
      img.onload = function () {
          ctx.sava();
          ctx.setTransform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
          ctx.drawImage(img, 0, 0);
          ctx.restore();
      };
      
      img.src = "asset/img/test.png";
      

      可以看到,這里讓開發者不用自己去拼湊matrix。SVG的粒子就不再舉例,和用于DOM的例子差不多,相信大家能夠很快搞定。

      開始使用吧

      最后,多謝大家對transformjs的建議,有了你們中肯建議和意見,才讓它變得更好更靈活更強大。

      主站蜘蛛池模板: 欧美熟妇乱子伦XX视频| 亚洲中文字幕无码av永久| 亚洲精品一区二区毛豆| 久久96热在精品国产高清| 国精品91人妻无码一区二区三区| 久色伊人激情文学你懂的| 久久高清超碰AV热热久久| 人人入人人爱| 99www久久综合久久爱com| 18禁美女裸体爆乳无遮挡| 国产成人综合色就色综合| 亚洲午夜av一区二区| 久久99精品国产麻豆宅宅| 久久人人爽爽人人爽人人片av| 精品尤物国产尤物在线看| 久久久精品94久久精品| 天天躁夜夜躁狠狠喷水| 亚洲欧美综合中文| 国产麻豆剧传媒精品国产av| 男女啪啪免费观看网站| 99精品国产中文字幕| 巨胸喷奶水视频www免费网站| 精品久久综合日本久久网| 久久日韩在线观看视频| 人妻无码中文字幕免费视频蜜桃| 亚洲第四色在线中文字幕| 亚洲一本二区偷拍精品| 久久婷婷五月综合色精品| 91精品国产老熟女在线| 成人精品天堂一区二区三区| 人妻丝袜AV中文系列先锋影音| 美女黄网站人色视频免费国产| 亚洲日韩VA无码中文字幕| 好深好湿好硬顶到了好爽| 国产精品午夜福利免费看| 一级做a爰片在线播放| 美女又黄又免费的视频| 九九热视频精品在线播放| 亚洲人成网站在线在线观看| 亚洲男人的天堂网站| 韩国免费a级毛片久久|