Javascript從變形矩陣反推scale以及rotate

- - posted in javascript | Comments

原文: http://css-tricks.com/get-value-of-css-rotation-through-javascript/

今天在追一個跟CSS3 transform有關的bug, 過程中懷疑是transform沒有正確應用到element上。

最後想到用一個Mutation Observer去觀察元素的變形矩陣的某個值(在此例為scale)的變化, 因為transform沒辦法直接用element.style直接拿到scale的值, 所以要用getComputedStyle拿出變形矩陣後算出來: (skew跟translate的值原文沒有提供算法,看了一下網路文章似乎沒辦法逆推。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  /**
   * Construct a mutation observer.
   * See https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
   */

  /**
   * var target = document.querySelector('#id');
   */
  var target = document.querySelector('#id');
  /**
   * create an observer instance
   */
  var observer = new MutationObserver(function(mutations) {
    /**
     * We could iterate the mutations here,
     * but I don't really care it now.
     */
    var st = window.getComputedStyle(target, null);
    var tr = st.getPropertyValue("-webkit-transform") ||
             st.getPropertyValue("-moz-transform") ||
             st.getPropertyValue("-ms-transform") ||
             st.getPropertyValue("-o-transform") ||
             st.getPropertyValue("transform");

    console.log('Matrix: ' + tr);

    // rotation matrix - http://en.wikipedia.org/wiki/Rotation_matrix

    var values = tr.split('(')[1];
    values = values.split(')')[0];
    values = values.split(',');
    var a = values[0];
    var b = values[1];
    var c = values[2];
    var d = values[3];

    var scale = Math.sqrt(a*a + b*b);

    // arc sin, convert from radians to degrees, round
    // DO NOT USE: see update below
    var sin = b/scale;
    var angle = Math.round(Math.asin(sin) * (180/Math.PI));

    // works!
    console.log('Scale: ' + scale + ';Rotate: ' + angle + 'deg');
  });
  /**
    * Configuration of mutation observer.
    */
  var config = { attributes: true, childList: true, characterData: true };

  /**
   * pass in the target node, as well as the observer options
   */
  observer.observe(target, config);

Comments