Current File : //home/tradevaly/www/node_modules/svg.js/src/matrix.js |
SVG.Matrix = SVG.invent({
// Initialize
create: function(source) {
var i, base = arrayToMatrix([1, 0, 0, 1, 0, 0])
// ensure source as object
source = source instanceof SVG.Element ?
source.matrixify() :
typeof source === 'string' ?
arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) :
arguments.length == 6 ?
arrayToMatrix([].slice.call(arguments)) :
Array.isArray(source) ?
arrayToMatrix(source) :
typeof source === 'object' ?
source : base
// merge source
for (i = abcdef.length - 1; i >= 0; --i)
this[abcdef[i]] = source[abcdef[i]] != null ?
source[abcdef[i]] : base[abcdef[i]]
}
// Add methods
, extend: {
// Extract individual transformations
extract: function() {
// find delta transform points
var px = deltaTransformPoint(this, 0, 1)
, py = deltaTransformPoint(this, 1, 0)
, skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90
return {
// translation
x: this.e
, y: this.f
, transformedX:(this.e * Math.cos(skewX * Math.PI / 180) + this.f * Math.sin(skewX * Math.PI / 180)) / Math.sqrt(this.a * this.a + this.b * this.b)
, transformedY:(this.f * Math.cos(skewX * Math.PI / 180) + this.e * Math.sin(-skewX * Math.PI / 180)) / Math.sqrt(this.c * this.c + this.d * this.d)
// skew
, skewX: -skewX
, skewY: 180 / Math.PI * Math.atan2(py.y, py.x)
// scale
, scaleX: Math.sqrt(this.a * this.a + this.b * this.b)
, scaleY: Math.sqrt(this.c * this.c + this.d * this.d)
// rotation
, rotation: skewX
, a: this.a
, b: this.b
, c: this.c
, d: this.d
, e: this.e
, f: this.f
, matrix: new SVG.Matrix(this)
}
}
// Clone matrix
, clone: function() {
return new SVG.Matrix(this)
}
// Morph one matrix into another
, morph: function(matrix) {
// store new destination
this.destination = new SVG.Matrix(matrix)
return this
}
// Get morphed matrix at a given position
, at: function(pos) {
// make sure a destination is defined
if (!this.destination) return this
// calculate morphed matrix at a given position
var matrix = new SVG.Matrix({
a: this.a + (this.destination.a - this.a) * pos
, b: this.b + (this.destination.b - this.b) * pos
, c: this.c + (this.destination.c - this.c) * pos
, d: this.d + (this.destination.d - this.d) * pos
, e: this.e + (this.destination.e - this.e) * pos
, f: this.f + (this.destination.f - this.f) * pos
})
return matrix
}
// Multiplies by given matrix
, multiply: function(matrix) {
return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native()))
}
// Inverses matrix
, inverse: function() {
return new SVG.Matrix(this.native().inverse())
}
// Translate matrix
, translate: function(x, y) {
return new SVG.Matrix(this.native().translate(x || 0, y || 0))
}
// Scale matrix
, scale: function(x, y, cx, cy) {
// support uniformal scale
if (arguments.length == 1) {
y = x
} else if (arguments.length == 3) {
cy = cx
cx = y
y = x
}
return this.around(cx, cy, new SVG.Matrix(x, 0, 0, y, 0, 0))
}
// Rotate matrix
, rotate: function(r, cx, cy) {
// convert degrees to radians
r = SVG.utils.radians(r)
return this.around(cx, cy, new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0))
}
// Flip matrix on x or y, at a given offset
, flip: function(a, o) {
return a == 'x' ?
this.scale(-1, 1, o, 0) :
a == 'y' ?
this.scale(1, -1, 0, o) :
this.scale(-1, -1, a, o != null ? o : a)
}
// Skew
, skew: function(x, y, cx, cy) {
// support uniformal skew
if (arguments.length == 1) {
y = x
} else if (arguments.length == 3) {
cy = cx
cx = y
y = x
}
// convert degrees to radians
x = SVG.utils.radians(x)
y = SVG.utils.radians(y)
return this.around(cx, cy, new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0))
}
// SkewX
, skewX: function(x, cx, cy) {
return this.skew(x, 0, cx, cy)
}
// SkewY
, skewY: function(y, cx, cy) {
return this.skew(0, y, cx, cy)
}
// Transform around a center point
, around: function(cx, cy, matrix) {
return this
.multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))
.multiply(matrix)
.multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))
}
// Convert to native SVGMatrix
, native: function() {
// create new matrix
var matrix = SVG.parser.native.createSVGMatrix()
// update with current values
for (var i = abcdef.length - 1; i >= 0; i--)
matrix[abcdef[i]] = this[abcdef[i]]
return matrix
}
// Convert matrix to string
, toString: function() {
// Construct the matrix directly, avoid values that are too small
return 'matrix(' + float32String(this.a) + ',' + float32String(this.b)
+ ',' + float32String(this.c) + ',' + float32String(this.d)
+ ',' + float32String(this.e) + ',' + float32String(this.f)
+ ')'
}
}
// Define parent
, parent: SVG.Element
// Add parent method
, construct: {
// Get current matrix
ctm: function() {
return new SVG.Matrix(this.node.getCTM())
},
// Get current screen matrix
screenCTM: function() {
/* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537
This is needed because FF does not return the transformation matrix
for the inner coordinate system when getScreenCTM() is called on nested svgs.
However all other Browsers do that */
if(this instanceof SVG.Nested) {
var rect = this.rect(1,1)
var m = rect.node.getScreenCTM()
rect.remove()
return new SVG.Matrix(m)
}
return new SVG.Matrix(this.node.getScreenCTM())
}
}
})