UNPKG

bodymovin

Version:

After Effects plugin for exporting animations to SVG + JavaScript or canvas + JavaScript

367 lines (326 loc) 13.4 kB
/*! Transformation Matrix v2.0 (c) Epistemex 2014-2015 www.epistemex.com By Ken Fyrstenberg Contributions by leeoniya. License: MIT, header required. */ /** * 2D transformation matrix object initialized with identity matrix. * * The matrix can synchronize a canvas context by supplying the context * as an argument, or later apply current absolute transform to an * existing context. * * All values are handled as floating point values. * * @param {CanvasRenderingContext2D} [context] - Optional context to sync with Matrix * @prop {number} a - scale x * @prop {number} b - shear y * @prop {number} c - shear x * @prop {number} d - scale y * @prop {number} e - translate x * @prop {number} f - translate y * @prop {CanvasRenderingContext2D|null} [context=null] - set or get current canvas context * @constructor */ var Matrix = (function(){ function reset(){ this.props[0] = 1; this.props[1] = 0; this.props[2] = 0; this.props[3] = 0; this.props[4] = 0; this.props[5] = 1; this.props[6] = 0; this.props[7] = 0; this.props[8] = 0; this.props[9] = 0; this.props[10] = 1; this.props[11] = 0; this.props[12] = 0; this.props[13] = 0; this.props[14] = 0; this.props[15] = 1; return this; } function rotate(angle) { if(angle === 0){ return this; } var mCos = Math.cos(angle); var mSin = Math.sin(angle); return this._t(mCos, -mSin, 0, 0 , mSin, mCos, 0, 0 , 0, 0, 1, 0 , 0, 0, 0, 1); } function rotateX(angle){ if(angle === 0){ return this; } var mCos = Math.cos(angle); var mSin = Math.sin(angle); return this._t(1, 0, 0, 0 , 0, mCos, -mSin, 0 , 0, mSin, mCos, 0 , 0, 0, 0, 1); } function rotateY(angle){ if(angle === 0){ return this; } var mCos = Math.cos(angle); var mSin = Math.sin(angle); return this._t(mCos, 0, mSin, 0 , 0, 1, 0, 0 , -mSin, 0, mCos, 0 , 0, 0, 0, 1); } function rotateZ(angle){ if(angle === 0){ return this; } var mCos = Math.cos(angle); var mSin = Math.sin(angle); return this._t(mCos, -mSin, 0, 0 , mSin, mCos, 0, 0 , 0, 0, 1, 0 , 0, 0, 0, 1); } function shear(sx,sy){ return this._t(1, sy, sx, 1, 0, 0); } function skew(ax, ay){ return this.shear(Math.tan(ax), Math.tan(ay)); } function skewFromAxis(ax, angle){ var mCos = Math.cos(angle); var mSin = Math.sin(angle); return this._t(mCos, mSin, 0, 0 , -mSin, mCos, 0, 0 , 0, 0, 1, 0 , 0, 0, 0, 1) ._t(1, 0, 0, 0 , Math.tan(ax), 1, 0, 0 , 0, 0, 1, 0 , 0, 0, 0, 1) ._t(mCos, -mSin, 0, 0 , mSin, mCos, 0, 0 , 0, 0, 1, 0 , 0, 0, 0, 1); //return this._t(mCos, mSin, -mSin, mCos, 0, 0)._t(1, 0, Math.tan(ax), 1, 0, 0)._t(mCos, -mSin, mSin, mCos, 0, 0); } function scale(sx, sy, sz) { sz = isNaN(sz) ? 1 : sz; if(sx == 1 && sy == 1 && sz == 1){ return this; } return this._t(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1); } function setTransform(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) { this.props[0] = a; this.props[1] = b; this.props[2] = c; this.props[3] = d; this.props[4] = e; this.props[5] = f; this.props[6] = g; this.props[7] = h; this.props[8] = i; this.props[9] = j; this.props[10] = k; this.props[11] = l; this.props[12] = m; this.props[13] = n; this.props[14] = o; this.props[15] = p; return this; } function translate(tx, ty, tz) { tz = tz || 0; if(tx !== 0 || ty !== 0 || tz !== 0){ return this._t(1,0,0,0,0,1,0,0,0,0,1,0,tx,ty,tz,1); } return this; } function transform(a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2, p2) { if(a2 === 1 && b2 === 0 && c2 === 0 && d2 === 0 && e2 === 0 && f2 === 1 && g2 === 0 && h2 === 0 && i2 === 0 && j2 === 0 && k2 === 1 && l2 === 0){ if(m2 !== 0 || n2 !== 0 || o2 !== 0){ this.props[12] = this.props[12] * a2 + this.props[13] * e2 + this.props[14] * i2 + this.props[15] * m2 ; this.props[13] = this.props[12] * b2 + this.props[13] * f2 + this.props[14] * j2 + this.props[15] * n2 ; this.props[14] = this.props[12] * c2 + this.props[13] * g2 + this.props[14] * k2 + this.props[15] * o2 ; this.props[15] = this.props[12] * d2 + this.props[13] * h2 + this.props[14] * l2 + this.props[15] * p2 ; } this._identityCalculated = false; return this; } var a1 = this.props[0]; var b1 = this.props[1]; var c1 = this.props[2]; var d1 = this.props[3]; var e1 = this.props[4]; var f1 = this.props[5]; var g1 = this.props[6]; var h1 = this.props[7]; var i1 = this.props[8]; var j1 = this.props[9]; var k1 = this.props[10]; var l1 = this.props[11]; var m1 = this.props[12]; var n1 = this.props[13]; var o1 = this.props[14]; var p1 = this.props[15]; /* matrix order (canvas compatible): * ace * bdf * 001 */ this.props[0] = a1 * a2 + b1 * e2 + c1 * i2 + d1 * m2; this.props[1] = a1 * b2 + b1 * f2 + c1 * j2 + d1 * n2 ; this.props[2] = a1 * c2 + b1 * g2 + c1 * k2 + d1 * o2 ; this.props[3] = a1 * d2 + b1 * h2 + c1 * l2 + d1 * p2 ; this.props[4] = e1 * a2 + f1 * e2 + g1 * i2 + h1 * m2 ; this.props[5] = e1 * b2 + f1 * f2 + g1 * j2 + h1 * n2 ; this.props[6] = e1 * c2 + f1 * g2 + g1 * k2 + h1 * o2 ; this.props[7] = e1 * d2 + f1 * h2 + g1 * l2 + h1 * p2 ; this.props[8] = i1 * a2 + j1 * e2 + k1 * i2 + l1 * m2 ; this.props[9] = i1 * b2 + j1 * f2 + k1 * j2 + l1 * n2 ; this.props[10] = i1 * c2 + j1 * g2 + k1 * k2 + l1 * o2 ; this.props[11] = i1 * d2 + j1 * h2 + k1 * l2 + l1 * p2 ; this.props[12] = m1 * a2 + n1 * e2 + o1 * i2 + p1 * m2 ; this.props[13] = m1 * b2 + n1 * f2 + o1 * j2 + p1 * n2 ; this.props[14] = m1 * c2 + n1 * g2 + o1 * k2 + p1 * o2 ; this.props[15] = m1 * d2 + n1 * h2 + o1 * l2 + p1 * p2 ; this._identityCalculated = false; return this; } function isIdentity() { if(!this._identityCalculated){ this._identity = !(this.props[0] !== 1 || this.props[1] !== 0 || this.props[2] !== 0 || this.props[3] !== 0 || this.props[4] !== 0 || this.props[5] !== 1 || this.props[6] !== 0 || this.props[7] !== 0 || this.props[8] !== 0 || this.props[9] !== 0 || this.props[10] !== 1 || this.props[11] !== 0 || this.props[12] !== 0 || this.props[13] !== 0 || this.props[14] !== 0 || this.props[15] !== 1); this._identityCalculated = true; } return this._identity; } function clone(matr){ var i; for(i=0;i<16;i+=1){ matr.props[i] = this.props[i]; } } function cloneFromProps(props){ var i; for(i=0;i<16;i+=1){ this.props[i] = props[i]; } } function applyToPoint(x, y, z) { return { x: x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12], y: x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13], z: x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14] }; /*return { x: x * me.a + y * me.c + me.e, y: x * me.b + y * me.d + me.f };*/ } function applyToX(x, y, z) { return x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12]; } function applyToY(x, y, z) { return x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13]; } function applyToZ(x, y, z) { return x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14]; } function inversePoint(pt) { var determinant = this.props[0] * this.props[5] - this.props[1] * this.props[4]; var a = this.props[5]/determinant; var b = - this.props[1]/determinant; var c = - this.props[4]/determinant; var d = this.props[0]/determinant; var e = (this.props[4] * this.props[13] - this.props[5] * this.props[12])/determinant; var f = - (this.props[0] * this.props[13] - this.props[1] * this.props[12])/determinant; return [pt[0] * a + pt[1] * c + e, pt[0] * b + pt[1] * d + f, 0]; } function inversePoints(pts){ var i, len = pts.length, retPts = []; for(i=0;i<len;i+=1){ retPts[i] = inversePoint(pts[i]); } return retPts; } function applyToPointArray(x,y,z,dimensions){ if(dimensions && dimensions === 2) { var arr = point_pool.newPoint(); arr[0] = x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12]; arr[1] = x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13]; return arr; } return [x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12],x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13],x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14]]; } function applyToPointStringified(x, y) { if(this.isIdentity()) { return x + ',' + y; } return (bm_rnd(x * this.props[0] + y * this.props[4] + this.props[12]))+','+(bm_rnd(x * this.props[1] + y * this.props[5] + this.props[13])); } function toArray() { return [this.props[0],this.props[1],this.props[2],this.props[3],this.props[4],this.props[5],this.props[6],this.props[7],this.props[8],this.props[9],this.props[10],this.props[11],this.props[12],this.props[13],this.props[14],this.props[15]]; } function toCSS() { if(isSafari){ return "matrix3d(" + roundTo2Decimals(this.props[0]) + ',' + roundTo2Decimals(this.props[1]) + ',' + roundTo2Decimals(this.props[2]) + ',' + roundTo2Decimals(this.props[3]) + ',' + roundTo2Decimals(this.props[4]) + ',' + roundTo2Decimals(this.props[5]) + ',' + roundTo2Decimals(this.props[6]) + ',' + roundTo2Decimals(this.props[7]) + ',' + roundTo2Decimals(this.props[8]) + ',' + roundTo2Decimals(this.props[9]) + ',' + roundTo2Decimals(this.props[10]) + ',' + roundTo2Decimals(this.props[11]) + ',' + roundTo2Decimals(this.props[12]) + ',' + roundTo2Decimals(this.props[13]) + ',' + roundTo2Decimals(this.props[14]) + ',' + roundTo2Decimals(this.props[15]) + ')'; } else { this.cssParts[1] = this.props.join(','); return this.cssParts.join(''); } } function to2dCSS() { return "matrix(" + roundTo2Decimals(this.props[0]) + ',' + roundTo2Decimals(this.props[1]) + ',' + roundTo2Decimals(this.props[4]) + ',' + roundTo2Decimals(this.props[5]) + ',' + roundTo2Decimals(this.props[12]) + ',' + roundTo2Decimals(this.props[13]) + ")"; } function toString() { return "" + this.toArray(); } return function(){ this.reset = reset; this.rotate = rotate; this.rotateX = rotateX; this.rotateY = rotateY; this.rotateZ = rotateZ; this.skew = skew; this.skewFromAxis = skewFromAxis; this.shear = shear; this.scale = scale; this.setTransform = setTransform; this.translate = translate; this.transform = transform; this.applyToPoint = applyToPoint; this.applyToX = applyToX; this.applyToY = applyToY; this.applyToZ = applyToZ; this.applyToPointArray = applyToPointArray; this.applyToPointStringified = applyToPointStringified; this.toArray = toArray; this.toCSS = toCSS; this.to2dCSS = to2dCSS; this.toString = toString; this.clone = clone; this.cloneFromProps = cloneFromProps; this.inversePoints = inversePoints; this.inversePoint = inversePoint; this._t = this.transform; this.isIdentity = isIdentity; this._identity = true; this._identityCalculated = false; this.props = [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]; this.cssParts = ['matrix3d(','',')']; } }()); function Matrix() { }