From 9f5d88672a62ab1eef42bf481d38787562363e7d Mon Sep 17 00:00:00 2001 From: Saivan Date: Mon, 26 Feb 2018 16:59:46 +1100 Subject: [PATCH] We can form a compound matrix in the matrix module This commit allows us to form a compounded matrix by setting parameters like scale, translate, rotate etc directly in a single call by asserting a particular matrix order. --- src/matrix.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++-- src/transform.js | 38 ++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/matrix.js b/src/matrix.js index e83fce6..52fb080 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -23,7 +23,8 @@ SVG.Matrix = SVG.invent({ // Add methods , extend: { - // Convert an array of affine parameters into a matrix + + // Convert an object of affine parameters into a matrix compose: function (o, cx, cy) { // Set the defaults @@ -53,7 +54,7 @@ SVG.Matrix = SVG.invent({ return matrix } // Decompose a matrix into the affine parameters needed to form it - , decompose: function (matrix, cx, cy) { + , decompose: function (matrix, cx, cy) { // Get the paramaters of the current matrix var a = matrix.a @@ -106,6 +107,50 @@ SVG.Matrix = SVG.invent({ } } // Clone matrix + , form: function (o) { + + // Get all of the parameters required to form the matrix + var flipX = o.flip && (o.flip == "x" || o.flip == "both") ? -1 : 1 + , flipY = o.flip && (o.flip == "y" || o.flip == "both") ? -1 : 1 + , kX = o.skew.length ? o.skew[0] + : isFinite(o.skew) ? o.skew + : isFinite(o.skewX) ? o.skewX + : 0 + , kY = o.skew.length ? o.skew[1] + : isFinite(o.skew) ? o.skew + : isFinite(o.skewY) ? o.skewY + : 0 + , skewX = o.scale.length ? o.scale[0] * flipX + : isFinite(o.scale) ? o.scale * flipX + : isFinite(o.scaleX) ? o.scaleX * flipX + : flipX + , skewY = o.scale.length ? o.scale[1] * flipY + : isFinite(o.scale) ? o.scale * flipY + : isFinite(o.scaleY) ? o.scaleY * flipY + : flipY + , kx = Math.tan(SVG.utils.radians(skewX)) + , ky = Math.tan(SVG.utils.radians(skewY)) + , lam = o.shear || 0 + , theta = SVG.utils.radians(o.rotate || 0) + , st = Math.sin(theta) + , ct = Math.cos(theta) + , ox = o.origin.length ? o.origin[0] : o.ox || 0 + , oy = o.origin.length ? o.origin[1] : o.oy || 0 + , px = o.position.length ? o.position[0] : o.px || ox + , py = o.position.length ? o.position[1] : o.py || oy + , tx = o.translate.length ? o.translate[0] : o.tx || 0 + , ty = o.translate.length ? o.translate[1] : o.ty || 0 + + // Form the matrix parameters... aka. welcome to wonderland! (used wolfram) + var a = ct*sx + ky*st*sy + , b = -st*sx+ct*ky*sy + , c = ct*kx*sx+st*sy + lam*(ct*sx+ky*st*sy) + , d = -kx*st*sx + ct*sy + lam*(-st*sx + ct*ky*sy) + , e = px + tx + cx*(ct*sx+ky*st*sy) + cy*(ct*kx*sx+st*sy+lam*(ct*sx+ky*st*sy)) + , f = py + ty + cx*(-st*sx + ct*ky*sy) + cy*(-kx*st*sx + ct*sy + lam*(-st*sx + ct*ky*sy)) + , result = new Matrix(a, b, c, d, e, f) + return result + } , clone: function() { return new SVG.Matrix(this) } @@ -174,6 +219,9 @@ SVG.Matrix = SVG.invent({ this.scale(-1, -1, a, o != null ? o : a) } // Skew + , shear: function(a, cx, cy) { + return this.around(cx, cy, new SVG.Matrix(1, a, 0, 1, 0, 0)) + } , skew: function(x, y, cx, cy) { // support uniformal skew if (arguments.length == 1) { diff --git a/src/transform.js b/src/transform.js index 548ac61..96b58ab 100644 --- a/src/transform.js +++ b/src/transform.js @@ -1,26 +1,50 @@ SVG.extend(SVG.Element, { // Add transformations - transform: function(o, relative) { + transform: function (o) { + + /** + * EXTRACTING PARAMETERS + */ // Get target in case of the fx module, otherwise reference this var target = this - , matrix, bbox // Act as a getter if no object was passed if (typeof o !== 'object') { - matrix = new SVG.Matrix(target).extract() return typeof o === 'string' ? matrix[o] : matrix + } + + // Get the origin location + var ox = o.ox + , oy = o.oy - // If an object was passed, then we should apply the transformations - } else { + // Allow the user to define the origin with a string + if (typeof o.origin == "string") { // Get the bounding box to use in our calculations var bbox = target.bbox() + , x = bbox.x + , y = bbox.y + , width = bbox.width + , height = bbox.height + + // Get the string to modify + var string = o.origin.toLowerCase().trim() + + // Set the bounds eg : "bottom-left", "Top right", "middle" etc... + ox = string.includes("left") ? x + : string.includes("right") ? x + width + : x + width / 2 + oy = string.includes("top") ? y + : string.includes("bottom") ? y + height + : y + height / 2 - // Extract the parameters for the affine transform - var cx = (o.origin && o.origin.length) ? + } + // Get the resulting matrix and apply it to the element + var result = new SVG.Matrix().form(o) + , matrixString = result.toString() -- 2.39.5