API Docs for: 3.8.0
Show:

File: matrix/js/Matrix.js

  1. /**
  2.  * Matrix is a class that allows for the manipulation of a transform matrix.
  3.  * This class is a work in progress.
  4.  *
  5.  * @class Matrix
  6.  * @constructor
  7.  * @module matrix
  8.  */
  9. var Matrix = function(config) {
  10.     this.init(config);
  11. };

  12. Matrix.prototype = {
  13.     /**
  14.      * Used as value for the _rounding method.
  15.      *
  16.      * @property _rounder
  17.      * @private
  18.      */
  19.     _rounder: 100000,

  20.     /**
  21.      * Updates the matrix.
  22.      *
  23.      * @method multiple
  24.      * @param {Number} a
  25.      * @param {Number} b
  26.      * @param {Number} c
  27.      * @param {Number} d
  28.      * @param {Number} dx
  29.      * @param {Number} dy
  30.      */
  31.     multiply: function(a, b, c, d, dx, dy) {
  32.         var matrix = this,
  33.             matrix_a = matrix.a * a + matrix.c * b,
  34.             matrix_b = matrix.b * a + matrix.d * b,
  35.             matrix_c = matrix.a * c + matrix.c * d,
  36.             matrix_d = matrix.b * c + matrix.d * d,
  37.             matrix_dx = matrix.a * dx + matrix.c * dy + matrix.dx,
  38.             matrix_dy = matrix.b * dx + matrix.d * dy + matrix.dy;

  39.         matrix.a = this._round(matrix_a);
  40.         matrix.b = this._round(matrix_b);
  41.         matrix.c = this._round(matrix_c);
  42.         matrix.d = this._round(matrix_d);
  43.         matrix.dx = this._round(matrix_dx);
  44.         matrix.dy = this._round(matrix_dy);
  45.         return this;
  46.     },

  47.     /**
  48.      * Parses a string and updates the matrix.
  49.      *
  50.      * @method applyCSSText
  51.      * @param {String} val A css transform string
  52.      */
  53.     applyCSSText: function(val) {
  54.         var re = /\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi,
  55.             args,
  56.             m;

  57.         val = val.replace(/matrix/g, "multiply");
  58.         while ((m = re.exec(val))) {
  59.             if (typeof this[m[1]] === 'function') {
  60.                 args = m[2].split(',');
  61.                 this[m[1]].apply(this, args);
  62.             }
  63.         }
  64.     },

  65.     /**
  66.      * Parses a string and returns an array of transform arrays.
  67.      *
  68.      * @method getTransformArray
  69.      * @param {String} val A css transform string
  70.      * @return Array
  71.      */
  72.     getTransformArray: function(val) {
  73.         var re = /\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi,
  74.             transforms = [],
  75.             args,
  76.             m;

  77.         val = val.replace(/matrix/g, "multiply");
  78.         while ((m = re.exec(val))) {
  79.             if (typeof this[m[1]] === 'function') {
  80.                 args = m[2].split(',');
  81.                 args.unshift(m[1]);
  82.                 transforms.push(args);
  83.             }
  84.         }
  85.         return transforms;
  86.     },

  87.     /**
  88.      * Default values for the matrix
  89.      *
  90.      * @property _defaults
  91.      * @private
  92.      */
  93.     _defaults: {
  94.         a: 1,
  95.         b: 0,
  96.         c: 0,
  97.         d: 1,
  98.         dx: 0,
  99.         dy: 0
  100.     },

  101.     /**
  102.      * Rounds values
  103.      *
  104.      * @method _round
  105.      * @private
  106.      */
  107.     _round: function(val) {
  108.         val = Math.round(val * this._rounder) / this._rounder;
  109.         return val;
  110.     },

  111.     /**
  112.      * Initializes a matrix.
  113.      *
  114.      * @method init
  115.      * @param {Object} config Specified key value pairs for matrix properties. If a property is not explicitly defined in the config argument,
  116.      * the default value will be used.
  117.      */
  118.     init: function(config) {
  119.         var defaults = this._defaults,
  120.             prop;

  121.         config = config || {};

  122.         for (prop in defaults) {
  123.             if(defaults.hasOwnProperty(prop))
  124.             {
  125.                 this[prop] = (prop in config) ? config[prop] : defaults[prop];
  126.             }
  127.         }

  128.         this._config = config;
  129.     },

  130.     /**
  131.      * Applies a scale transform
  132.      *
  133.      * @method scale
  134.      * @param {Number} val
  135.      */
  136.     scale: function(x, y) {
  137.         this.multiply(x, 0, 0, y, 0, 0);
  138.         return this;
  139.     },

  140.     /**
  141.      * Applies a skew transformation.
  142.      *
  143.      * @method skew
  144.      * @param {Number} x The value to skew on the x-axis.
  145.      * @param {Number} y The value to skew on the y-axis.
  146.      */
  147.     skew: function(x, y) {
  148.         x = x || 0;
  149.         y = y || 0;

  150.         if (x !== undefined) { // null or undef
  151.             x = Math.tan(this.angle2rad(x));

  152.         }

  153.         if (y !== undefined) { // null or undef
  154.             y = Math.tan(this.angle2rad(y));
  155.         }

  156.         this.multiply(1, y, x, 1, 0, 0);
  157.         return this;
  158.     },

  159.     /**
  160.      * Applies a skew to the x-coordinate
  161.      *
  162.      * @method skewX
  163.      * @param {Number} x x-coordinate
  164.      */
  165.     skewX: function(x) {
  166.         this.skew(x);
  167.         return this;
  168.     },

  169.     /**
  170.      * Applies a skew to the y-coordinate
  171.      *
  172.      * @method skewY
  173.      * @param {Number} y y-coordinate
  174.      */
  175.     skewY: function(y) {
  176.         this.skew(null, y);
  177.         return this;
  178.     },

  179.     /**
  180.      * Returns a string of text that can be used to populate a the css transform property of an element.
  181.      *
  182.      * @method toCSSText
  183.      * @return String
  184.      */
  185.     toCSSText: function() {
  186.         var matrix = this,
  187.             text = 'matrix(' +
  188.                     matrix.a + ',' +
  189.                     matrix.b + ',' +
  190.                     matrix.c + ',' +
  191.                     matrix.d + ',' +
  192.                     matrix.dx + ',' +
  193.                     matrix.dy + ')';
  194.         return text;
  195.     },

  196.     /**
  197.      * Returns a string that can be used to populate the css filter property of an element.
  198.      *
  199.      * @method toFilterText
  200.      * @return String
  201.      */
  202.     toFilterText: function() {
  203.         var matrix = this,
  204.             text = 'progid:DXImageTransform.Microsoft.Matrix(';
  205.         text +=     'M11=' + matrix.a + ',' +
  206.                     'M21=' + matrix.b + ',' +
  207.                     'M12=' + matrix.c + ',' +
  208.                     'M22=' + matrix.d + ',' +
  209.                     'sizingMethod="auto expand")';

  210.         text += '';

  211.         return text;
  212.     },

  213.     /**
  214.      * Converts a radian value to a degree.
  215.      *
  216.      * @method rad2deg
  217.      * @param {Number} rad Radian value to be converted.
  218.      * @return Number
  219.      */
  220.     rad2deg: function(rad) {
  221.         var deg = rad * (180 / Math.PI);
  222.         return deg;
  223.     },

  224.     /**
  225.      * Converts a degree value to a radian.
  226.      *
  227.      * @method deg2rad
  228.      * @param {Number} deg Degree value to be converted to radian.
  229.      * @return Number
  230.      */
  231.     deg2rad: function(deg) {
  232.         var rad = deg * (Math.PI / 180);
  233.         return rad;
  234.     },

  235.     angle2rad: function(val) {
  236.         if (typeof val === 'string' && val.indexOf('rad') > -1) {
  237.             val = parseFloat(val);
  238.         } else { // default to deg
  239.             val = this.deg2rad(parseFloat(val));
  240.         }

  241.         return val;
  242.     },

  243.     /**
  244.      * Applies a rotate transform.
  245.      *
  246.      * @method rotate
  247.      * @param {Number} deg The degree of the rotation.
  248.      */
  249.     rotate: function(deg, x, y) {
  250.         var rad = this.angle2rad(deg),
  251.             sin = Math.sin(rad),
  252.             cos = Math.cos(rad);
  253.         this.multiply(cos, sin, 0 - sin, cos, 0, 0);
  254.         return this;
  255.     },

  256.     /**
  257.      * Applies translate transformation.
  258.      *
  259.      * @method translate
  260.      * @param {Number} x The value to transate on the x-axis.
  261.      * @param {Number} y The value to translate on the y-axis.
  262.      */
  263.     translate: function(x, y) {
  264.         x = parseFloat(x) || 0;
  265.         y = parseFloat(y) || 0;
  266.         this.multiply(1, 0, 0, 1, x, y);
  267.         return this;
  268.     },

  269.     /**
  270.      * Applies a translate to the x-coordinate
  271.      *
  272.      * @method translateX
  273.      * @param {Number} x x-coordinate
  274.      */
  275.     translateX: function(x) {
  276.         this.translate(x);
  277.         return this;
  278.     },

  279.     /**
  280.      * Applies a translate to the y-coordinate
  281.      *
  282.      * @method translateY
  283.      * @param {Number} y y-coordinate
  284.      */
  285.     translateY: function(y) {
  286.         this.translate(null, y);
  287.         return this;
  288.     },


  289.     /**
  290.      * Returns an identity matrix.
  291.      *
  292.      * @method identity
  293.      * @return Object
  294.      */
  295.     identity: function() {
  296.         var config = this._config,
  297.             defaults = this._defaults,
  298.             prop;

  299.         for (prop in config) {
  300.             if (prop in defaults) {
  301.                 this[prop] = defaults[prop];
  302.             }
  303.         }
  304.         return this;
  305.     },

  306.     /**
  307.      * Returns a 3x3 Matrix array
  308.      *
  309.      * /                                             \
  310.      * | matrix[0][0]   matrix[1][0]    matrix[2][0] |
  311.      * | matrix[0][1]   matrix[1][1]    matrix[2][1] |
  312.      * | matrix[0][2]   matrix[1][2]    matrix[2][2] |
  313.      * \                                             /
  314.      *
  315.      * @method getMatrixArray
  316.      * @return Array
  317.      */
  318.     getMatrixArray: function()
  319.     {
  320.         var matrix = this,
  321.             matrixArray = [
  322.                 [matrix.a, matrix.c, matrix.dx],
  323.                 [matrix.b, matrix.d, matrix.dy],
  324.                 [0, 0, 1]
  325.             ];
  326.         return matrixArray;
  327.     },

  328.     /**
  329.      * Returns the left, top, right and bottom coordinates for a transformed
  330.      * item.
  331.      *
  332.      * @method getContentRect
  333.      * @param {Number} width The width of the item.
  334.      * @param {Number} height The height of the item.
  335.      * @param {Number} x The x-coordinate of the item.
  336.      * @param {Number} y The y-coordinate of the item.
  337.      * @return Object
  338.      */
  339.     getContentRect: function(width, height, x, y)
  340.     {
  341.         var left = !isNaN(x) ? x : 0,
  342.             top = !isNaN(y) ? y : 0,
  343.             right = left + width,
  344.             bottom = top + height,
  345.             matrix = this,
  346.             a = matrix.a,
  347.             b = matrix.b,
  348.             c = matrix.c,
  349.             d = matrix.d,
  350.             dx = matrix.dx,
  351.             dy = matrix.dy,
  352.             x1 = (a * left + c * top + dx),
  353.             y1 = (b * left + d * top + dy),
  354.             //[x2, y2]
  355.             x2 = (a * right + c * top + dx),
  356.             y2 = (b * right + d * top + dy),
  357.             //[x3, y3]
  358.             x3 = (a * left + c * bottom + dx),
  359.             y3 = (b * left + d * bottom + dy),
  360.             //[x4, y4]
  361.             x4 = (a * right + c * bottom + dx),
  362.             y4 = (b * right + d * bottom + dy);
  363.         return {
  364.             left: Math.min(x3, Math.min(x1, Math.min(x2, x4))),
  365.             right: Math.max(x3, Math.max(x1, Math.max(x2, x4))),
  366.             top: Math.min(y2, Math.min(y4, Math.min(y3, y1))),
  367.             bottom: Math.max(y2, Math.max(y4, Math.max(y3, y1)))
  368.         };
  369.     },

  370.     /**
  371.      * Returns the determinant of the matrix.
  372.      *
  373.      * @method getDeterminant
  374.      * @return Number
  375.      */
  376.     getDeterminant: function()
  377.     {
  378.         return Y.MatrixUtil.getDeterminant(this.getMatrixArray());
  379.     },

  380.     /**
  381.      * Returns the inverse (in array form) of the matrix.
  382.      *
  383.      * @method inverse
  384.      * @return Array
  385.      */
  386.     inverse: function()
  387.     {
  388.         return Y.MatrixUtil.inverse(this.getMatrixArray());
  389.     },

  390.     /**
  391.      * Returns the transpose of the matrix
  392.      *
  393.      * @method transpose
  394.      * @return Array
  395.      */
  396.     transpose: function()
  397.     {
  398.         return Y.MatrixUtil.transpose(this.getMatrixArray());
  399.     },

  400.     /**
  401.      * Returns an array of transform commands that represent the matrix.
  402.      *
  403.      * @method decompose
  404.      * @return Array
  405.      */
  406.     decompose: function()
  407.     {
  408.         return Y.MatrixUtil.decompose(this.getMatrixArray());
  409.     }
  410. };

  411. Y.Matrix = Matrix;

  412.