From: Saivan Date: Mon, 17 Sep 2018 04:10:12 +0000 (+1000) Subject: Fixed the relative non-affine transform animations X-Git-Tag: 3.0.0~60^2~16 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=791bb2bab91a022d1b5265b40faa997ad9938ad7;p=svg.js.git Fixed the relative non-affine transform animations This commit uncovered an issue with the relative non-affine transformations. It is now correctly fixed and working. Next we should fix the affine transforms as well. Changes ======= - Fixed the relative non-affine transformation animations --- diff --git a/dirty.html b/dirty.html index ab9e3c8..f7542e6 100644 --- a/dirty.html +++ b/dirty.html @@ -25,7 +25,7 @@
- + @@ -295,6 +295,7 @@ let canvas = SVG('#canvas') // }) // +canvas.ellipse(20, 20).center(100, 100) let r = canvas.rect(200, 400).move(100, 100) .attr('opacity', 0.3) .transform({ tx: 300, ty: 500, origin: 'top-left' }) @@ -304,26 +305,38 @@ let wait = 1000 let rAnim = r.clone().attr('fill', '#f00').animate(wait).attr('fill', '#0f0') let rDecl = r.clone().attr('fill', 'blue').animate(new SVG.Spring(wait, 15)) -// Move once -setTimeout(() => { - let trans = {tx: 500, ty: 300} - r.transform(trans, true) - rAnim.animate(wait, 0, 'start').transform(trans, true) - //rDecl.transform(trans, true) -}, wait) - -// Move again +// // Move once // setTimeout(() => { -// let trans = {rotate: 300} +// let trans = {tx: 500, ty: 300} // r.transform(trans, true) -// rAnim.animate(wait).transform(trans, true) -// //rDecl.transform(trans, true) -// }, 1.5 * wait ) - - - - +// // rAnim.animate(wait, 0, 'start').transform(trans, true) +// rDecl.transform(trans, true) +// }, wait) +// Move again +setTimeout(() => { + let transform = { + origin: 'top-left', + translate: [530, 250], + rotate: 300, + scale: 2, + shear: 1, + } + let relative = true + let affine = false + r.transform(transform, relative) + rAnim.animate(wait).transform(transform, relative, affine) + rDecl.transform(transform, relative, affine) +}, 0.1 * wait ) + + +// declaritive relative (affine/nonaffine) +// declaritive absolute non affine +// normal non affine relative + +// D N +// R +// A diff --git a/src/helpers.js b/src/helpers.js index d4abc08..44bce72 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -249,9 +249,10 @@ function formatTransforms (o) { } -function getOrigin (o, element) { +function getOrigin (o, element, relative) { // Allow origin or around as the names let origin = o.around == null ? o.origin : o.around + let ox, oy // Allow the user to pass a string to rotate around a given point if (typeof origin === 'string' || origin == null) { @@ -269,13 +270,22 @@ function getOrigin (o, element) { : y + height / 2 // Set the bounds eg : "bottom-left", "Top right", "middle" etc... - const ox = o.ox != null ? o.ox : bx - const oy = o.oy != null ? o.oy : by + ox = o.ox != null ? o.ox : bx + oy = o.oy != null ? o.oy : by - // Set the origin based on the current matrix location - return [ox, oy] + } else { + ox = origin[0] + oy = origin[1] + } + + // Transform the origin into the current reference frame + if ( relative ) { + let matrix = new SVG.Matrix(element) + let originRelative = new SVG.Point( ox, oy ).transform(matrix) + ox = originRelative.x + oy = originRelative.y } // Return the origin as it is if it wasn't a string - return origin + return [ ox, oy ] } diff --git a/src/runner.js b/src/runner.js index e82d641..881efd4 100644 --- a/src/runner.js +++ b/src/runner.js @@ -615,8 +615,10 @@ SVG.extend(SVG.Runner, { // // M v -----|-----(D M v = F v)------|-----> T v // - // 1. define the final state (T) and decompose it (once) t = [tx, ty, the, lam, sy, sx] - // 2. on every frame: pull the current state of all previous transforms (M - m can change) + // 1. define the final state (T) and decompose it (once) + // t = [tx, ty, the, lam, sy, sx] + // 2. on every frame: pull the current state of all previous transforms + // (M - m can change) // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) // - Note F(0) = M @@ -624,38 +626,43 @@ SVG.extend(SVG.Runner, { // 4. Now you get the delta matrix as a result: D = F * inv(M) transform: function (transforms, relative, affine) { - if (this._isDeclarative && this._tryRetarget('transform', transforms)) { + // If we have a declarative function, we should retarget it if possible + relative = transforms.relative || relative + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { return this } // Parse the parameters var isMatrix = transforms.a != null - relative = transforms.relative || relative affine = transforms.affine != null ? transforms.affine : (affine != null ? affine : !isMatrix) - - const morpher = new SVG.Morphable().type( - affine ? SVG.Morphable.TransformBag2 : SVG.Matrix - ).stepper(this._stepper) + // Create a morepher and set its type + const morpher = new SVG.Morphable() + .type( affine ? SVG.Morphable.TransformBag2 : SVG.Matrix ) + .stepper(this._stepper) let origin let element let current let currentAngle var u = 0 - this.queue(function () { + + function setup () { // make sure element and origin is defined element = element || this.element() - origin = origin || getOrigin(transforms, element) + origin = origin || getOrigin(transforms, element, relative) + +this.element().parent().ellipse(50, 50).center(...origin) // add the runner to the element so it can merge transformations element.addRunner(this) // Deactivate all transforms that have run so far if we are absolute - if (!relative) { + let absolute = !relative + if ( absolute ) { element._clearTransformRunnersBefore(this) } @@ -686,7 +693,9 @@ SVG.extend(SVG.Runner, { morpher.from(start) morpher.to(target) - }, function (pos) { + } + + function run (pos) { // clear all other transforms before this in case something is saved // on this runner. We are absolute. We dont need these! @@ -705,23 +714,25 @@ SVG.extend(SVG.Runner, { current = new SVG.Matrix(affineParameters) this.addTransform(current) - return morpher.done() + } - }, function (newTransforms) { + function retarget (newTransforms) { // only get a new origin if it changed since the last call - if ((newTransforms.origin || 'center').toString() != (transforms.origin || 'center').toString()) { + if ( + (newTransforms.origin || 'center').toString() + != (transforms.origin || 'center').toString() + ) { origin = getOrigin (transforms, element) } // overwrite the old transformations with the new ones transforms = {...newTransforms, origin} - }) - + } + this.queue(setup, run, retarget) this._isDeclarative && this._rememberMorpher('transform', morpher) - return this }, diff --git a/src/transform.js b/src/transform.js index 0549d7a..35eb53e 100644 --- a/src/transform.js +++ b/src/transform.js @@ -58,7 +58,7 @@ SVG.extend(SVG.Element, { } // Set the origin according to the defined transform - o = {...o, origin: getOrigin(o, this, relative)} + o = {...o, origin: getOrigin(o, this)} // The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing var cleanRelative = relative === true ? this : (relative || false)