Last active
May 20, 2017 11:16
-
-
Save vaalentin/affaf6f01e53796c471b73d5c9488a91 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Signal<T> { | |
private _listeners: ((data?: T) => any)[] | |
constructor() { | |
this._listeners = [] | |
} | |
public add(listener: (data?: T) => any) { | |
const i = this._listeners.indexOf(listener) | |
if (i !== -1) { | |
return | |
} | |
this._listeners.push(listener) | |
} | |
public remove(listener: (data?: T) => any) { | |
const i = this._listeners.indexOf(listener) | |
if (i === -1) { | |
return | |
} | |
this._listeners.splice(i, 1) | |
} | |
public dispatch(data?: T) { | |
for (let listener of this._listeners) { | |
listener(data) | |
} | |
} | |
public dispose() { | |
this._listeners.length = 0 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Spring { | |
private static _EPSILON = 0.001 | |
private static _MAX_DELTA = 0.032 | |
private static _springs: Spring[] = [] | |
public static update(dt: number) { | |
dt = Math.min(Spring._MAX_DELTA, dt) | |
for (let spring of Spring._springs) { | |
spring.update(dt) | |
} | |
} | |
private _currentValue: number | |
private _endValue: number | |
private _velocity: number | |
private _isActive: boolean | |
public stiffness: number | |
public damping: number | |
public mass: number | |
public onUpdate: Signal<{ value: number, velocity: number }> | |
public onComplete: Signal<{ value: number, velocity: number }> | |
constructor(stiffness = -30, damping = -0.97, mass = 0.1) { | |
this._currentValue = 0 | |
this._endValue = 0 | |
this._velocity = 0 | |
this._isActive = false | |
this.stiffness = stiffness | |
this.damping = damping | |
this.mass = mass | |
this.onUpdate = new Signal() | |
this.onComplete = new Signal() | |
} | |
private _start() { | |
this._isActive = true | |
Spring._springs.push(this) | |
} | |
private _stop() { | |
this._isActive = false | |
const i = Spring._springs.indexOf(this) | |
if (i === -1) { | |
return | |
} | |
Spring._springs.splice(i, 1) | |
} | |
public setCurrentValue(value: number) { | |
this._currentValue = value | |
this._endValue = value | |
} | |
public setEndValue(value: number) { | |
if (value === this._endValue) { | |
return | |
} | |
this._endValue = value | |
if (!this._isActive) { | |
this._start() | |
} | |
} | |
public update(dt: number) { | |
const springForce = this.stiffness * ((this._currentValue - this._endValue)) | |
if (Math.abs(springForce) < Spring._EPSILON) { | |
this._currentValue = this._endValue | |
this._velocity = 0 | |
this.onUpdate.dispatch({ value: this._currentValue, velocity: this._velocity }) | |
this.onComplete.dispatch({ value: this._currentValue, velocity: this._velocity }) | |
return this._stop() | |
} | |
const dampingForce = this.damping * this._velocity | |
const acceleration = (springForce + dampingForce) / this.mass | |
this._velocity += acceleration * dt | |
this._currentValue += this._velocity * dt | |
this.onUpdate.dispatch({ value: this._currentValue, velocity: this._velocity }) | |
} | |
public dispose() { | |
this._stop() | |
this.onUpdate.dispose() | |
this.onComplete.dispose() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment