var timer = 0
-let recy = SVG('<rect>').addTo('svg').size(100, 100).transform({translateX: -50, translateY: -50})
+let recy = SVG('<rect>').addTo('svg').size(100, 100)//.transform({translateX: -50, translateY: -50})
recy.timeline().source(() => {
- timer += 16
+ timer += 5
return timer
})
var runner = recy
- .animate(5000)
- .transform({rotate: 360, origin: [200, 200]}, true)
- .transform({translate: [200, 200]}, true)
- .animate(2000, 1000, 'absolute')
- .transform({scale: 2}, true)
+ // .animate(100).attr('fill', '#fff')
+ //.animate().transform({rotate: -45, origin: [50, 50]})
+ .animate(500)
+ .transform({
+ a: -1, b: -0.1, c: 0.1, d: -1, e: 200, f: 200, affine: true
+ }, true)
+ .animate(500, 0, 'after')
+ .transform({scale:2}, true)
+ // .transform({rotate: 360}, true)
+ // .transform({translateX: 50, translateY: 50}, true)
+ //.transform({translateX: 50, translateY: 50}, true)
+ // .animate(500, 0, 'absolute')
+ // .transform({scale: 2}, true)
// .animate(2000, 0, 'absolute')
// .transform({rotate: -300})
this.tags = {}
// save transforms applied to this runner
- // this.transforms = []
+ this.transforms = new SVG.Matrix()
this.count = 0
// Looping variables
// this.fire('start', this)
}
+ // Work out if the runner is finished
+ // set the done flag here so animations know,
+ // that they are running in the last step
+ // (this is good for transformations which can be merged)
+ this.done = !declarative && !justFinished && this._time >= duration
+
// Call initialise and the run function
this._initialise()
var declarative = this._isDeclarative
if ( runNow || declarative ) {
+ this.transforms = new SVG.Matrix()
var converged = this._run(declarative ? dt : position)
// this.fire('step', this)
}
- this.count = 0
+ // correct the done flag here
+ // declaritive animations itself know when they converged
+ this.done = this.done || (converged && declarative)
- // Work out if we are done and return this
- this.done = (converged && declarative)
- || (this._time >= duration && !justFinished && !declarative)
if (this.done) {
// this.fire('finish', this)
}
},
_pushLeft: function (transform) {
- // this.transforms.push(transform)
- // this.element().addRunner(this)
- this.element()._queueTransform(transform, false, this.id, this.count++)
+ this.transforms = this.transforms.lmultiply(transform)
+ this.element().addRunner(this)
+ //this.element()._queueTransform(transform, false, this.id, this.count++)
return this
},
_currentTransform: function () {
- return this.element()._currentTransform(this.id, this.count)
+ return this.element()._currentTransform(this)
}
},
}
}
-recudeTransform = function (arr, base) {
- return arr.reduceRight(function (last, curr) {
- if(Array.isArray(curr)) return recudeTransform(curr, last)
+reduceTransform = function (arr, base) {
+ return arr.reduce(function (last, curr) {
return last.lmultiply(curr)
}, base)
}
+function mergeTransforms () {
+ var net = reduceTransform(this.runners.map(el => el.transforms), this._baseTransform)
+ this.transform(net)
+ this._mergeTransforms = null
+ //_this._transformationChain = []
+}
+
SVG.extend(SVG.Element, {
+ addRunner: function (r) {
+ var runners = this.runners
+ var index = ((runners.indexOf(r) + 1) || this.runners.push(r)) - 1
+
+ if(r.done) this.checkForSimplification(index)
+
+ this._mergeTransforms = SVG.Animator.transform_frame(mergeTransforms.bind(this))
+ },
+
+ checkForSimplification: function (index) {
+ var r
+ if(index == 0) {
+ r = this.runners.shift()
+ this._baseTransform = this._baseTransform.lmultiply(r.transforms)
+ r.transforms = new SVG.Matrix()
+ return
+ }
+
+ var r = this.runners[index-1]
+
+ if(!r.done) return
+console.log(r, this.runners[index])
+ var obj = {
+ done: true,
+ transforms: r.transforms.multiply(this.runners[index].transforms)
+ }
+
+ this.runners.splice(index-1, 2, obj)
+
+ },
+
_prepareRunner: function () {
if (!this._baseTransform) {
this._baseTransform = new SVG.Matrix(this)
this._mergeTransforms = null
this._transformationChain = []
+ this.runners = []
}
},
// This function will merge all of the transforms on the chain, but it
// should only be called at most, once per animation frame
function mergeTransforms () {
- var net = recudeTransform(_this._transformationChain.map(el => el.transforms), _this._baseTransform)
+ var net = reduceTransform(_this.runners.map(el => el.transforms), _this._baseTransform)
_this.transform(net)
_this._mergeTransforms = null
//_this._transformationChain = []
this._mergeTransforms = SVG.Animator.transform_frame(mergeTransforms)
},
- _currentTransform: function (id, count) {
- var runners = []
- var chain = this._transformationChain
-
- for(var i = 0, len = chain.length; i < len; ++i) {
- if(chain[i].id == id) {
- var a = {id: id, transforms: chain[i].transforms.slice(0, count+1)}
- runners.push(a)
- break
- }
+ _currentTransform: function (r) {
- runners.push(chain[i])
- }
+ var transforms = this.runners.slice(0, this.runners.indexOf(this)+1).map(el => el.transforms)
- return recudeTransform(runners.map(el => el.transforms), this._baseTransform)
+ return reduceTransform(transforms, this._baseTransform)
}
})
// 4. Now you get the delta matrix as a result: D = F * inv(M)
transform: function (transforms, relative, affine) {
- affine = transforms.affine || affine || !!transforms.a
- relative = transforms.relative || relative || false
+ var isMatrix = transforms.a != null
+ affine = transforms.affine || affine || !isMatrix
+ relative = transforms.relative || relative
var morpher
// the following cases are covered here:
// - true, false with ObjectBag
// - true, true with ObjectBag
- if(relative && transforms.a == null) {
+ if(relative && !isMatrix) {
morpher = new SVG.Morphable.ObjectBag(formatTransforms({}))
.to(formatTransforms(transforms))
.stepper(this._stepper)
// - false, false with SVG.Matrix
// 1. define the final state (T) and decompose it (once) t = [tx, ty, the, lam, sy, sx]
- morpher = (transforms.a && !affine)
+ morpher = (isMatrix && !affine)
? new SVG.Matrix().to(transforms)
: new SVG.Morphable.TransformBag().to(transforms)