From 632e0cc50b383a74052321aa661c0ed2d6820f34 Mon Sep 17 00:00:00 2001 From: Saivan Date: Mon, 26 Feb 2018 19:21:18 +1100 Subject: [PATCH] Matrix operations now apply to the current matrix This commit applies matrix operations to the current matrix, so calling mat.rotate will rotate the current matrix directly --- src/matrix.js | 38 +++++++++--- src/sugar.js | 10 ++- src/transform.js | 154 +++++++++-------------------------------------- 3 files changed, 62 insertions(+), 140 deletions(-) diff --git a/src/matrix.js b/src/matrix.js index 52fb080..cde44ca 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -143,8 +143,8 @@ SVG.Matrix = SVG.invent({ // 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) + , b = ct*ky*sy - st*sx + , 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)) @@ -188,11 +188,13 @@ SVG.Matrix = SVG.invent({ } // Translate matrix , translate: function(x, y) { - return new SVG.Matrix(this.native().translate(x || 0, y || 0)) + var translation = new SVG.Matrix(this.native().translate(x || 0, y || 0)) + , matrix = this.multiply(translation) + return matrix } // Scale matrix , scale: function(x, y, cx, cy) { - // support uniformal scale + // Support uniform scaling if (arguments.length == 1) { y = x } else if (arguments.length == 3) { @@ -201,14 +203,23 @@ SVG.Matrix = SVG.invent({ y = x } - return this.around(cx, cy, new SVG.Matrix(x, 0, 0, y, 0, 0)) + // Rotate the current matrix + var scale = new SVG.Matrix(x, 0, 0, y, 0, 0) + , centered = this.around(cx, cy, rotation) + , matrix = this.multiply(centered) + return scale } // Rotate matrix , rotate: function(r, cx, cy) { - // convert degrees to radians + + // 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)) + // Construct the rotation matrix + var rotation = new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0) + , centered = this.around(cx, cy, rotation) + , matrix = this.multiply(centered) + return matrix } // Flip matrix on x or y, at a given offset , flip: function(a, o) { @@ -220,7 +231,10 @@ SVG.Matrix = SVG.invent({ } // Skew , shear: function(a, cx, cy) { - return this.around(cx, cy, new SVG.Matrix(1, a, 0, 1, 0, 0)) + var shear = new SVG.Matrix(1, a, 0, 1, 0, 0) + , centered = this.around(cx, cy, shear) + , matrix = this.multiply(centered) + return matrix } , skew: function(x, y, cx, cy) { // support uniformal skew @@ -232,11 +246,15 @@ SVG.Matrix = SVG.invent({ y = x } - // convert degrees to radians + // 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)) + // Construct the matrix + var skew = new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0) + , centered = this.around(cx, cy, skew) + , matrix = this.multiply(centered) + return matrix } // SkewX , skewX: function(x, cx, cy) { diff --git a/src/sugar.js b/src/sugar.js index 117acea..838592c 100644 --- a/src/sugar.js +++ b/src/sugar.js @@ -32,13 +32,15 @@ var sugar = { SVG.extend([SVG.Element, SVG.FX], { // Map rotation to transform - rotate: function(d, cx, cy) { +, rotate: function(angle, cx, cy) { + var matrix = new SVG.Matrix().rotate(angle, cx, cy) + return this.transform({ rotation: d, cx: cx, cy: cy }) } // Map skew to transform , skew: function(x, y, cx, cy) { return arguments.length == 1 || arguments.length == 3 ? - this.transform({ skew: x, cx: y, cy: cx }) : + this.transform({ skew: x, cx: y, cy: cx }) : this.transform({ skewX: x, skewY: y, cx: cx, cy: cy }) } // Map scale to transform @@ -56,10 +58,6 @@ SVG.extend([SVG.Element, SVG.FX], { o = typeof a == 'number' ? a : o return this.transform({ flip: a || 'both', offset: o }) } - // Map matrix to transform -, matrix: function(m) { - return this.attr('transform', new SVG.Matrix(arguments.length == 6 ? [].slice.call(arguments) : m)) - } // Opacity , opacity: function(value) { return this.attr('opacity', value) diff --git a/src/transform.js b/src/transform.js index 96b58ab..1175b13 100644 --- a/src/transform.js +++ b/src/transform.js @@ -1,4 +1,6 @@ + SVG.extend(SVG.Element, { + // Add transformations transform: function (o) { @@ -6,153 +8,58 @@ SVG.extend(SVG.Element, { * EXTRACTING PARAMETERS */ - // Get target in case of the fx module, otherwise reference this - var target = this - // Act as a getter if no object was passed if (typeof o !== 'object') { - matrix = new SVG.Matrix(target).extract() + matrix = new SVG.Matrix(this).extract() return typeof o === 'string' ? matrix[o] : matrix } - // Get the origin location - var ox = o.ox - , oy = o.oy - // Allow the user to define the origin with a string - if (typeof o.origin == "string") { + if (typeof o.origin === "string") { - // Get the bounding box to use in our calculations - var bbox = target.bbox() + // Get the bounding box and string to use in our calculations + var string = o.origin.toLowerCase().trim() + , bbox = this.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 - + o.ox = string.includes("left") ? x + : string.includes("right") ? x + width + : x + width / 2 + o.oy = string.includes("top") ? y + : string.includes("bottom") ? y + height + : y + height / 2 + + // Make sure we only pass ox and oy + o.origin = null } // Get the resulting matrix and apply it to the element var result = new SVG.Matrix().form(o) , matrixString = result.toString() - - + // Apply the result + return this.attr('transform', matrix) } + } + // Map matrix to transform +, matrix: function(m, relative) { + // Construct a matrix from the first parameter + var matrix = new SVG.Matrix(m) + // If we have a relative matrix, we just apply the old matrix + if (relative) { + var oldMatrix = new SVG.Matrix(this) + matrix = oldMatrix.multiply(matrix) + } - - - - - - - - - - // - // // get current matrix - // matrix = new SVG.Matrix(target) - // - // // ensure relative flag - // relative = !!relative || !!o.relative - // - // // act on matrix - // if (o.a != null) { - // matrix = relative ? - // // relative - // matrix.multiply(new SVG.Matrix(o)) : - // // absolute - // new SVG.Matrix(o) - // - // // act on rotation - // } else if (o.rotation != null) { - // // ensure centre point - // ensureCentre(o, target) - // - // // apply transformation - // matrix = relative ? - // // relative - // matrix.rotate(o.rotation, o.cx, o.cy) : - // // absolute - // matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy) - // - // // act on scale - // } else if (o.scale != null || o.scaleX != null || o.scaleY != null) { - // // ensure centre point - // ensureCentre(o, target) - // - // // ensure scale values on both axes - // o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1 - // o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1 - // - // if (!relative) { - // // absolute; multiply inversed values - // var e = matrix.extract() - // o.scaleX = o.scaleX * 1 / e.scaleX - // o.scaleY = o.scaleY * 1 / e.scaleY - // } - // - // matrix = matrix.scale(o.scaleX, o.scaleY, o.cx, o.cy) - // - // // act on skew - // } else if (o.skew != null || o.skewX != null || o.skewY != null) { - // // ensure centre point - // ensureCentre(o, target) - // - // // ensure skew values on both axes - // o.skewX = o.skew != null ? o.skew : o.skewX != null ? o.skewX : 0 - // o.skewY = o.skew != null ? o.skew : o.skewY != null ? o.skewY : 0 - // - // if (!relative) { - // // absolute; reset skew values - // var e = matrix.extract() - // matrix = matrix.multiply(new SVG.Matrix().skew(e.skewX, e.skewY, o.cx, o.cy).inverse()) - // } - // - // matrix = matrix.skew(o.skewX, o.skewY, o.cx, o.cy) - // - // // act on flip - // } else if (o.flip) { - // if(o.flip == 'x' || o.flip == 'y') { - // o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset - // } else { - // if(o.offset == null) { - // bbox = target.bbox() - // o.flip = bbox.cx - // o.offset = bbox.cy - // } else { - // o.flip = o.offset - // } - // } - // - // matrix = new SVG.Matrix().flip(o.flip, o.offset) - // - // // act on translate - // } else if (o.x != null || o.y != null) { - // if (relative) { - // // relative - // matrix = matrix.translate(o.x, o.y) - // } else { - // // absolute - // if (o.x != null) matrix.e = o.x - // if (o.y != null) matrix.f = o.y - // } - // } - // - // return this.attr('transform', matrix) + // Apply the matrix directly + return this.attr('transform', matrix) } }) @@ -281,7 +188,6 @@ SVG.extend(SVG.Element, { toDoc: function() { return this.toParent(this.doc()) } - }) // TODO: DESTROY -- 2.39.5