diff --git a/src/tweenable.js b/src/tweenable.js index d8e5e887..dafcad9d 100644 --- a/src/tweenable.js +++ b/src/tweenable.js @@ -130,11 +130,11 @@ const processTween = (tween, currentTime) => { const endTime = timestamp + delay + duration let timeToCompute = currentTime > endTime ? endTime : currentTime - const hasEnded = timeToCompute >= endTime + tween._hasEnded = timeToCompute >= endTime const offset = duration - (endTime - timeToCompute) const hasFilters = tween._filters.length > 0 - if (hasEnded) { + if (tween._hasEnded) { tween._render(targetState, tween._data, offset) return tween.stop(true) } @@ -321,6 +321,8 @@ export class Tweenable { /** @private */ this._timestamp = null /** @private */ + this._hasEnded = false + /** @private */ this._resolve = null /** @private */ this._reject = null @@ -717,6 +719,15 @@ export class Tweenable { return this._isPlaying } + /** + * Whether or not a tween has finished running. + * @method Tweenable#hasEnded + * @return {boolean} + */ + hasEnded() { + return this._hasEnded + } + /** * @method Tweenable#setScheduleFunction * @param {shifty.scheduleFunction} scheduleFunction diff --git a/src/tweenable.test.js b/src/tweenable.test.js index 54d0469a..1d56f51c 100644 --- a/src/tweenable.test.js +++ b/src/tweenable.test.js @@ -324,6 +324,37 @@ describe('#tween', () => { }) }) +describe('#hasEnded', () => { + test('Only trigger after the end of the tween', () => { + tweenable = new Tweenable() + + tweenable.tween({ + from: { x: 0 }, + to: { x: 10 }, + duration: 500, + }) + + expect(tweenable.hasEnded()).toBe(false) + tweenable.seek(500) + expect(tweenable.hasEnded()).toBe(true) + }) + + test('Triggers again after restarting the tween', () => { + tweenable = new Tweenable() + + tweenable.tween({ + from: { x: 0 }, + to: { x: 10 }, + duration: 500, + }) + + tweenable.seek(500) + expect(tweenable.hasEnded()).toBe(true) + tweenable.seek(0) + expect(tweenable.hasEnded()).toBe(false) + }) +}) + describe('#resume', () => { beforeEach(() => { Tweenable.now = () => 0