aboutsummaryrefslogtreecommitdiffstats
path: root/src/types/Matrix.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/types/Matrix.js')
-rw-r--r--src/types/Matrix.js419
1 files changed, 210 insertions, 209 deletions
diff --git a/src/types/Matrix.js b/src/types/Matrix.js
index 9b783da..d4f516c 100644
--- a/src/types/Matrix.js
+++ b/src/types/Matrix.js
@@ -13,72 +13,99 @@ export default class Matrix {
this.init(...args)
}
- // Initialize
- init (source) {
- var base = Matrix.fromArray([ 1, 0, 0, 1, 0, 0 ])
-
- // ensure source as object
- source = source instanceof Element ? source.matrixify()
- : typeof source === 'string' ? Matrix.fromArray(source.split(delimiter).map(parseFloat))
- : Array.isArray(source) ? Matrix.fromArray(source)
- : (typeof source === 'object' && Matrix.isMatrixLike(source)) ? source
- : (typeof source === 'object') ? new Matrix().transform(source)
- : arguments.length === 6 ? Matrix.fromArray([].slice.call(arguments))
- : base
+ static formatTransforms (o) {
+ // Get all of the parameters required to form the matrix
+ var flipBoth = o.flip === 'both' || o.flip === true
+ var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1
+ var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1
+ var skewX = o.skew && o.skew.length ? o.skew[0]
+ : isFinite(o.skew) ? o.skew
+ : isFinite(o.skewX) ? o.skewX
+ : 0
+ var skewY = o.skew && o.skew.length ? o.skew[1]
+ : isFinite(o.skew) ? o.skew
+ : isFinite(o.skewY) ? o.skewY
+ : 0
+ var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX
+ : isFinite(o.scale) ? o.scale * flipX
+ : isFinite(o.scaleX) ? o.scaleX * flipX
+ : flipX
+ var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY
+ : isFinite(o.scale) ? o.scale * flipY
+ : isFinite(o.scaleY) ? o.scaleY * flipY
+ : flipY
+ var shear = o.shear || 0
+ var theta = o.rotate || o.theta || 0
+ var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY)
+ var ox = origin.x
+ var oy = origin.y
+ // We need Point to be invalid if nothing was passed because we cannot default to 0 here. Thats why NaN
+ var position = new Point(o.position || o.px || o.positionX || NaN, o.py || o.positionY || NaN)
+ var px = position.x
+ var py = position.y
+ var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY)
+ var tx = translate.x
+ var ty = translate.y
+ var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY)
+ var rx = relative.x
+ var ry = relative.y
- // Merge the source matrix with the base matrix
- this.a = source.a != null ? source.a : base.a
- this.b = source.b != null ? source.b : base.b
- this.c = source.c != null ? source.c : base.c
- this.d = source.d != null ? source.d : base.d
- this.e = source.e != null ? source.e : base.e
- this.f = source.f != null ? source.f : base.f
+ // Populate all of the values
+ return {
+ scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py
+ }
+ }
- return this
+ static fromArray (a) {
+ return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] }
}
- // Clones this matrix
- clone () {
- return new Matrix(this)
+ static isMatrixLike (o) {
+ return (
+ o.a != null
+ || o.b != null
+ || o.c != null
+ || o.d != null
+ || o.e != null
+ || o.f != null
+ )
}
- // Transform a matrix into another matrix by manipulating the space
- transform (o) {
- // Check if o is a matrix and then left multiply it directly
- if (Matrix.isMatrixLike(o)) {
- var matrix = new Matrix(o)
- return matrix.multiplyO(this)
- }
+ // left matrix, right matrix, target matrix which is overwritten
+ static matrixMultiply (l, r, o) {
+ // Work out the product directly
+ var a = l.a * r.a + l.c * r.b
+ var b = l.b * r.a + l.d * r.b
+ var c = l.a * r.c + l.c * r.d
+ var d = l.b * r.c + l.d * r.d
+ var e = l.e + l.a * r.e + l.c * r.f
+ var f = l.f + l.b * r.e + l.d * r.f
- // Get the proposed transformations and the current transformations
- var t = Matrix.formatTransforms(o)
- var current = this
- const { x: ox, y: oy } = new Point(t.ox, t.oy).transform(current)
+ // make sure to use local variables because l/r and o could be the same
+ o.a = a
+ o.b = b
+ o.c = c
+ o.d = d
+ o.e = e
+ o.f = f
- // Construct the resulting matrix
- var transformer = new Matrix()
- .translateO(t.rx, t.ry)
- .lmultiplyO(current)
- .translateO(-ox, -oy)
- .scaleO(t.scaleX, t.scaleY)
- .skewO(t.skewX, t.skewY)
- .shearO(t.shear)
- .rotateO(t.theta)
- .translateO(ox, oy)
+ return o
+ }
- // If we want the origin at a particular place, we force it there
- if (isFinite(t.px) || isFinite(t.py)) {
- const origin = new Point(ox, oy).transform(transformer)
- // TODO: Replace t.px with isFinite(t.px)
- // Doesnt work because t.px is also 0 if it wasnt passed
- const dx = isFinite(t.px) ? t.px - origin.x : 0
- const dy = isFinite(t.py) ? t.py - origin.y : 0
- transformer.translateO(dx, dy)
- }
+ around (cx, cy, matrix) {
+ return this.clone().aroundO(cx, cy, matrix)
+ }
- // Translate now after positioning
- transformer.translateO(t.tx, t.ty)
- return transformer
+ // Transform around a center point
+ aroundO (cx, cy, matrix) {
+ var dx = cx || 0
+ var dy = cy || 0
+ return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy)
+ }
+
+ // Clones this matrix
+ clone () {
+ return new Matrix(this)
}
// Decomposes this matrix into its affine parameters
@@ -134,32 +161,52 @@ export default class Matrix {
}
}
- // Left multiplies by the given matrix
- multiply (matrix) {
- return this.clone().multiplyO(matrix)
+ // Check if two matrices are equal
+ equals (other) {
+ if (other === this) return true
+ var comp = new Matrix(other)
+ return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b)
+ && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d)
+ && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f)
}
- multiplyO (matrix) {
- // Get the matrices
- var l = this
- var r = matrix instanceof Matrix
- ? matrix
- : new Matrix(matrix)
-
- return Matrix.matrixMultiply(l, r, this)
+ // Flip matrix on x or y, at a given offset
+ flip (axis, around) {
+ return this.clone().flipO(axis, around)
}
- lmultiply (matrix) {
- return this.clone().lmultiplyO(matrix)
+ flipO (axis, around) {
+ return axis === 'x' ? this.scaleO(-1, 1, around, 0)
+ : axis === 'y' ? this.scaleO(1, -1, 0, around)
+ : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point
}
- lmultiplyO (matrix) {
- var r = this
- var l = matrix instanceof Matrix
- ? matrix
- : new Matrix(matrix)
+ // Initialize
+ init (source) {
+ var base = Matrix.fromArray([ 1, 0, 0, 1, 0, 0 ])
- return Matrix.matrixMultiply(l, r, this)
+ // ensure source as object
+ source = source instanceof Element ? source.matrixify()
+ : typeof source === 'string' ? Matrix.fromArray(source.split(delimiter).map(parseFloat))
+ : Array.isArray(source) ? Matrix.fromArray(source)
+ : (typeof source === 'object' && Matrix.isMatrixLike(source)) ? source
+ : (typeof source === 'object') ? new Matrix().transform(source)
+ : arguments.length === 6 ? Matrix.fromArray([].slice.call(arguments))
+ : base
+
+ // Merge the source matrix with the base matrix
+ this.a = source.a != null ? source.a : base.a
+ this.b = source.b != null ? source.b : base.b
+ this.c = source.c != null ? source.c : base.c
+ this.d = source.d != null ? source.d : base.d
+ this.e = source.e != null ? source.e : base.e
+ this.f = source.f != null ? source.f : base.f
+
+ return this
+ }
+
+ inverse () {
+ return this.clone().inverseO()
}
// Inverses matrix
@@ -197,44 +244,32 @@ export default class Matrix {
return this
}
- inverse () {
- return this.clone().inverseO()
+ lmultiply (matrix) {
+ return this.clone().lmultiplyO(matrix)
}
- // Translate matrix
- translate (x, y) {
- return this.clone().translateO(x, y)
- }
+ lmultiplyO (matrix) {
+ var r = this
+ var l = matrix instanceof Matrix
+ ? matrix
+ : new Matrix(matrix)
- translateO (x, y) {
- this.e += x || 0
- this.f += y || 0
- return this
+ return Matrix.matrixMultiply(l, r, this)
}
- // Scale matrix
- scale (x, y, cx, cy) {
- return this.clone().scaleO(...arguments)
+ // Left multiplies by the given matrix
+ multiply (matrix) {
+ return this.clone().multiplyO(matrix)
}
- scaleO (x, y = x, cx = 0, cy = 0) {
- // Support uniform scaling
- if (arguments.length === 3) {
- cy = cx
- cx = y
- y = x
- }
-
- const { a, b, c, d, e, f } = this
-
- this.a = a * x
- this.b = b * y
- this.c = c * x
- this.d = d * y
- this.e = e * x - cx * x + cx
- this.f = f * y - cy * y + cy
+ multiplyO (matrix) {
+ // Get the matrices
+ var l = this
+ var r = matrix instanceof Matrix
+ ? matrix
+ : new Matrix(matrix)
- return this
+ return Matrix.matrixMultiply(l, r, this)
}
// Rotate matrix
@@ -261,15 +296,29 @@ export default class Matrix {
return this
}
- // Flip matrix on x or y, at a given offset
- flip (axis, around) {
- return this.clone().flipO(axis, around)
+ // Scale matrix
+ scale (x, y, cx, cy) {
+ return this.clone().scaleO(...arguments)
}
- flipO (axis, around) {
- return axis === 'x' ? this.scaleO(-1, 1, around, 0)
- : axis === 'y' ? this.scaleO(1, -1, 0, around)
- : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point
+ scaleO (x, y = x, cx = 0, cy = 0) {
+ // Support uniform scaling
+ if (arguments.length === 3) {
+ cy = cx
+ cx = y
+ y = x
+ }
+
+ const { a, b, c, d, e, f } = this
+
+ this.a = a * x
+ this.b = b * y
+ this.c = c * x
+ this.d = d * y
+ this.e = e * x - cx * x + cx
+ this.f = f * y - cy * y + cy
+
+ return this
}
// Shear matrix
@@ -329,33 +378,63 @@ export default class Matrix {
return this.skew(0, y, cx, cy)
}
- // Transform around a center point
- aroundO (cx, cy, matrix) {
- var dx = cx || 0
- var dy = cy || 0
- return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy)
+ toArray () {
+ return [ this.a, this.b, this.c, this.d, this.e, this.f ]
}
- around (cx, cy, matrix) {
- return this.clone().aroundO(cx, cy, matrix)
+ // Convert matrix to string
+ toString () {
+ return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'
}
- // Check if two matrices are equal
- equals (other) {
- if (other === this) return true
- var comp = new Matrix(other)
- return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b)
- && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d)
- && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f)
+ // Transform a matrix into another matrix by manipulating the space
+ transform (o) {
+ // Check if o is a matrix and then left multiply it directly
+ if (Matrix.isMatrixLike(o)) {
+ var matrix = new Matrix(o)
+ return matrix.multiplyO(this)
+ }
+
+ // Get the proposed transformations and the current transformations
+ var t = Matrix.formatTransforms(o)
+ var current = this
+ const { x: ox, y: oy } = new Point(t.ox, t.oy).transform(current)
+
+ // Construct the resulting matrix
+ var transformer = new Matrix()
+ .translateO(t.rx, t.ry)
+ .lmultiplyO(current)
+ .translateO(-ox, -oy)
+ .scaleO(t.scaleX, t.scaleY)
+ .skewO(t.skewX, t.skewY)
+ .shearO(t.shear)
+ .rotateO(t.theta)
+ .translateO(ox, oy)
+
+ // If we want the origin at a particular place, we force it there
+ if (isFinite(t.px) || isFinite(t.py)) {
+ const origin = new Point(ox, oy).transform(transformer)
+ // TODO: Replace t.px with isFinite(t.px)
+ // Doesnt work because t.px is also 0 if it wasnt passed
+ const dx = isFinite(t.px) ? t.px - origin.x : 0
+ const dy = isFinite(t.py) ? t.py - origin.y : 0
+ transformer.translateO(dx, dy)
+ }
+
+ // Translate now after positioning
+ transformer.translateO(t.tx, t.ty)
+ return transformer
}
- // Convert matrix to string
- toString () {
- return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'
+ // Translate matrix
+ translate (x, y) {
+ return this.clone().translateO(x, y)
}
- toArray () {
- return [ this.a, this.b, this.c, this.d, this.e, this.f ]
+ translateO (x, y) {
+ this.e += x || 0
+ this.f += y || 0
+ return this
}
valueOf () {
@@ -369,84 +448,6 @@ export default class Matrix {
}
}
- static fromArray (a) {
- return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] }
- }
-
- static isMatrixLike (o) {
- return (
- o.a != null
- || o.b != null
- || o.c != null
- || o.d != null
- || o.e != null
- || o.f != null
- )
- }
-
- static formatTransforms (o) {
- // Get all of the parameters required to form the matrix
- var flipBoth = o.flip === 'both' || o.flip === true
- var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1
- var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1
- var skewX = o.skew && o.skew.length ? o.skew[0]
- : isFinite(o.skew) ? o.skew
- : isFinite(o.skewX) ? o.skewX
- : 0
- var skewY = o.skew && o.skew.length ? o.skew[1]
- : isFinite(o.skew) ? o.skew
- : isFinite(o.skewY) ? o.skewY
- : 0
- var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX
- : isFinite(o.scale) ? o.scale * flipX
- : isFinite(o.scaleX) ? o.scaleX * flipX
- : flipX
- var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY
- : isFinite(o.scale) ? o.scale * flipY
- : isFinite(o.scaleY) ? o.scaleY * flipY
- : flipY
- var shear = o.shear || 0
- var theta = o.rotate || o.theta || 0
- var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY)
- var ox = origin.x
- var oy = origin.y
- // We need Point to be invalid if nothing was passed because we cannot default to 0 here. Thats why NaN
- var position = new Point(o.position || o.px || o.positionX || NaN, o.py || o.positionY || NaN)
- var px = position.x
- var py = position.y
- var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY)
- var tx = translate.x
- var ty = translate.y
- var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY)
- var rx = relative.x
- var ry = relative.y
-
- // Populate all of the values
- return {
- scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py
- }
- }
-
- // left matrix, right matrix, target matrix which is overwritten
- static matrixMultiply (l, r, o) {
- // Work out the product directly
- var a = l.a * r.a + l.c * r.b
- var b = l.b * r.a + l.d * r.b
- var c = l.a * r.c + l.c * r.d
- var d = l.b * r.c + l.d * r.d
- var e = l.e + l.a * r.e + l.c * r.f
- var f = l.f + l.b * r.e + l.d * r.f
-
- // make sure to use local variables because l/r and o could be the same
- o.a = a
- o.b = b
- o.c = c
- o.d = d
- o.e = e
- o.f = f
-
- return o
- }
}
export function ctm () {