]> source.dussan.org Git - svg.js.git/commitdiff
We can form a compound matrix in the matrix module
authorSaivan <savian@me.com>
Mon, 26 Feb 2018 05:59:46 +0000 (16:59 +1100)
committerSaivan <savian@me.com>
Mon, 26 Feb 2018 05:59:46 +0000 (16:59 +1100)
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
src/transform.js

index e83fce6be137e7dddc3711c8cbb292a005fb6887..52fb080a304982b6655efb2eaa20ae9c9fb6985e 100644 (file)
@@ -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) {
index 548ac61f8560eda101f660c52945fcbb52eff0d2..96b58ab01c0ba628f6d868ea9c265ac1cb7021d6 100644 (file)
@@ -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()