aboutsummaryrefslogtreecommitdiffstats
path: root/src/animation
diff options
context:
space:
mode:
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2023-06-13 01:43:37 +0200
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2023-06-13 01:43:37 +0200
commit03322672782a6318b019eff33fe44ec800d6f12c (patch)
tree9d807e1585cf28a1ea98e87b855932dba00f1880 /src/animation
parent8e18b4698edd00f83af0be05bb3374f92fecaeb9 (diff)
downloadsvg.js-03322672782a6318b019eff33fe44ec800d6f12c.tar.gz
svg.js-03322672782a6318b019eff33fe44ec800d6f12c.zip
dependency updates, easier formatting
Diffstat (limited to 'src/animation')
-rw-r--r--src/animation/Animator.js23
-rw-r--r--src/animation/Controller.js44
-rw-r--r--src/animation/Morphable.js117
-rw-r--r--src/animation/Queue.js18
-rw-r--r--src/animation/Runner.js426
-rw-r--r--src/animation/Timeline.js61
6 files changed, 367 insertions, 322 deletions
diff --git a/src/animation/Animator.js b/src/animation/Animator.js
index fc3df10..11cca54 100644
--- a/src/animation/Animator.js
+++ b/src/animation/Animator.js
@@ -9,7 +9,7 @@ const Animator = {
timer: () => globals.window.performance || globals.window.Date,
transforms: [],
- frame (fn) {
+ frame(fn) {
// Store the node
const node = Animator.frames.push({ run: fn })
@@ -22,7 +22,7 @@ const Animator = {
return node
},
- timeout (fn, delay) {
+ timeout(fn, delay) {
delay = delay || 0
// Work out when the event should fire
@@ -39,7 +39,7 @@ const Animator = {
return node
},
- immediate (fn) {
+ immediate(fn) {
// Add the immediate fn to the end of the queue
const node = Animator.immediates.push(fn)
// Request another animation frame if we need one
@@ -50,19 +50,19 @@ const Animator = {
return node
},
- cancelFrame (node) {
+ cancelFrame(node) {
node != null && Animator.frames.remove(node)
},
- clearTimeout (node) {
+ clearTimeout(node) {
node != null && Animator.timeouts.remove(node)
},
- cancelImmediate (node) {
+ cancelImmediate(node) {
node != null && Animator.immediates.remove(node)
},
- _draw (now) {
+ _draw(now) {
// Run all the timeouts we can run, if they are not ready yet, add them
// to the end of the queue immediately! (bad timeouts!!! [sarcasm])
let nextTimeout = null
@@ -82,7 +82,7 @@ const Animator = {
// Run all of the animation frames
let nextFrame = null
const lastFrame = Animator.frames.last()
- while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) {
+ while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) {
nextFrame.run(now)
}
@@ -92,9 +92,10 @@ const Animator = {
}
// If we have remaining timeouts or frames, draw until we don't anymore
- Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first()
- ? globals.window.requestAnimationFrame(Animator._draw)
- : null
+ Animator.nextDraw =
+ Animator.timeouts.first() || Animator.frames.first()
+ ? globals.window.requestAnimationFrame(Animator._draw)
+ : null
}
}
diff --git a/src/animation/Controller.js b/src/animation/Controller.js
index 303fb71..1cf879d 100644
--- a/src/animation/Controller.js
+++ b/src/animation/Controller.js
@@ -7,7 +7,7 @@ Base Class
The base stepper class that will be
***/
-function makeSetterGetter (k, f) {
+function makeSetterGetter(k, f) {
return function (v) {
if (v == null) return this[k]
this[k] = v
@@ -24,27 +24,27 @@ export const easing = {
return -Math.cos(pos * Math.PI) / 2 + 0.5
},
'>': function (pos) {
- return Math.sin(pos * Math.PI / 2)
+ return Math.sin((pos * Math.PI) / 2)
},
'<': function (pos) {
- return -Math.cos(pos * Math.PI / 2) + 1
+ return -Math.cos((pos * Math.PI) / 2) + 1
},
bezier: function (x1, y1, x2, y2) {
// see https://www.w3.org/TR/css-easing-1/#cubic-bezier-algo
return function (t) {
if (t < 0) {
if (x1 > 0) {
- return y1 / x1 * t
+ return (y1 / x1) * t
} else if (x2 > 0) {
- return y2 / x2 * t
+ return (y2 / x2) * t
} else {
return 0
}
} else if (t > 1) {
if (x2 < 1) {
- return (1 - y2) / (1 - x2) * t + (y2 - x2) / (1 - x2)
+ return ((1 - y2) / (1 - x2)) * t + (y2 - x2) / (1 - x2)
} else if (x1 < 1) {
- return (1 - y1) / (1 - x1) * t + (y1 - x1) / (1 - x1)
+ return ((1 - y1) / (1 - x1)) * t + (y1 - x1) / (1 - x1)
} else {
return 1
}
@@ -93,7 +93,7 @@ export const easing = {
}
export class Stepper {
- done () {
+ done() {
return false
}
}
@@ -104,12 +104,12 @@ Easing Functions
***/
export class Ease extends Stepper {
- constructor (fn = timeline.ease) {
+ constructor(fn = timeline.ease) {
super()
this.ease = easing[fn] || fn
}
- step (from, to, pos) {
+ step(from, to, pos) {
if (typeof from !== 'number') {
return pos < 1 ? from : to
}
@@ -123,22 +123,21 @@ Controller Types
***/
export class Controller extends Stepper {
- constructor (fn) {
+ constructor(fn) {
super()
this.stepper = fn
}
- done (c) {
+ done(c) {
return c.done
}
- step (current, target, dt, c) {
+ step(current, target, dt, c) {
return this.stepper(current, target, dt, c)
}
-
}
-function recalculate () {
+function recalculate() {
// Apply the default parameters
const duration = (this._duration || 500) / 1000
const overshoot = this._overshoot || 0
@@ -156,13 +155,12 @@ function recalculate () {
}
export class Spring extends Controller {
- constructor (duration = 500, overshoot = 0) {
+ constructor(duration = 500, overshoot = 0) {
super()
- this.duration(duration)
- .overshoot(overshoot)
+ this.duration(duration).overshoot(overshoot)
}
- step (current, target, dt, c) {
+ step(current, target, dt, c) {
if (typeof current === 'string') return current
c.done = dt === Infinity
if (dt === Infinity) return target
@@ -177,9 +175,7 @@ export class Spring extends Controller {
// Apply the control to get the new position and store it
const acceleration = -this.d * velocity - this.k * (current - target)
- const newPosition = current
- + velocity * dt
- + acceleration * dt * dt / 2
+ const newPosition = current + velocity * dt + (acceleration * dt * dt) / 2
// Store the velocity
c.velocity = velocity + acceleration * dt
@@ -196,12 +192,12 @@ extend(Spring, {
})
export class PID extends Controller {
- constructor (p = 0.1, i = 0.01, d = 0, windup = 1000) {
+ constructor(p = 0.1, i = 0.01, d = 0, windup = 1000) {
super()
this.p(p).i(i).d(d).windup(windup)
}
- step (current, target, dt, c) {
+ step(current, target, dt, c) {
if (typeof current === 'string') return current
c.done = dt === Infinity
diff --git a/src/animation/Morphable.js b/src/animation/Morphable.js
index e9b3ff8..240ca7b 100644
--- a/src/animation/Morphable.js
+++ b/src/animation/Morphable.js
@@ -19,9 +19,7 @@ const getClassForType = (value) => {
if (Color.isColor(value)) {
return Color
} else if (delimiter.test(value)) {
- return isPathLetter.test(value)
- ? PathArray
- : SVGArray
+ return isPathLetter.test(value) ? PathArray : SVGArray
} else if (numberAndUnit.test(value)) {
return SVGNumber
} else {
@@ -39,7 +37,7 @@ const getClassForType = (value) => {
}
export default class Morphable {
- constructor (stepper) {
+ constructor(stepper) {
this._stepper = stepper || new Ease('-')
this._from = null
@@ -49,12 +47,17 @@ export default class Morphable {
this._morphObj = null
}
- at (pos) {
- return this._morphObj.morph(this._from, this._to, pos, this._stepper, this._context)
-
+ at(pos) {
+ return this._morphObj.morph(
+ this._from,
+ this._to,
+ pos,
+ this._stepper,
+ this._context
+ )
}
- done () {
+ done() {
const complete = this._context
.map(this._stepper.done)
.reduce(function (last, curr) {
@@ -63,7 +66,7 @@ export default class Morphable {
return complete
}
- from (val) {
+ from(val) {
if (val == null) {
return this._from
}
@@ -72,13 +75,13 @@ export default class Morphable {
return this
}
- stepper (stepper) {
+ stepper(stepper) {
if (stepper == null) return this._stepper
this._stepper = stepper
return this
}
- to (val) {
+ to(val) {
if (val == null) {
return this._to
}
@@ -87,7 +90,7 @@ export default class Morphable {
return this
}
- type (type) {
+ type(type) {
// getter
if (type == null) {
return this._type
@@ -98,33 +101,34 @@ export default class Morphable {
return this
}
- _set (value) {
+ _set(value) {
if (!this._type) {
this.type(getClassForType(value))
}
- let result = (new this._type(value))
+ let result = new this._type(value)
if (this._type === Color) {
result = this._to
? result[this._to[4]]()
: this._from
- ? result[this._from[4]]()
- : result
+ ? result[this._from[4]]()
+ : result
}
if (this._type === ObjectBag) {
result = this._to
? result.align(this._to)
: this._from
- ? result.align(this._from)
- : result
+ ? result.align(this._from)
+ : result
}
result = result.toConsumable()
this._morphObj = this._morphObj || new this._type()
- this._context = this._context
- || Array.apply(null, Array(result.length))
+ this._context =
+ this._context ||
+ Array.apply(null, Array(result.length))
.map(Object)
.map(function (o) {
o.done = true
@@ -132,36 +136,34 @@ export default class Morphable {
})
return result
}
-
}
export class NonMorphable {
- constructor (...args) {
+ constructor(...args) {
this.init(...args)
}
- init (val) {
+ init(val) {
val = Array.isArray(val) ? val[0] : val
this.value = val
return this
}
- toArray () {
- return [ this.value ]
+ toArray() {
+ return [this.value]
}
- valueOf () {
+ valueOf() {
return this.value
}
-
}
export class TransformBag {
- constructor (...args) {
+ constructor(...args) {
this.init(...args)
}
- init (obj) {
+ init(obj) {
if (Array.isArray(obj)) {
obj = {
scaleX: obj[0],
@@ -179,7 +181,7 @@ export class TransformBag {
return this
}
- toArray () {
+ toArray() {
const v = this
return [
@@ -207,23 +209,24 @@ TransformBag.defaults = {
}
const sortByKey = (a, b) => {
- return (a[0] < b[0] ? -1 : (a[0] > b[0] ? 1 : 0))
+ return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0
}
export class ObjectBag {
- constructor (...args) {
+ constructor(...args) {
this.init(...args)
}
- align (other) {
+ align(other) {
const values = this.values
for (let i = 0, il = values.length; i < il; ++i) {
-
// If the type is the same we only need to check if the color is in the correct format
if (values[i + 1] === other[i + 1]) {
if (values[i + 1] === Color && other[i + 7] !== values[i + 7]) {
const space = other[i + 7]
- const color = new Color(this.values.splice(i + 3, 5))[space]().toArray()
+ const color = new Color(this.values.splice(i + 3, 5))
+ [space]()
+ .toArray()
this.values.splice(i + 3, 0, ...color)
}
@@ -237,19 +240,26 @@ export class ObjectBag {
// The types differ, so we overwrite the new type with the old one
// And initialize it with the types default (e.g. black for color or 0 for number)
- const defaultObject = new (other[i + 1])().toArray()
+ const defaultObject = new other[i + 1]().toArray()
// Than we fix the values array
- const toDelete = (values[i + 2]) + 3
+ const toDelete = values[i + 2] + 3
- values.splice(i, toDelete, other[i], other[i + 1], other[i + 2], ...defaultObject)
+ values.splice(
+ i,
+ toDelete,
+ other[i],
+ other[i + 1],
+ other[i + 2],
+ ...defaultObject
+ )
i += values[i + 2] + 2
}
return this
}
- init (objOrArr) {
+ init(objOrArr) {
this.values = []
if (Array.isArray(objOrArr)) {
@@ -263,7 +273,7 @@ export class ObjectBag {
for (const i in objOrArr) {
const Type = getClassForType(objOrArr[i])
const val = new Type(objOrArr[i]).toArray()
- entries.push([ i, Type, val.length, ...val ])
+ entries.push([i, Type, val.length, ...val])
}
entries.sort(sortByKey)
@@ -272,11 +282,11 @@ export class ObjectBag {
return this
}
- toArray () {
+ toArray() {
return this.values
}
- valueOf () {
+ valueOf() {
const obj = {}
const arr = this.values
@@ -286,40 +296,35 @@ export class ObjectBag {
const Type = arr.shift()
const num = arr.shift()
const values = arr.splice(0, num)
- obj[key] = new Type(values)// .valueOf()
+ obj[key] = new Type(values) // .valueOf()
}
return obj
}
-
}
-const morphableTypes = [
- NonMorphable,
- TransformBag,
- ObjectBag
-]
+const morphableTypes = [NonMorphable, TransformBag, ObjectBag]
-export function registerMorphableType (type = []) {
+export function registerMorphableType(type = []) {
morphableTypes.push(...[].concat(type))
}
-export function makeMorphable () {
+export function makeMorphable() {
extend(morphableTypes, {
- to (val) {
+ to(val) {
return new Morphable()
.type(this.constructor)
- .from(this.toArray())// this.valueOf())
+ .from(this.toArray()) // this.valueOf())
.to(val)
},
- fromArray (arr) {
+ fromArray(arr) {
this.init(arr)
return this
},
- toConsumable () {
+ toConsumable() {
return this.toArray()
},
- morph (from, to, pos, stepper, context) {
+ morph(from, to, pos, stepper, context) {
const mapper = function (i, index) {
return stepper.step(i, to[index], pos, context[index], context)
}
diff --git a/src/animation/Queue.js b/src/animation/Queue.js
index ba484dc..65108f3 100644
--- a/src/animation/Queue.js
+++ b/src/animation/Queue.js
@@ -1,22 +1,25 @@
export default class Queue {
- constructor () {
+ constructor() {
this._first = null
this._last = null
}
// Shows us the first item in the list
- first () {
+ first() {
return this._first && this._first.value
}
// Shows us the last item in the list
- last () {
+ last() {
return this._last && this._last.value
}
- push (value) {
+ push(value) {
// An item stores an id and the provided value
- const item = typeof value.next !== 'undefined' ? value : { value: value, next: null, prev: null }
+ const item =
+ typeof value.next !== 'undefined'
+ ? value
+ : { value: value, next: null, prev: null }
// Deal with the queue being empty or populated
if (this._last) {
@@ -33,7 +36,7 @@ export default class Queue {
}
// Removes the item that was returned from the push
- remove (item) {
+ remove(item) {
// Relink the previous item
if (item.prev) item.prev.next = item.next
if (item.next) item.next.prev = item.prev
@@ -45,7 +48,7 @@ export default class Queue {
item.next = null
}
- shift () {
+ shift() {
// Check if we have a value
const remove = this._first
if (!remove) return null
@@ -56,5 +59,4 @@ export default class Queue {
this._last = this._first ? this._last : null
return remove.value
}
-
}
diff --git a/src/animation/Runner.js b/src/animation/Runner.js
index 9d50042..a83a02f 100644
--- a/src/animation/Runner.js
+++ b/src/animation/Runner.js
@@ -15,21 +15,17 @@ import SVGNumber from '../types/SVGNumber.js'
import Timeline from './Timeline.js'
export default class Runner extends EventTarget {
- constructor (options) {
+ constructor(options) {
super()
// Store a unique id on the runner, so that we can identify it later
this.id = Runner.id++
// Ensure a default value
- options = options == null
- ? timeline.duration
- : options
+ options = options == null ? timeline.duration : options
// Ensure that we get a controller
- options = typeof options === 'function'
- ? new Controller(options)
- : options
+ options = typeof options === 'function' ? new Controller(options) : options
// Declare all of the variables
this._element = null
@@ -71,7 +67,7 @@ export default class Runner extends EventTarget {
this._persist = this._isDeclarative ? true : null
}
- static sanitise (duration, delay, when) {
+ static sanitise(duration, delay, when) {
// Initialise the default parameters
let times = 1
let swing = false
@@ -100,7 +96,7 @@ export default class Runner extends EventTarget {
}
}
- active (enabled) {
+ active(enabled) {
if (enabled == null) return this.enabled
this.enabled = enabled
return this
@@ -111,16 +107,16 @@ export default class Runner extends EventTarget {
===============
Methods that shouldn't be used externally
*/
- addTransform (transform, index) {
+ addTransform(transform) {
this.transforms.lmultiplyO(transform)
return this
}
- after (fn) {
+ after(fn) {
return this.on('finished', fn)
}
- animate (duration, delay, when) {
+ animate(duration, delay, when) {
const o = Runner.sanitise(duration, delay, when)
const runner = new Runner(o.duration)
if (this._timeline) runner.timeline(this._timeline)
@@ -128,33 +124,37 @@ export default class Runner extends EventTarget {
return runner.loop(o).schedule(o.delay, o.when)
}
- clearTransform () {
+ clearTransform() {
this.transforms = new Matrix()
return this
}
// TODO: Keep track of all transformations so that deletion is faster
- clearTransformsFromQueue () {
- if (!this.done || !this._timeline || !this._timeline._runnerIds.includes(this.id)) {
+ clearTransformsFromQueue() {
+ if (
+ !this.done ||
+ !this._timeline ||
+ !this._timeline._runnerIds.includes(this.id)
+ ) {
this._queue = this._queue.filter((item) => {
return !item.isTransform
})
}
}
- delay (delay) {
+ delay(delay) {
return this.animate(0, delay)
}
- duration () {
+ duration() {
return this._times * (this._wait + this._duration) - this._wait
}
- during (fn) {
+ during(fn) {
return this.queue(null, fn)
}
- ease (fn) {
+ ease(fn) {
this._stepper = new Ease(fn)
return this
}
@@ -165,18 +165,18 @@ export default class Runner extends EventTarget {
help us make new runners from the current runner
*/
- element (element) {
+ element(element) {
if (element == null) return this._element
this._element = element
element._prepareRunner()
return this
}
- finish () {
+ finish() {
return this.step(Infinity)
}
- loop (times, swing, wait) {
+ loop(times, swing, wait) {
// Deal with the user passing in an object
if (typeof times === 'object') {
swing = times.swing
@@ -190,16 +190,18 @@ export default class Runner extends EventTarget {
this._wait = wait || 0
// Allow true to be passed
- if (this._times === true) { this._times = Infinity }
+ if (this._times === true) {
+ this._times = Infinity
+ }
return this
}
- loops (p) {
+ loops(p) {
const loopDuration = this._duration + this._wait
if (p == null) {
const loopsDone = Math.floor(this._time / loopDuration)
- const relativeTime = (this._time - loopsDone * loopDuration)
+ const relativeTime = this._time - loopsDone * loopDuration
const position = relativeTime / this._duration
return Math.min(loopsDone + position, this._times)
}
@@ -209,13 +211,13 @@ export default class Runner extends EventTarget {
return this.time(time)
}
- persist (dtOrForever) {
+ persist(dtOrForever) {
if (dtOrForever == null) return this._persist
this._persist = dtOrForever
return this
}
- position (p) {
+ position(p) {
// Get all of the variables we need
const x = this._time
const d = this._duration
@@ -235,18 +237,20 @@ export default class Runner extends EventTarget {
// Figure out the value without thinking about the start or end time
const f = function (x) {
- const swinging = s * Math.floor(x % (2 * (w + d)) / (w + d))
+ const swinging = s * Math.floor((x % (2 * (w + d))) / (w + d))
const backwards = (swinging && !r) || (!swinging && r)
- const uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards
+ const uncliped =
+ (Math.pow(-1, backwards) * (x % (w + d))) / d + backwards
const clipped = Math.max(Math.min(uncliped, 1), 0)
return clipped
}
// Figure out the value by incorporating the start time
const endTime = t * (w + d) - w
- position = x <= 0
- ? Math.round(f(1e-5))
- : x < endTime
+ position =
+ x <= 0
+ ? Math.round(f(1e-5))
+ : x < endTime
? f(x)
: Math.round(f(endTime - 1e-5))
return position
@@ -254,13 +258,13 @@ export default class Runner extends EventTarget {
// Work out the loops done and add the position to the loops done
const loopsDone = Math.floor(this.loops())
- const swingForward = s && (loopsDone % 2 === 0)
+ const swingForward = s && loopsDone % 2 === 0
const forwards = (swingForward && !r) || (r && swingForward)
position = loopsDone + (forwards ? p : 1 - p)
return this.loops(position)
}
- progress (p) {
+ progress(p) {
if (p == null) {
return Math.min(1, this._time / this.duration())
}
@@ -272,7 +276,7 @@ export default class Runner extends EventTarget {
===================
These methods allow us to attach basic functions to the runner directly
*/
- queue (initFn, runFn, retargetFn, isTransform) {
+ queue(initFn, runFn, retargetFn, isTransform) {
this._queue.push({
initialiser: initFn || noop,
runner: runFn || noop,
@@ -286,19 +290,19 @@ export default class Runner extends EventTarget {
return this
}
- reset () {
+ reset() {
if (this._reseted) return this
this.time(0)
this._reseted = true
return this
}
- reverse (reverse) {
+ reverse(reverse) {
this._reverse = reverse == null ? !this._reverse : reverse
return this
}
- schedule (timeline, delay, when) {
+ schedule(timeline, delay, when) {
// The user doesn't need to pass a timeline if we already have one
if (!(timeline instanceof Timeline)) {
when = delay
@@ -316,7 +320,7 @@ export default class Runner extends EventTarget {
return this
}
- step (dt) {
+ step(dt) {
// If we are inactive, this stepper just gets skipped
if (!this.enabled) return this
@@ -373,7 +377,7 @@ export default class Runner extends EventTarget {
========================
Control how the animation plays
*/
- time (time) {
+ time(time) {
if (time == null) {
return this._time
}
@@ -382,21 +386,21 @@ export default class Runner extends EventTarget {
return this
}
- timeline (timeline) {
+ timeline(timeline) {
// check explicitly for undefined so we can set the timeline to null
if (typeof timeline === 'undefined') return this._timeline
this._timeline = timeline
return this
}
- unschedule () {
+ unschedule() {
const timeline = this.timeline()
timeline && timeline.unschedule(this)
return this
}
// Run each initialise function in the runner if required
- _initialise (running) {
+ _initialise(running) {
// If we aren't running, we shouldn't initialise when not declarative
if (!running && !this._isDeclarative) return
@@ -418,7 +422,7 @@ export default class Runner extends EventTarget {
}
// Save a morpher to the morpher list so that we can retarget it later
- _rememberMorpher (method, morpher) {
+ _rememberMorpher(method, morpher) {
this._history[method] = {
morpher: morpher,
caller: this._queue[this._queue.length - 1]
@@ -438,7 +442,7 @@ export default class Runner extends EventTarget {
// Try to set the target for a morpher if the morpher exists, otherwise
// Run each run function for the position or dt given
- _run (positionOrDt) {
+ _run(positionOrDt) {
// Run all of the _queue directly
let allfinished = true
for (let i = 0, len = this._queue.length; i < len; ++i) {
@@ -448,7 +452,7 @@ export default class Runner extends EventTarget {
// Run the function if its not finished, we keep track of the finished
// flag for the sake of declarative _queue
const converged = current.runner.call(this, positionOrDt)
- current.finished = current.finished || (converged === true)
+ current.finished = current.finished || converged === true
allfinished = allfinished && current.finished
}
@@ -457,7 +461,7 @@ export default class Runner extends EventTarget {
}
// do nothing and return false
- _tryRetarget (method, target, extra) {
+ _tryRetarget(method, target, extra) {
if (this._history[method]) {
// if the last method wasn't even initialised, throw it away
if (!this._history[method].caller.initialised) {
@@ -482,23 +486,22 @@ export default class Runner extends EventTarget {
}
return false
}
-
}
Runner.id = 0
export class FakeRunner {
- constructor (transforms = new Matrix(), id = -1, done = true) {
+ constructor(transforms = new Matrix(), id = -1, done = true) {
this.transforms = transforms
this.id = id
this.done = done
}
- clearTransformsFromQueue () { }
+ clearTransformsFromQueue() {}
}
-extend([ Runner, FakeRunner ], {
- mergeWith (runner) {
+extend([Runner, FakeRunner], {
+ mergeWith(runner) {
return new FakeRunner(
runner.transforms.lmultiply(this.transforms),
runner.id
@@ -511,7 +514,7 @@ extend([ Runner, FakeRunner ], {
const lmultiply = (last, curr) => last.lmultiplyO(curr)
const getRunnerTransform = (runner) => runner.transforms
-function mergeTransforms () {
+function mergeTransforms() {
// Find the matrix to apply to the element and apply it
const runners = this._transformationRunners.runners
const netTransform = runners
@@ -528,12 +531,12 @@ function mergeTransforms () {
}
export class RunnerArray {
- constructor () {
+ constructor() {
this.runners = []
this.ids = []
}
- add (runner) {
+ add(runner) {
if (this.runners.includes(runner)) return
const id = runner.id + 1
@@ -543,39 +546,44 @@ export class RunnerArray {
return this
}
- clearBefore (id) {
+ clearBefore(id) {
const deleteCnt = this.ids.indexOf(id + 1) || 1
this.ids.splice(0, deleteCnt, 0)
- this.runners.splice(0, deleteCnt, new FakeRunner())
+ this.runners
+ .splice(0, deleteCnt, new FakeRunner())
.forEach((r) => r.clearTransformsFromQueue())
return this
}
- edit (id, newRunner) {
+ edit(id, newRunner) {
const index = this.ids.indexOf(id + 1)
this.ids.splice(index, 1, id + 1)
this.runners.splice(index, 1, newRunner)
return this
}
- getByID (id) {
+ getByID(id) {
return this.runners[this.ids.indexOf(id + 1)]
}
- length () {
+ length() {
return this.ids.length
}
- merge () {
+ merge() {
let lastRunner = null
for (let i = 0; i < this.runners.length; ++i) {
const runner = this.runners[i]
- const condition = lastRunner
- && runner.done && lastRunner.done
+ const condition =
+ lastRunner &&
+ runner.done &&
+ lastRunner.done &&
// don't merge runner when persisted on timeline
- && (!runner._timeline || !runner._timeline._runnerIds.includes(runner.id))
- && (!lastRunner._timeline || !lastRunner._timeline._runnerIds.includes(lastRunner.id))
+ (!runner._timeline ||
+ !runner._timeline._runnerIds.includes(runner.id)) &&
+ (!lastRunner._timeline ||
+ !lastRunner._timeline._runnerIds.includes(lastRunner.id))
if (condition) {
// the +1 happens in the function
@@ -592,18 +600,17 @@ export class RunnerArray {
return this
}
- remove (id) {
+ remove(id) {
const index = this.ids.indexOf(id + 1)
this.ids.splice(index, 1)
this.runners.splice(index, 1)
return this
}
-
}
registerMethods({
Element: {
- animate (duration, delay, when) {
+ animate(duration, delay, when) {
const o = Runner.sanitise(duration, delay, when)
const timeline = this.timeline()
return new Runner(o.duration)
@@ -613,7 +620,7 @@ registerMethods({
.schedule(o.delay, o.when)
},
- delay (by, when) {
+ delay(by, when) {
return this.animate(0, by, when)
},
@@ -621,21 +628,23 @@ registerMethods({
// which run before the current one. This is because absolute transformations
// overwrite anything anyway so there is no need to waste time computing
// other runners
- _clearTransformRunnersBefore (currentRunner) {
+ _clearTransformRunnersBefore(currentRunner) {
this._transformationRunners.clearBefore(currentRunner.id)
},
- _currentTransform (current) {
- return this._transformationRunners.runners
- // we need the equal sign here to make sure, that also transformations
- // on the same runner which execute before the current transformation are
- // taken into account
- .filter((runner) => runner.id <= current.id)
- .map(getRunnerTransform)
- .reduce(lmultiply, new Matrix())
+ _currentTransform(current) {
+ return (
+ this._transformationRunners.runners
+ // we need the equal sign here to make sure, that also transformations
+ // on the same runner which execute before the current transformation are
+ // taken into account
+ .filter((runner) => runner.id <= current.id)
+ .map(getRunnerTransform)
+ .reduce(lmultiply, new Matrix())
+ )
},
- _addRunner (runner) {
+ _addRunner(runner) {
this._transformationRunners.add(runner)
// Make sure that the runner merge is executed at the very end of
@@ -645,29 +654,30 @@ registerMethods({
this._frameId = Animator.immediate(mergeTransforms.bind(this))
},
- _prepareRunner () {
+ _prepareRunner() {
if (this._frameId == null) {
- this._transformationRunners = new RunnerArray()
- .add(new FakeRunner(new Matrix(this)))
+ this._transformationRunners = new RunnerArray().add(
+ new FakeRunner(new Matrix(this))
+ )
}
}
}
})
// Will output the elements from array A that are not in the array B
-const difference = (a, b) => a.filter(x => !b.includes(x))
+const difference = (a, b) => a.filter((x) => !b.includes(x))
extend(Runner, {
- attr (a, v) {
+ attr(a, v) {
return this.styleAttr('attr', a, v)
},
// Add animatable styles
- css (s, v) {
+ css(s, v) {
return this.styleAttr('css', s, v)
},
- styleAttr (type, nameOrAttrs, val) {
+ styleAttr(type, nameOrAttrs, val) {
if (typeof nameOrAttrs === 'string') {
return this.styleAttr(type, { [nameOrAttrs]: val })
}
@@ -678,62 +688,69 @@ extend(Runner, {
let morpher = new Morphable(this._stepper).to(attrs)
let keys = Object.keys(attrs)
- this.queue(function () {
- morpher = morpher.from(this.element()[type](keys))
- }, function (pos) {
- this.element()[type](morpher.at(pos).valueOf())
- return morpher.done()
- }, function (newToAttrs) {
+ this.queue(
+ function () {
+ morpher = morpher.from(this.element()[type](keys))
+ },
+ function (pos) {
+ this.element()[type](morpher.at(pos).valueOf())
+ return morpher.done()
+ },
+ function (newToAttrs) {
+ // Check if any new keys were added
+ const newKeys = Object.keys(newToAttrs)
+ const differences = difference(newKeys, keys)
+
+ // If their are new keys, initialize them and add them to morpher
+ if (differences.length) {
+ // Get the values
+ const addedFromAttrs = this.element()[type](differences)
+
+ // Get the already initialized values
+ const oldFromAttrs = new ObjectBag(morpher.from()).valueOf()
+
+ // Merge old and new
+ Object.assign(oldFromAttrs, addedFromAttrs)
+ morpher.from(oldFromAttrs)
+ }
- // Check if any new keys were added
- const newKeys = Object.keys(newToAttrs)
- const differences = difference(newKeys, keys)
+ // Get the object from the morpher
+ const oldToAttrs = new ObjectBag(morpher.to()).valueOf()
- // If their are new keys, initialize them and add them to morpher
- if (differences.length) {
- // Get the values
- const addedFromAttrs = this.element()[type](differences)
+ // Merge in new attributes
+ Object.assign(oldToAttrs, newToAttrs)
- // Get the already initialized values
- const oldFromAttrs = new ObjectBag(morpher.from()).valueOf()
+ // Change morpher target
+ morpher.to(oldToAttrs)
- // Merge old and new
- Object.assign(oldFromAttrs, addedFromAttrs)
- morpher.from(oldFromAttrs)
+ // Make sure that we save the work we did so we don't need it to do again
+ keys = newKeys
+ attrs = newToAttrs
}
-
- // Get the object from the morpher
- const oldToAttrs = new ObjectBag(morpher.to()).valueOf()
-
- // Merge in new attributes
- Object.assign(oldToAttrs, newToAttrs)
-
- // Change morpher target
- morpher.to(oldToAttrs)
-
- // Make sure that we save the work we did so we don't need it to do again
- keys = newKeys
- attrs = newToAttrs
- })
+ )
this._rememberMorpher(type, morpher)
return this
},
- zoom (level, point) {
+ zoom(level, point) {
if (this._tryRetarget('zoom', level, point)) return this
let morpher = new Morphable(this._stepper).to(new SVGNumber(level))
- this.queue(function () {
- morpher = morpher.from(this.element().zoom())
- }, function (pos) {
- this.element().zoom(morpher.at(pos), point)
- return morpher.done()
- }, function (newLevel, newPoint) {
- point = newPoint
- morpher.to(newLevel)
- })
+ this.queue(
+ function () {
+ morpher = morpher.from(this.element().zoom())
+ },
+ function (pos) {
+ this.element().zoom(morpher.at(pos), point)
+ return morpher.done()
+ },
+ function (newLevel, newPoint) {
+ point = newPoint
+ morpher.to(newLevel)
+ }
+ )
this._rememberMorpher('zoom', morpher)
return this
@@ -756,22 +773,30 @@ extend(Runner, {
// - Note F(1) = T
// 4. Now you get the delta matrix as a result: D = F * inv(M)
- transform (transforms, relative, affine) {
+ transform(transforms, relative, affine) {
// If we have a declarative function, we should retarget it if possible
relative = transforms.relative || relative
- if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) {
+ if (
+ this._isDeclarative &&
+ !relative &&
+ this._tryRetarget('transform', transforms)
+ ) {
return this
}
// Parse the parameters
const isMatrix = Matrix.isMatrixLike(transforms)
- affine = transforms.affine != null
- ? transforms.affine
- : (affine != null ? affine : !isMatrix)
+ affine =
+ transforms.affine != null
+ ? transforms.affine
+ : affine != null
+ ? affine
+ : !isMatrix
// Create a morpher and set its type
- const morpher = new Morphable(this._stepper)
- .type(affine ? TransformBag : Matrix)
+ const morpher = new Morphable(this._stepper).type(
+ affine ? TransformBag : Matrix
+ )
let origin
let element
@@ -779,7 +804,7 @@ extend(Runner, {
let currentAngle
let startTransform
- function setup () {
+ function setup() {
// make sure element and origin is defined
element = element || this.element()
origin = origin || getOrigin(transforms, element)
@@ -795,17 +820,17 @@ extend(Runner, {
}
}
- function run (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!
if (!relative) this.clearTransform()
- const { x, y } = new Point(origin).transform(element._currentTransform(this))
+ const { x, y } = new Point(origin).transform(
+ element._currentTransform(this)
+ )
- let target = new Matrix({ ...transforms, origin: [ x, y ] })
- let start = this._isDeclarative && current
- ? current
- : startTransform
+ let target = new Matrix({ ...transforms, origin: [x, y] })
+ let start = this._isDeclarative && current ? current : startTransform
if (affine) {
target = target.decompose(x, y)
@@ -816,8 +841,8 @@ extend(Runner, {
const rCurrent = start.rotate
// Figure out the shortest path to rotate directly
- const possibilities = [ rTarget - 360, rTarget, rTarget + 360 ]
- const distances = possibilities.map(a => Math.abs(a - rCurrent))
+ const possibilities = [rTarget - 360, rTarget, rTarget + 360]
+ const distances = possibilities.map((a) => Math.abs(a - rCurrent))
const shortest = Math.min(...distances)
const index = distances.indexOf(shortest)
target.rotate = possibilities[index]
@@ -846,11 +871,11 @@ extend(Runner, {
return morpher.done()
}
- function retarget (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()
+ (newTransforms.origin || 'center').toString() !==
+ (transforms.origin || 'center').toString()
) {
origin = getOrigin(newTransforms, element)
}
@@ -865,28 +890,28 @@ extend(Runner, {
},
// Animatable x-axis
- x (x, relative) {
+ x(x) {
return this._queueNumber('x', x)
},
// Animatable y-axis
- y (y) {
+ y(y) {
return this._queueNumber('y', y)
},
- dx (x = 0) {
+ dx(x = 0) {
return this._queueNumberDelta('x', x)
},
- dy (y = 0) {
+ dy(y = 0) {
return this._queueNumberDelta('y', y)
},
- dmove (x, y) {
+ dmove(x, y) {
return this.dx(x).dy(y)
},
- _queueNumberDelta (method, to) {
+ _queueNumberDelta(method, to) {
to = new SVGNumber(to)
// Try to change the target if we have this method already registered
@@ -895,66 +920,73 @@ extend(Runner, {
// Make a morpher and queue the animation
const morpher = new Morphable(this._stepper).to(to)
let from = null
- this.queue(function () {
- from = this.element()[method]()
- morpher.from(from)
- morpher.to(from + to)
- }, function (pos) {
- this.element()[method](morpher.at(pos))
- return morpher.done()
- }, function (newTo) {
- morpher.to(from + new SVGNumber(newTo))
- })
+ this.queue(
+ function () {
+ from = this.element()[method]()
+ morpher.from(from)
+ morpher.to(from + to)
+ },
+ function (pos) {
+ this.element()[method](morpher.at(pos))
+ return morpher.done()
+ },
+ function (newTo) {
+ morpher.to(from + new SVGNumber(newTo))
+ }
+ )
// Register the morpher so that if it is changed again, we can retarget it
this._rememberMorpher(method, morpher)
return this
},
- _queueObject (method, to) {
+ _queueObject(method, to) {
// Try to change the target if we have this method already registered
if (this._tryRetarget(method, to)) return this
// Make a morpher and queue the animation
const morpher = new Morphable(this._stepper).to(to)
- this.queue(function () {
- morpher.from(this.element()[method]())
- }, function (pos) {
- this.element()[method](morpher.at(pos))
- return morpher.done()
- })
+ this.queue(
+ function () {
+ morpher.from(this.element()[method]())
+ },
+ function (pos) {
+ this.element()[method](morpher.at(pos))
+ return morpher.done()
+ }
+ )
// Register the morpher so that if it is changed again, we can retarget it
this._rememberMorpher(method, morpher)
return this
},
- _queueNumber (method, value) {
+ _queueNumber(method, value) {
return this._queueObject(method, new SVGNumber(value))
},
// Animatable center x-axis
- cx (x) {
+ cx(x) {
return this._queueNumber('cx', x)
},
// Animatable center y-axis
- cy (y) {
+ cy(y) {
return this._queueNumber('cy', y)
},
// Add animatable move
- move (x, y) {
+ move(x, y) {
return this.x(x).y(y)
},
// Add animatable center
- center (x, y) {
+ center(x, y) {
return this.cx(x).cy(y)
},
// Add animatable size
- size (width, height) {
+ size(width, height) {
// animate bbox based size for all other elements
let box
@@ -963,62 +995,64 @@ extend(Runner, {
}
if (!width) {
- width = box.width / box.height * height
+ width = (box.width / box.height) * height
}
if (!height) {
- height = box.height / box.width * width
+ height = (box.height / box.width) * width
}
- return this
- .width(width)
- .height(height)
+ return this.width(width).height(height)
},
// Add animatable width
- width (width) {
+ width(width) {
return this._queueNumber('width', width)
},
// Add animatable height
- height (height) {
+ height(height) {
return this._queueNumber('height', height)
},
// Add animatable plot
- plot (a, b, c, d) {
+ plot(a, b, c, d) {
// Lines can be plotted with 4 arguments
if (arguments.length === 4) {
- return this.plot([ a, b, c, d ])
+ return this.plot([a, b, c, d])
}
if (this._tryRetarget('plot', a)) return this
const morpher = new Morphable(this._stepper)
- .type(this._element.MorphArray).to(a)
-
- this.queue(function () {
- morpher.from(this._element.array())
- }, function (pos) {
- this._element.plot(morpher.at(pos))
- return morpher.done()
- })
+ .type(this._element.MorphArray)
+ .to(a)
+
+ this.queue(
+ function () {
+ morpher.from(this._element.array())
+ },
+ function (pos) {
+ this._element.plot(morpher.at(pos))
+ return morpher.done()
+ }
+ )
this._rememberMorpher('plot', morpher)
return this
},
// Add leading method
- leading (value) {
+ leading(value) {
return this._queueNumber('leading', value)
},
// Add animatable viewbox
- viewbox (x, y, width, height) {
+ viewbox(x, y, width, height) {
return this._queueObject('viewbox', new Box(x, y, width, height))
},
- update (o) {
+ update(o) {
if (typeof o !== 'object') {
return this.update({
offset: arguments[0],
diff --git a/src/animation/Timeline.js b/src/animation/Timeline.js
index 3f81b66..39e0f1a 100644
--- a/src/animation/Timeline.js
+++ b/src/animation/Timeline.js
@@ -7,7 +7,12 @@ const makeSchedule = function (runnerInfo) {
const start = runnerInfo.start
const duration = runnerInfo.runner.duration()
const end = start + duration
- return { start: start, duration: duration, end: end, runner: runnerInfo.runner }
+ return {
+ start: start,
+ duration: duration,
+ end: end,
+ runner: runnerInfo.runner
+ }
}
const defaultSource = function () {
@@ -17,7 +22,7 @@ const defaultSource = function () {
export default class Timeline extends EventTarget {
// Construct a new timeline on the given element
- constructor (timeSource = defaultSource) {
+ constructor(timeSource = defaultSource) {
super()
this._timeSource = timeSource
@@ -44,55 +49,55 @@ export default class Timeline extends EventTarget {
this._stepImmediate = this._stepFn.bind(this, true)
}
- active () {
+ active() {
return !!this._nextFrame
}
- finish () {
+ finish() {
// Go to end and pause
this.time(this.getEndTimeOfTimeline() + 1)
return this.pause()
}
// Calculates the end of the timeline
- getEndTime () {
+ getEndTime() {
const lastRunnerInfo = this.getLastRunnerInfo()
const lastDuration = lastRunnerInfo ? lastRunnerInfo.runner.duration() : 0
const lastStartTime = lastRunnerInfo ? lastRunnerInfo.start : this._time
return lastStartTime + lastDuration
}
- getEndTimeOfTimeline () {
+ getEndTimeOfTimeline() {
const endTimes = this._runners.map((i) => i.start + i.runner.duration())
return Math.max(0, ...endTimes)
}
- getLastRunnerInfo () {
+ getLastRunnerInfo() {
return this.getRunnerInfoById(this._lastRunnerId)
}
- getRunnerInfoById (id) {
+ getRunnerInfoById(id) {
return this._runners[this._runnerIds.indexOf(id)] || null
}
- pause () {
+ pause() {
this._paused = true
return this._continue()
}
- persist (dtOrForever) {
+ persist(dtOrForever) {
if (dtOrForever == null) return this._persist
this._persist = dtOrForever
return this
}
- play () {
+ play() {
// Now make sure we are not paused and continue the animation
this._paused = false
return this.updateTime()._continue()
}
- reverse (yes) {
+ reverse(yes) {
const currentSpeed = this.speed()
if (yes == null) return this.speed(-currentSpeed)
@@ -101,7 +106,7 @@ export default class Timeline extends EventTarget {
}
// schedules a runner on the timeline
- schedule (runner, delay, when) {
+ schedule(runner, delay, when) {
if (runner == null) {
return this._runners.map(makeSchedule)
}
@@ -152,42 +157,42 @@ export default class Timeline extends EventTarget {
this._runners.push(runnerInfo)
this._runners.sort((a, b) => a.start - b.start)
- this._runnerIds = this._runners.map(info => info.runner.id)
+ this._runnerIds = this._runners.map((info) => info.runner.id)
this.updateTime()._continue()
return this
}
- seek (dt) {
+ seek(dt) {
return this.time(this._time + dt)
}
- source (fn) {
+ source(fn) {
if (fn == null) return this._timeSource
this._timeSource = fn
return this
}
- speed (speed) {
+ speed(speed) {
if (speed == null) return this._speed
this._speed = speed
return this
}
- stop () {
+ stop() {
// Go to start and pause
this.time(0)
return this.pause()
}
- time (time) {
+ time(time) {
if (time == null) return this._time
this._time = time
return this._continue(true)
}
// Remove the runner from this timeline
- unschedule (runner) {
+ unschedule(runner) {
const index = this._runnerIds.indexOf(runner.id)
if (index < 0) return this
@@ -199,7 +204,7 @@ export default class Timeline extends EventTarget {
}
// Makes sure, that after pausing the time doesn't jump
- updateTime () {
+ updateTime() {
if (!this.active()) {
this._lastSourceTime = this._timeSource()
}
@@ -207,7 +212,7 @@ export default class Timeline extends EventTarget {
}
// Checks if we are running and continues the animation
- _continue (immediateStep = false) {
+ _continue(immediateStep = false) {
Animator.cancelFrame(this._nextFrame)
this._nextFrame = null
@@ -218,7 +223,7 @@ export default class Timeline extends EventTarget {
return this
}
- _stepFn (immediateStep = false) {
+ _stepFn(immediateStep = false) {
// Get the time delta from the last time and update the time
const time = this._timeSource()
let dtSource = time - this._lastSourceTime
@@ -249,7 +254,7 @@ export default class Timeline extends EventTarget {
// runner always wins the reset even if the other runner started earlier
// and therefore should win the attribute battle
// this can be solved by resetting them backwards
- for (let k = this._runners.length; k--;) {
+ for (let k = this._runners.length; k--; ) {
// Get and run the current runner and ignore it if its inactive
const runnerInfo = this._runners[k]
const runner = runnerInfo.runner
@@ -309,7 +314,10 @@ export default class Timeline extends EventTarget {
// Basically: we continue when there are runners right from us in time
// when -->, and when runners are left from us when <--
- if ((runnersLeft && !(this._speed < 0 && this._time === 0)) || (this._runnerIds.length && this._speed < 0 && this._time > 0)) {
+ if (
+ (runnersLeft && !(this._speed < 0 && this._time === 0)) ||
+ (this._runnerIds.length && this._speed < 0 && this._time > 0)
+ ) {
this._continue()
} else {
this.pause()
@@ -318,14 +326,13 @@ export default class Timeline extends EventTarget {
return this
}
-
}
registerMethods({
Element: {
timeline: function (timeline) {
if (timeline == null) {
- this._timeline = (this._timeline || new Timeline())
+ this._timeline = this._timeline || new Timeline()
return this._timeline
} else {
this._timeline = timeline