From 5a1be483befaa644fd996b7be74ef59655160f95 Mon Sep 17 00:00:00 2001 From: Saivan Date: Tue, 3 Jul 2018 22:07:53 +1000 Subject: [PATCH] Fixed an issue that occurred when we applied more than one transform This commit allows us to apply more than one transform to an element, and have them correctly applied to the element. --- dirty.html | 80 +++++++++++++++++++++++++++++++++----------------- src/helpers.js | 35 ++++++++++++++++++++-- src/matrix.js | 3 +- 3 files changed, 86 insertions(+), 32 deletions(-) diff --git a/dirty.html b/dirty.html index 95227cf..1d4601c 100644 --- a/dirty.html +++ b/dirty.html @@ -10,10 +10,17 @@ + + + + + + + -
+
@@ -198,39 +205,58 @@ rectangle.animate().transform({ let canvas = SVG('#canvas') -// // Make the green rectange -// canvas.rect(200, 400).move(500, 400) -// .attr('opacity', 0.3) -// .addClass('green') - -// Make the pink rectangle -let a = canvas.rect(200, 400).move(500, 400) - .attr('opacity', 0.3) - .addClass('pink') - .transform({ px: 100, py: 500, origin: 'top-left' }) - -var timer = 0 -a.timeline().source(() => { - timer += 1 - document.querySelector('#absolute span').textContent = timer - return timer +SVG('#absolute').on('input slide', function (e) { + var val = e.target.value + canvas.clear() + canvas.ellipse(20, 20) + let re = canvas.rect(300, 150).move(100, 150).attr('opacity', 0.5) + re.clone() + .transform({rotate: 45, skew: 30}, true) + + re.clone() + .transform({rotate: 45, skew: 30}, true) + .transform({rotate: val}, true) }) -let obj = { rotate: 180, shear:2, origin: [600, 600], translate: [200, 100] } -let obj2 = { rotate: 180, shear:2, origin: [600, 600], translate: [200, 100] } -a.clone() // startPosition -a.clone().transform(obj, true).transform(obj2, true) // endPosition -//a.animate(new SVG.Spring(50, 30)).transform(obj) // animation -a.animate(300).transform(obj, true).transform(obj2, true) // animation +// transform({}) -// Put an ellipse where we expect the object to be -canvas.ellipse(30, 30).center(100, 500) - .attr('opacity', 0.3) - .addClass('dark-pink') +// // Make the green rectange +// canvas.rect(200, 400).move(500, 400) +// .attr('opacity', 0.3) +// .addClass('green') + +// Make the pink rectangle +// let a = canvas.rect(200, 400).move(500, 400) +// .attr('opacity', 0.3) +// .addClass('pink') +// .transform({ px: 100, py: 500, origin: 'top-left' }) +// +// +// var timer = 0 +// a.timeline().source(() => { +// timer += 1 +// document.querySelector('#absolute span').textContent = timer +// return timer +// }) +// +// +// let obj = { rotate: 180, shear:2, origin: [600, 600], translate: [200, 100] } +// let obj2 = { rotate: 180, shear:2, origin: [600, 600], translate: [200, 100] } +// +// a.clone() // startPosition +// a.clone().transform(obj, true).transform(obj2, true) // endPosition +// //a.animate(new SVG.Spring(50, 30)).transform(obj) // animation +// a.animate(300).transform(obj, true).transform(obj2, true) // animation +// +// +// // Put an ellipse where we expect the object to be +// canvas.ellipse(30, 30).center(100, 500) +// .attr('opacity', 0.3) +// .addClass('dark-pink') // var timeline = new SVG.Timeline().pause() diff --git a/src/helpers.js b/src/helpers.js index 99a7c0b..755beba 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -260,23 +260,52 @@ function formatTransforms (o) { } } +/* TODO: KILL + + + 1. Transform the origin by figuring out the delta + + - At the start, we had: + + let Sinv = new SVG.Matrix(element).inverse() + let origin = getOrigin(element) + + - At a particular frame we have: + + let C = Matrix(element) + let newOrigin = origin.transform(S.inv).transform(C) + +*/ + + function getOrigin (o, element) { // Allow origin or around as the names let origin = o.around == null ? o.origin : o.around // Allow the user to pass a string to rotate around a given point if (typeof origin === 'string' || origin == null) { + // Get the bounding box of the element with no transformations applied const string = (origin || 'center').toLowerCase().trim() const { height, width, x, y } = element.bbox() - // Set the bounds eg : "bottom-left", "Top right", "middle" etc... - const ox = o.ox || string.includes('left') ? x + // Calculate the transformed x and y coordinates + const bx = string.includes('left') ? x : string.includes('right') ? x + width : x + width / 2 - const oy = o.oy || string.includes('top') ? y + const by = string.includes('top') ? y : string.includes('bottom') ? y + height : y + height / 2 + + // Find the new center in the transformed coordinates + const matrix = new SVG.Matrix(element) + const {x: tx , y: ty} = new SVG.Point(bx, by).transform(matrix) + + // Set the bounds eg : "bottom-left", "Top right", "middle" etc... + const ox = o.ox != null ? o.ox : tx + const oy = o.oy != null ? o.oy : ty + + // Set the origin based on the current matrix location return [ox, oy] } diff --git a/src/matrix.js b/src/matrix.js index 4396816..07dc82b 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -48,7 +48,7 @@ SVG.Matrix = SVG.invent({ var currentTransform = new SVG.Matrix(this) // Construct the resulting matrix - var transformer = new SVG.Matrix() + var transformer = new SVG.Matrix(currentTransform) .translate(-t.ox, -t.oy) .scale(t.scaleX, t.scaleY) .skew(t.skewX, t.skewY) @@ -56,7 +56,6 @@ SVG.Matrix = SVG.invent({ .rotate(t.theta) .translate(t.ox, t.oy) .translate(t.rx, t.ry) - .lmultiply(currentTransform) // If we want the origin at a particular place, we force it there if (isFinite(t.px) || isFinite(t.py)) { -- 2.39.5