      1 /**
      2  * Hilo
      3  * Copyright 2015 alibaba.com
      4  * Licensed under the MIT License
      5  */
      6
      7 /**
      8  * @class Matrix类表示一个转换矩阵，它确定如何将点从一个坐标空间映射到另一个坐标空间。
      9  * @param {Number} a 缩放或旋转图像时影响像素沿 x 轴定位的值。
     10  * @param {Number} b 旋转或倾斜图像时影响像素沿 y 轴定位的值。
     11  * @param {Number} c 旋转或倾斜图像时影响像素沿 x 轴定位的值。
     12  * @param {Number} d 缩放或旋转图像时影响像素沿 y 轴定位的值。
     13  * @param {Number} tx 沿 x 轴平移每个点的距离。
     14  * @param {Number} ty 沿 y 轴平移每个点的距离。
     15  * @module hilo/geom/Matrix
     16  * @requires hilo/core/Class
     17  */
     18 var Matrix = Class.create(/** @lends Matrix.prototype */{
     19     constructor: function(a, b, c, d, tx, ty){
     20         this.a = a;
     21         this.b = b;
     22         this.c = c;
     23         this.d = d;
     24         this.tx = tx;
     25         this.ty = ty;
     26     },
     27
     28     /**
     29      * set
     30      * @param {Number} a
     31      * @param {Number} b
     32      * @param {Number} c
     33      * @param {Number} d
     34      * @param {Number} tx
     35      * @param {Number} ty
     36      */
     37     set: function(a, b, c, d, tx, ty){
     38         this.a = a;
     39         this.b = b;
     40         this.c = c;
     41         this.d = d;
     42         this.tx = tx;
     43         this.ty = ty;
     44
     45 	return this;
     46     },
     47
     48     /**
     49      * copy
     50      * @param  {Matrix} mat
     51      * @return {Matrix}  this
     52      */
     53     copy: function(mat){
     54         this.a = mat.a;
     55         this.b = mat.b;
     56         this.c = mat.c;
     57         this.d = mat.d;
     58         this.tx = mat.tx;
     59         this.ty = mat.ty;
     60
     61         return this;
     62     },
     63
     64     /**
     65      * clone
     66      * @return {Matrix}
     67      */
     68     clone: function(){
     69         return new Matrix().copy(this);
     70     },
     71
     72     /**
     73      * 将某个矩阵与当前矩阵连接，从而将这两个矩阵的几何效果有效地结合在一起。
     74      * @param {Matrix} mtx 要连接到源矩阵的矩阵。
     75      * @returns {Matrix} 一个Matrix对象。
     76      */
     77     concat: function(mtx){
     78         var args = arguments,
     79             a = this.a, b = this.b, c = this.c, d = this.d,
     80             tx = this.tx, ty = this.ty;
     81
     82         var ma, mb, mc, md, mx, my;
     83         if(args.length >= 6){
     84             ma = args[0];
     85             mb = args[1];
     86             mc = args[2];
     87             md = args[3];
     88             mx = args[4];
     89             my = args[5];
     90         }
     91         else{
     92             ma = mtx.a;
     93             mb = mtx.b;
     94             mc = mtx.c;
     95             md = mtx.d;
     96             mx = mtx.tx;
     97             my = mtx.ty;
     98         }
     99
    100         this.a = a * ma + b * mc;
    101         this.b = a * mb + b * md;
    102         this.c = c * ma + d * mc;
    103         this.d = c * mb + d * md;
    104         this.tx = tx * ma + ty * mc + mx;
    105         this.ty = tx * mb + ty * md + my;
    106         return this;
    107     },
    108
    109     /**
    110      * 对 Matrix 对象应用旋转转换。
    111      * @param {Number} angle 旋转的角度。
    112      * @returns {Matrix} 一个Matrix对象。
    113      */
    114     rotate: function(angle){
    115         var sin = Math.sin(angle), cos = Math.cos(angle),
    116             a = this.a, b = this.b, c = this.c, d = this.d,
    117             tx = this.tx, ty = this.ty;
    118
    119         this.a = a * cos - b * sin;
    120         this.b = a * sin + b * cos;
    121         this.c = c * cos - d * sin;
    122         this.d = c * sin + d * cos;
    123         this.tx = tx * cos - ty * sin;
    124         this.ty = tx * sin + ty * cos;
    125         return this;
    126     },
    127
    128     /**
    129      * 对矩阵应用缩放转换。
    130      * @param {Number} sx 用于沿 x 轴缩放对象的乘数。
    131      * @param {Number} sy 用于沿 y 轴缩放对象的乘数。
    132      * @returns {Matrix} 一个Matrix对象。
    133      */
    134     scale: function(sx, sy){
    135         this.a *= sx;
    136         this.d *= sy;
    137         this.c *= sx;
    138         this.b *= sy;
    139         this.tx *= sx;
    140         this.ty *= sy;
    141         return this;
    142     },
    143
    144     /**
    145      * 沿 x 和 y 轴平移矩阵，由 dx 和 dy 参数指定。
    146      * @param {Number} dx 沿 x 轴向右移动的量（以像素为单位）。
    147      * @param {Number} dy 沿 y 轴向右移动的量（以像素为单位）。
    148      * @returns {Matrix} 一个Matrix对象。
    149      */
    150     translate: function(dx, dy){
    151         this.tx += dx;
    152         this.ty += dy;
    153         return this;
    154     },
    155
    156     /**
    157      * 为每个矩阵属性设置一个值，该值将导致 null 转换。通过应用恒等矩阵转换的对象将与原始对象完全相同。
    158      * @returns {Matrix} 一个Matrix对象。
    159      */
    160     identity: function(){
    161         this.a = this.d = 1;
    162         this.b = this.c = this.tx = this.ty = 0;
    163         return this;
    164     },
    165
    166     /**
    167      * 执行原始矩阵的逆转换。您可以将一个逆矩阵应用于对象来撤消在应用原始矩阵时执行的转换。
    168      * @returns {Matrix} 一个Matrix对象。
    169      */
    170     invert: function(){
    171         var a = this.a;
    172         var b = this.b;
    173         var c = this.c;
    174         var d = this.d;
    175         var tx = this.tx;
    176         var i = a * d - b * c;
    177
    178         this.a = d / i;
    179         this.b = -b / i;
    180         this.c = -c / i;
    181         this.d = a / i;
    182         this.tx = (c * this.ty - d * tx) / i;
    183         this.ty = -(a * this.ty - b * tx) / i;
    184         return this;
    185     },
    186
    187     /**
    188      * 返回将 Matrix 对象表示的几何转换应用于指定点所产生的结果。
    189      * @param {Object} point 想要获得其矩阵转换结果的点。
    190      * @param {Boolean} round 是否对点的坐标进行向上取整。
    191      * @param {Boolean} returnNew 是否返回一个新的点。
    192      * @returns {Object} 由应用矩阵转换所产生的点。
    193      */
    194     transformPoint: function(point, round, returnNew){
    195         var x = point.x * this.a + point.y * this.c + this.tx,
    196             y = point.x * this.b + point.y * this.d + this.ty;
    197
    198         if(round){
    199             x = x + 0.5 >> 0;
    200             y = y + 0.5 >> 0;
    201         }
    202         if(returnNew) return {x:x, y:y};
    203         point.x = x;
    204         point.y = y;
    205         return point;
    206     }
    207
    208 });
    209