summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorwout <wout@impinc.co.uk>2014-07-30 11:04:56 +0200
committerwout <wout@impinc.co.uk>2014-07-30 11:04:56 +0200
commit725828a6fc3ad423b4bd61710fe541d9b5feb3a1 (patch)
tree43bcdc2d3e6658e6f6f5b70de3dd71f5bcec35fe /src
parent411a621d7ac1b84c684d59b99bd4979f28805a64 (diff)
downloadsvg.js-725828a6fc3ad423b4bd61710fe541d9b5feb3a1.tar.gz
svg.js-725828a6fc3ad423b4bd61710fe541d9b5feb3a1.zip
Added reverse functionality for animation loops
Diffstat (limited to 'src')
-rwxr-xr-xsrc/fx.js174
-rwxr-xr-xsrc/parent.js4
-rwxr-xr-xsrc/set.js30
3 files changed, 107 insertions, 101 deletions
diff --git a/src/fx.js b/src/fx.js
index ddbbcd0..a2903fe 100755
--- a/src/fx.js
+++ b/src/fx.js
@@ -38,31 +38,32 @@ SVG.FX = SVG.invent({
akeys.push(key)
// make sure morphable elements are scaled, translated and morphed all together
- if (element.morphArray && (fx._plot || akeys.indexOf('points') > -1)) {
+ if (element.morphArray && (fx.destination.plot || akeys.indexOf('points') > -1)) {
// get destination
var box
- , p = new element.morphArray(fx._plot || fx.attrs.points || element.array)
+ , p = new element.morphArray(fx.destination.plot || fx.attrs.points || element.array)
// add size
- if (fx._size) p.size(fx._size.width.to, fx._size.height.to)
+ if (fx.destination.size)
+ p.size(fx.destination.size.width.to, fx.destination.size.height.to)
// add movement
box = p.bbox()
- if (fx._x) p.move(fx._x.to, box.y)
- else if (fx._cx) p.move(fx._cx.to - box.width / 2, box.y)
+ if (fx.destination.x)
+ p.move(fx.destination.x.to, box.y)
+ else if (fx.destination.cx)
+ p.move(fx.destination.cx.to - box.width / 2, box.y)
box = p.bbox()
- if (fx._y) p.move(box.x, fx._y.to)
- else if (fx._cy) p.move(box.x, fx._cy.to - box.height / 2)
-
- // delete element oriented changes
- delete fx._x
- delete fx._y
- delete fx._cx
- delete fx._cy
- delete fx._size
-
- fx._plot = element.array.morph(p)
+ if (fx.destination.y)
+ p.move(box.x, fx.destination.y.to)
+ else if (fx.destination.cy)
+ p.move(box.x, fx.destination.cy.to - box.height / 2)
+
+ // reset destination values
+ fx.destination = {
+ plot: element.array.morph(p)
+ }
}
}
@@ -87,39 +88,39 @@ SVG.FX = SVG.invent({
pos
// run plot function
- if (fx._plot) {
- element.plot(fx._plot.at(pos))
+ if (fx.destination.plot) {
+ element.plot(fx.destination.plot.at(pos))
} else {
// run all x-position properties
- if (fx._x)
- element.x(fx._x.at(pos))
- else if (fx._cx)
- element.cx(fx._cx.at(pos))
+ if (fx.destination.x)
+ element.x(fx.destination.x.at(pos))
+ else if (fx.destination.cx)
+ element.cx(fx.destination.cx.at(pos))
// run all y-position properties
- if (fx._y)
- element.y(fx._y.at(pos))
- else if (fx._cy)
- element.cy(fx._cy.at(pos))
+ if (fx.destination.y)
+ element.y(fx.destination.y.at(pos))
+ else if (fx.destination.cy)
+ element.cy(fx.destination.cy.at(pos))
// run all size properties
- if (fx._size)
- element.size(fx._size.width.at(pos), fx._size.height.at(pos))
+ if (fx.destination.size)
+ element.size(fx.destination.size.width.at(pos), fx.destination.size.height.at(pos))
}
// run all viewbox properties
- if (fx._viewbox)
+ if (fx.destination.viewbox)
element.viewbox(
- fx._viewbox.x.at(pos)
- , fx._viewbox.y.at(pos)
- , fx._viewbox.width.at(pos)
- , fx._viewbox.height.at(pos)
+ fx.destination.viewbox.x.at(pos)
+ , fx.destination.viewbox.y.at(pos)
+ , fx.destination.viewbox.width.at(pos)
+ , fx.destination.viewbox.height.at(pos)
)
// run leading property
- if (fx._leading)
- element.leading(fx._leading.at(pos))
+ if (fx.destination.leading)
+ element.leading(fx.destination.leading.at(pos))
// animate attributes
for (i = akeys.length - 1; i >= 0; i--)
@@ -130,8 +131,8 @@ SVG.FX = SVG.invent({
element.style(skeys[i], at(fx.styles[skeys[i]], pos))
// callback for each keyframe
- if (fx._during)
- fx._during.call(element, pos, function(from, to) {
+ if (fx.situation.during)
+ fx.situation.during.call(element, pos, function(from, to) {
return at({ from: from, to: to }, pos)
})
}
@@ -142,13 +143,11 @@ SVG.FX = SVG.invent({
var start = new Date().getTime()
// initialize situation object
- fx.situation = {
- interval: 1000 / 60
- , start: start
- , play: true
- , finish: start + d
- , duration: d
- }
+ fx.situation.start = start
+ fx.situation.play = true
+ fx.situation.finish = start + d
+ fx.situation.duration = d
+ fx.situation.ease = ease
// render function
fx.render = function() {
@@ -157,21 +156,37 @@ SVG.FX = SVG.invent({
// calculate pos
var time = new Date().getTime()
, pos = time > fx.situation.finish ? 1 : (time - fx.situation.start) / d
+
+ // reverse pos if animation is reversed
+ if (fx.situation.reversing)
+ pos = -pos + 1
// process values
fx.at(pos)
// finish off animation
if (time > fx.situation.finish) {
- if (fx._plot)
- element.plot(new SVG.PointArray(fx._plot.destination).settle())
-
- if (fx._loop === true || (typeof fx._loop == 'number' && fx._loop > 1)) {
- if (typeof fx._loop == 'number')
- --fx._loop
+ if (fx.destination.plot)
+ element.plot(new SVG.PointArray(fx.destination.plot.destination).settle())
+
+ if (fx.situation.loop === true || (typeof fx.situation.loop == 'number' && fx.situation.loop > 0)) {
+ // register reverse
+ if (fx.situation.reverse)
+ fx.situation.reversing = !fx.situation.reversing
+
+ if (typeof fx.situation.loop == 'number') {
+ // reduce loop count
+ if (!fx.situation.reverse || fx.situation.reversing)
+ --fx.situation.loop
+
+ // remove last loop if reverse is disabled
+ if (!fx.situation.reverse && fx.situation.loop == 1)
+ --fx.situation.loop
+ }
+
fx.animate(d, ease, delay)
} else {
- fx._after ? fx._after.apply(element, [fx]) : fx.stop()
+ fx.situation.after ? fx.situation.after.apply(element, [fx]) : fx.stop()
}
} else {
@@ -231,25 +246,25 @@ SVG.FX = SVG.invent({
}
// Animatable x-axis
, x: function(x) {
- this._x = new SVG.Number(this.target.x()).morph(x)
+ this.destination.x = new SVG.Number(this.target.x()).morph(x)
return this
}
// Animatable y-axis
, y: function(y) {
- this._y = new SVG.Number(this.target.y()).morph(y)
+ this.destination.y = new SVG.Number(this.target.y()).morph(y)
return this
}
// Animatable center x-axis
, cx: function(x) {
- this._cx = new SVG.Number(this.target.cx()).morph(x)
+ this.destination.cx = new SVG.Number(this.target.cx()).morph(x)
return this
}
// Animatable center y-axis
, cy: function(y) {
- this._cy = new SVG.Number(this.target.cy()).morph(y)
+ this.destination.cy = new SVG.Number(this.target.cy()).morph(y)
return this
}
@@ -271,7 +286,7 @@ SVG.FX = SVG.invent({
// animate bbox based size for all other elements
var box = this.target.bbox()
- this._size = {
+ this.destination.size = {
width: new SVG.Number(box.width).morph(width)
, height: new SVG.Number(box.height).morph(height)
}
@@ -281,14 +296,14 @@ SVG.FX = SVG.invent({
}
// Add animatable plot
, plot: function(p) {
- this._plot = p
+ this.destination.plot = p
return this
}
// Add leading method
, leading: function(value) {
- if (this.target._leading)
- this._leading = new SVG.Number(this.target._leading).morph(value)
+ if (this.target.destination.leading)
+ this.destination.leading = new SVG.Number(this.target.destination.leading).morph(value)
return this
}
@@ -297,7 +312,7 @@ SVG.FX = SVG.invent({
if (this.target instanceof SVG.Container) {
var box = this.target.viewbox()
- this._viewbox = {
+ this.destination.viewbox = {
x: new SVG.Number(box.x).morph(x)
, y: new SVG.Number(box.y).morph(y)
, width: new SVG.Number(box.width).morph(width)
@@ -319,19 +334,23 @@ SVG.FX = SVG.invent({
}
// Add callback for each keyframe
, during: function(during) {
- this._during = during
+ this.situation.during = during
return this
}
// Callback after animation
, after: function(after) {
- this._after = after
+ this.situation.after = after
return this
}
// Make loopable
- , loop: function(times) {
- this._loop = times || true
+ , loop: function(times, reverse) {
+ // store current loop and total loops
+ this.situation.loop = this.situation.loops = times || true
+
+ // make reversable
+ this.situation.reverse = !!reverse
return this
}
@@ -342,31 +361,18 @@ SVG.FX = SVG.invent({
this.animate(0)
- if (this._after)
- this._after.apply(this.target, [this])
+ if (this.situation.after)
+ this.situation.after.apply(this.target, [this])
} else {
// stop current animation
clearTimeout(this.timeout)
- // reset storage for properties that need animation
- this.attrs = {}
- this.trans = {}
- this.styles = {}
- this.situation = {}
-
- // delete destinations
- delete this._x
- delete this._y
- delete this._cx
- delete this._cy
- delete this._size
- delete this._plot
- delete this._loop
- delete this._after
- delete this._during
- delete this._leading
- delete this._viewbox
+ // reset storage for properties
+ this.attrs = {}
+ this.styles = {}
+ this.situation = {}
+ this.destination = {}
}
return this
diff --git a/src/parent.js b/src/parent.js
index bde35da..1954259 100755
--- a/src/parent.js
+++ b/src/parent.js
@@ -18,10 +18,10 @@ SVG.Parent = SVG.invent({
// Add given element at a position
, add: function(element, i) {
if (!this.has(element)) {
- // Define insertion index if none given
+ // define insertion index if none given
i = i == null ? this.children().length : i
- // Add element references
+ // add element references
this.node.insertBefore(element.node, this.node.childNodes[i] || null)
}
diff --git a/src/set.js b/src/set.js
index a4690bf..8c055cf 100755
--- a/src/set.js
+++ b/src/set.js
@@ -20,7 +20,7 @@ SVG.Set = SVG.invent({
, remove: function(element) {
var i = this.index(element)
- /* remove given child */
+ // remove given child
if (i > -1)
this.members.splice(i, 1)
@@ -35,7 +35,7 @@ SVG.Set = SVG.invent({
}
// Restore to defaults
, clear: function() {
- /* initialize store */
+ // initialize store
this.members = []
return this
@@ -68,11 +68,11 @@ SVG.Set = SVG.invent({
, bbox: function(){
var box = new SVG.BBox()
- /* return an empty box of there are no members */
+ // return an empty box of there are no members
if (this.members.length == 0)
return box
- /* get the first rbox and update the target bbox */
+ // get the first rbox and update the target bbox
var rbox = this.members[0].rbox()
box.x = rbox.x
box.y = rbox.y
@@ -80,7 +80,7 @@ SVG.Set = SVG.invent({
box.height = rbox.height
this.each(function() {
- /* user rbox for correct position and visual representation */
+ // user rbox for correct position and visual representation
box = box.merge(this.rbox())
})
@@ -97,10 +97,10 @@ SVG.Set = SVG.invent({
}
})
-SVG.SetFX = SVG.invent({
+SVG.FX.Set = SVG.invent({
// Initialize node
create: function(set) {
- /* store reference to set */
+ // store reference to set
this.set = set
}
@@ -111,33 +111,33 @@ SVG.Set.inherit = function() {
var m
, methods = []
- /* gather shape methods */
+ // gather shape methods
for(var m in SVG.Shape.prototype)
if (typeof SVG.Shape.prototype[m] == 'function' && typeof SVG.Set.prototype[m] != 'function')
methods.push(m)
- /* apply shape aliasses */
+ // apply shape aliasses
methods.forEach(function(method) {
SVG.Set.prototype[method] = function() {
for (var i = 0, il = this.members.length; i < il; i++)
if (this.members[i] && typeof this.members[i][method] == 'function')
this.members[i][method].apply(this.members[i], arguments)
- return method == 'animate' ? (this.fx || (this.fx = new SVG.SetFX(this))) : this
+ return method == 'animate' ? (this.fx || (this.fx = new SVG.FX.Set(this))) : this
}
})
- /* clear methods for the next round */
+ // clear methods for the next round
methods = []
- /* gather fx methods */
+ // gather fx methods
for(var m in SVG.FX.prototype)
- if (typeof SVG.FX.prototype[m] == 'function' && typeof SVG.SetFX.prototype[m] != 'function')
+ if (typeof SVG.FX.prototype[m] == 'function' && typeof SVG.FX.Set.prototype[m] != 'function')
methods.push(m)
- /* apply fx aliasses */
+ // apply fx aliasses
methods.forEach(function(method) {
- SVG.SetFX.prototype[method] = function() {
+ SVG.FX.Set.prototype[method] = function() {
for (var i = 0, il = this.set.members.length; i < il; i++)
this.set.members[i].fx[method].apply(this.set.members[i].fx, arguments)