2
YUI 3.10.3 (build 2fb5187)
3
Copyright 2013 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
8
YUI.add('matrix', function (Y, NAME) {
19
* Used as value for the _rounding method.
32
_round: function(val) {
33
val = Math.round(val * MatrixUtil._rounder) / MatrixUtil._rounder;
37
* Converts a radian value to a degree.
40
* @param {Number} rad Radian value to be converted.
43
rad2deg: function(rad) {
44
var deg = rad * (180 / Math.PI);
49
* Converts a degree value to a radian.
52
* @param {Number} deg Degree value to be converted to radian.
55
deg2rad: function(deg) {
56
var rad = deg * (Math.PI / 180);
61
* Converts an angle to a radian
64
* @param {Objecxt} val Value to be converted to radian.
67
angle2rad: function(val) {
68
if (typeof val === 'string' && val.indexOf('rad') > -1) {
69
val = parseFloat(val);
70
} else { // default to deg
71
val = MatrixUtil.deg2rad(parseFloat(val));
78
* Converts a transform object to an array of column vectors.
81
* | matrix[0][0] matrix[1][0] matrix[2][0] |
82
* | matrix[0][1] matrix[1][1] matrix[2][1] |
83
* | matrix[0][2] matrix[1][2] matrix[2][2] |
89
convertTransformToArray: function(matrix)
92
[matrix.a, matrix.c, matrix.dx],
93
[matrix.b, matrix.d, matrix.dy],
100
* Returns the determinant of a given matrix.
103
* | matrix[0][0] matrix[1][0] matrix[2][0] |
104
* | matrix[0][1] matrix[1][1] matrix[2][1] |
105
* | matrix[0][2] matrix[1][2] matrix[2][2] |
106
* | matrix[0][3] matrix[1][3] matrix[2][3] |
109
* @method getDeterminant
110
* @param {Array} matrix An nxn matrix represented an array of vector (column) arrays. Each vector array has index for each row.
113
getDeterminant: function(matrix)
122
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
126
multiplier = matrix[i][0];
127
if(i % 2 === 0 || i === 0)
129
determinant += multiplier * MatrixUtil.getDeterminant(MatrixUtil.getMinors(matrix, i, 0));
133
determinant -= multiplier * MatrixUtil.getDeterminant(MatrixUtil.getMinors(matrix, i, 0));
140
* Returns the inverse of a matrix
143
* @param Array matrix An array representing an nxn matrix
147
* | matrix[0][0] matrix[1][0] matrix[2][0] |
148
* | matrix[0][1] matrix[1][1] matrix[2][1] |
149
* | matrix[0][2] matrix[1][2] matrix[2][2] |
150
* | matrix[0][3] matrix[1][3] matrix[2][3] |
153
inverse: function(matrix)
161
//vector representing 2x2 matrix
165
determinant = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
167
[matrix[1][1] * determinant, -matrix[1][0] * determinant],
168
[-matrix[0][1] * determinant, matrix[0][0] * determinant]
173
determinant = MatrixUtil.getDeterminant(matrix);
177
for(j = 0; j < len; ++j)
179
minor = MatrixUtil.getMinors(matrix, j, i);
180
adjunct[i][j] = MatrixUtil.getDeterminant(minor);
181
if((i + j) % 2 !== 0 && (i + j) !== 0)
187
inverse = MatrixUtil.scalarMultiply(adjunct, 1/determinant);
193
* Multiplies a matrix by a numeric value.
195
* @method scalarMultiply
196
* @param {Array} matrix The matrix to be altered.
197
* @param {Number} multiplier The number to multiply against the matrix.
200
scalarMultiply: function(matrix, multiplier)
207
for(j = 0; j < len; ++j)
209
matrix[i][j] = MatrixUtil._round(matrix[i][j] * multiplier);
216
* Returns the transpose for an nxn matrix.
219
* @param matrix An nxn matrix represented by an array of vector arrays.
222
transpose: function(matrix)
224
var len = matrix.length,
231
for(j = 0; j < len; ++j)
233
transpose[i].push(matrix[j][i]);
240
* Returns a matrix of minors based on a matrix, column index and row index.
243
* @param {Array} matrix The matrix from which to extract the matrix of minors.
244
* @param {Number} columnIndex A zero-based index representing the specified column to exclude.
245
* @param {Number} rowIndex A zero-based index represeenting the specified row to exclude.
248
getMinors: function(matrix, columnIndex, rowIndex)
257
if(i !== columnIndex)
260
for(j = 0; j < len; ++j)
264
column.push(matrix[i][j]);
274
* Returns the sign of value
277
* @param {Number} val value to be interpreted
282
return val === 0 ? 1 : val/Math.abs(val);
286
* Multiplies a vector and a matrix
288
* @method vectorMatrixProduct
289
* @param {Array} vector Array representing a column vector
290
* @param {Array} matrix Array representing an nxn matrix
293
vectorMatrixProduct: function(vector, matrix)
300
for(i = 0; i < len; ++i)
303
for(j = 0; j < len; ++j)
305
rowProduct += vector[i] * matrix[i][j];
307
product[i] = rowProduct;
313
* Breaks up a 2d transform matrix into a series of transform operations.
316
* @param {Array} 3x3 matrix array
319
decompose: function(matrix)
321
var a = parseFloat(matrix[0][0]),
322
b = parseFloat(matrix[1][0]),
323
c = parseFloat(matrix[0][1]),
324
d = parseFloat(matrix[1][1]),
325
dx = parseFloat(matrix[0][2]),
326
dy = parseFloat(matrix[1][2]),
331
if((a * d - b * c) === 0)
335
//get length of vector(ab)
336
sx = MatrixUtil._round(Math.sqrt(a * a + b * b));
337
//normalize components of vector(ab)
340
shear = MatrixUtil._round(a * c + b * d);
343
//get length of vector(cd)
344
sy = MatrixUtil._round(Math.sqrt(c * c + d * d));
345
//normalize components of vector(cd)
349
shear = MatrixUtil._round(MatrixUtil.rad2deg(Math.atan(shear)));
350
rotate = MatrixUtil._round(MatrixUtil.rad2deg(Math.atan2(matrix[1][0], matrix[0][0])));
353
["translate", dx, dy],
361
* Parses a transform string and returns an array of transform arrays.
363
* @method getTransformArray
364
* @param {String} val A transform string
367
getTransformArray: function(transform) {
368
var re = /\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi,
373
methods = MatrixUtil.transformMethods;
375
while ((m = re.exec(transform))) {
376
if (methods.hasOwnProperty(m[1]))
378
args = m[2].split(',');
380
transforms.push(args);
382
else if(m[1] == "matrix")
384
args = m[2].split(',');
385
decomp = MatrixUtil.decompose([
386
[args[0], args[2], args[4]],
387
[args[1], args[3], args[5]],
390
transforms.push(decomp[0]);
391
transforms.push(decomp[1]);
392
transforms.push(decomp[2]);
393
transforms.push(decomp[3]);
400
* Returns an array of transform arrays representing transform functions and arguments.
402
* @method getTransformFunctionArray
405
getTransformFunctionArray: function(transform) {
410
list = [transform, 0, 0];
413
list = [transform, 1, 1];
416
list = [transform, 1];
419
list = [transform, 1];
422
list = [transform, 0, 0];
425
list = [transform, 0];
432
* Compares to arrays or transform functions to ensure both contain the same functions in the same
435
* @method compareTransformSequence
436
* @param {Array} list1 Array to compare
437
* @param {Array} list2 Array to compare
440
compareTransformSequence: function(list1, list2)
445
isEqual = len === len2;
450
if(list1[i][0] != list2[i][0])
461
* Mapping of possible transform method names.
463
* @property transformMethods
471
translate: "translate",
472
translateX: "translateX",
473
translateY: "tranlsateY",
481
Y.MatrixUtil = MatrixUtil;
484
* Matrix is a class that allows for the manipulation of a transform matrix.
485
* This class is a work in progress.
491
var Matrix = function(config) {
497
* Used as value for the _rounding method.
505
* Updates the matrix.
515
multiply: function(a, b, c, d, dx, dy) {
517
matrix_a = matrix.a * a + matrix.c * b,
518
matrix_b = matrix.b * a + matrix.d * b,
519
matrix_c = matrix.a * c + matrix.c * d,
520
matrix_d = matrix.b * c + matrix.d * d,
521
matrix_dx = matrix.a * dx + matrix.c * dy + matrix.dx,
522
matrix_dy = matrix.b * dx + matrix.d * dy + matrix.dy;
524
matrix.a = this._round(matrix_a);
525
matrix.b = this._round(matrix_b);
526
matrix.c = this._round(matrix_c);
527
matrix.d = this._round(matrix_d);
528
matrix.dx = this._round(matrix_dx);
529
matrix.dy = this._round(matrix_dy);
534
* Parses a string and updates the matrix.
536
* @method applyCSSText
537
* @param {String} val A css transform string
539
applyCSSText: function(val) {
540
var re = /\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi,
544
val = val.replace(/matrix/g, "multiply");
545
while ((m = re.exec(val))) {
546
if (typeof this[m[1]] === 'function') {
547
args = m[2].split(',');
548
this[m[1]].apply(this, args);
554
* Parses a string and returns an array of transform arrays.
556
* @method getTransformArray
557
* @param {String} val A css transform string
560
getTransformArray: function(val) {
561
var re = /\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi,
566
val = val.replace(/matrix/g, "multiply");
567
while ((m = re.exec(val))) {
568
if (typeof this[m[1]] === 'function') {
569
args = m[2].split(',');
571
transforms.push(args);
578
* Default values for the matrix
580
* @property _defaults
598
_round: function(val) {
599
val = Math.round(val * this._rounder) / this._rounder;
604
* Initializes a matrix.
607
* @param {Object} config Specified key value pairs for matrix properties. If a property is not explicitly defined in the config argument,
608
* the default value will be used.
610
init: function(config) {
611
var defaults = this._defaults,
614
config = config || {};
616
for (prop in defaults) {
617
if(defaults.hasOwnProperty(prop))
619
this[prop] = (prop in config) ? config[prop] : defaults[prop];
623
this._config = config;
627
* Applies a scale transform
630
* @param {Number} val
632
scale: function(x, y) {
633
this.multiply(x, 0, 0, y, 0, 0);
638
* Applies a skew transformation.
641
* @param {Number} x The value to skew on the x-axis.
642
* @param {Number} y The value to skew on the y-axis.
644
skew: function(x, y) {
648
if (x !== undefined) { // null or undef
649
x = Math.tan(this.angle2rad(x));
653
if (y !== undefined) { // null or undef
654
y = Math.tan(this.angle2rad(y));
657
this.multiply(1, y, x, 1, 0, 0);
662
* Applies a skew to the x-coordinate
665
* @param {Number} x x-coordinate
673
* Applies a skew to the y-coordinate
676
* @param {Number} y y-coordinate
684
* Returns a string of text that can be used to populate a the css transform property of an element.
689
toCSSText: function() {
702
* Returns a string that can be used to populate the css filter property of an element.
704
* @method toFilterText
707
toFilterText: function() {
709
text = 'progid:DXImageTransform.Microsoft.Matrix(';
710
text += 'M11=' + matrix.a + ',' +
711
'M21=' + matrix.b + ',' +
712
'M12=' + matrix.c + ',' +
713
'M22=' + matrix.d + ',' +
714
'sizingMethod="auto expand")';
722
* Converts a radian value to a degree.
725
* @param {Number} rad Radian value to be converted.
728
rad2deg: function(rad) {
729
var deg = rad * (180 / Math.PI);
734
* Converts a degree value to a radian.
737
* @param {Number} deg Degree value to be converted to radian.
740
deg2rad: function(deg) {
741
var rad = deg * (Math.PI / 180);
745
angle2rad: function(val) {
746
if (typeof val === 'string' && val.indexOf('rad') > -1) {
747
val = parseFloat(val);
748
} else { // default to deg
749
val = this.deg2rad(parseFloat(val));
756
* Applies a rotate transform.
759
* @param {Number} deg The degree of the rotation.
761
rotate: function(deg, x, y) {
762
var rad = this.angle2rad(deg),
765
this.multiply(cos, sin, 0 - sin, cos, 0, 0);
770
* Applies translate transformation.
773
* @param {Number} x The value to transate on the x-axis.
774
* @param {Number} y The value to translate on the y-axis.
776
translate: function(x, y) {
777
x = parseFloat(x) || 0;
778
y = parseFloat(y) || 0;
779
this.multiply(1, 0, 0, 1, x, y);
784
* Applies a translate to the x-coordinate
787
* @param {Number} x x-coordinate
789
translateX: function(x) {
795
* Applies a translate to the y-coordinate
798
* @param {Number} y y-coordinate
800
translateY: function(y) {
801
this.translate(null, y);
807
* Returns an identity matrix.
812
identity: function() {
813
var config = this._config,
814
defaults = this._defaults,
817
for (prop in config) {
818
if (prop in defaults) {
819
this[prop] = defaults[prop];
826
* Returns a 3x3 Matrix array
829
* | matrix[0][0] matrix[1][0] matrix[2][0] |
830
* | matrix[0][1] matrix[1][1] matrix[2][1] |
831
* | matrix[0][2] matrix[1][2] matrix[2][2] |
834
* @method getMatrixArray
837
getMatrixArray: function()
841
[matrix.a, matrix.c, matrix.dx],
842
[matrix.b, matrix.d, matrix.dy],
849
* Returns the left, top, right and bottom coordinates for a transformed
852
* @method getContentRect
853
* @param {Number} width The width of the item.
854
* @param {Number} height The height of the item.
855
* @param {Number} x The x-coordinate of the item.
856
* @param {Number} y The y-coordinate of the item.
859
getContentRect: function(width, height, x, y)
861
var left = !isNaN(x) ? x : 0,
862
top = !isNaN(y) ? y : 0,
863
right = left + width,
864
bottom = top + height,
872
x1 = (a * left + c * top + dx),
873
y1 = (b * left + d * top + dy),
875
x2 = (a * right + c * top + dx),
876
y2 = (b * right + d * top + dy),
878
x3 = (a * left + c * bottom + dx),
879
y3 = (b * left + d * bottom + dy),
881
x4 = (a * right + c * bottom + dx),
882
y4 = (b * right + d * bottom + dy);
884
left: Math.min(x3, Math.min(x1, Math.min(x2, x4))),
885
right: Math.max(x3, Math.max(x1, Math.max(x2, x4))),
886
top: Math.min(y2, Math.min(y4, Math.min(y3, y1))),
887
bottom: Math.max(y2, Math.max(y4, Math.max(y3, y1)))
892
* Returns the determinant of the matrix.
894
* @method getDeterminant
897
getDeterminant: function()
899
return Y.MatrixUtil.getDeterminant(this.getMatrixArray());
903
* Returns the inverse (in array form) of the matrix.
910
return Y.MatrixUtil.inverse(this.getMatrixArray());
914
* Returns the transpose of the matrix
919
transpose: function()
921
return Y.MatrixUtil.transpose(this.getMatrixArray());
925
* Returns an array of transform commands that represent the matrix.
930
decompose: function()
932
return Y.MatrixUtil.decompose(this.getMatrixArray());
939
}, '3.10.3', {"requires": ["yui-base"]});