Skip to content

Commit

Permalink
timing can now handle a duration of zero, timeline set takes now zero…
Browse files Browse the repository at this point in the history
… duration
  • Loading branch information
soerenmeier committed Jan 14, 2024
1 parent 7a69ec0 commit 258e405
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 14 deletions.
6 changes: 1 addition & 5 deletions src/tests/properties.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,12 @@ describe('properties', () => {

let windowAspectRatio;
const resp1 = responsive(() => {
console.log('reso call');
windowAspectRatio = windowWidth / 9;
});

const tl = timeline()
.add(div, {
width: responsive(e => {
console.log('width resp');
return 20 * windowAspectRatio
}),
width: responsive(e => 20 * windowAspectRatio),
duration: 10
})
.addResponsive(resp1);
Expand Down
27 changes: 27 additions & 0 deletions src/tests/timeline.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,33 @@ describe('timeline', () => {

ticker.run();
expect(target.style.transform).toBe('translateX(10.000px)');

tl.reverse();
tl.play();
ticker.run();
expect(target.style.transform).toBe('');
});

it('timeline set', () => {
const ticker = new TestTicker;

const target = el();
const tl = timeline()
.set(target, {
x: 10
});
tl.play();

ticker.run(0);
expect(target.style.transform).toBe('translateX(10.000px)');

ticker.run();
expect(target.style.transform).toBe('translateX(10.000px)');

tl.reverse();
tl.play();
ticker.run();
expect(target.style.transform).toBe('translateX(10.000px)');
});

it('offsetTimeline timeline', () => {
Expand Down
48 changes: 47 additions & 1 deletion src/tests/timing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,56 @@ import Timing, {
} from '../timing/timing.js';

describe('timing', () => {
it('short timing', () => {
it('zero duration', () => {
// if duration is zero the position is always 1
// and the state is either BEFORE or AFTER
const timing = new Timing({
duration: 0
});
expect(timing.duration).toBe(0);
expect(timing.state).toBe(STATE_BEFORE);

timing.seek(-1);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_BEFORE);

timing.seek(0);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_AFTER);

timing.seek(.5);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_AFTER);

timing.seek(1);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_AFTER);

timing.seek(2);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_AFTER);

timing.seekMs(-1);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_BEFORE);

timing.seekMs(0);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_AFTER);

timing.seekMs(.5);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_AFTER);

timing.seekMs(1);
expect(timing.position).toBe(1);
expect(timing.state).toBe(STATE_AFTER);
});

it('short timing', () => {
const timing = new Timing({
duration: 1
});
expect(timing.duration).toBe(1);
expect(timing.state).toBe(STATE_BEFORE);

Expand Down
9 changes: 7 additions & 2 deletions src/tests/usecases.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ describe('usecases', () => {
.add(ctn, {
maxHeight: responsive(el => el.scrollHeight),
duration: 100
}, 0);
});

tl.play();
ticker.run(1);
expect(ctn.style.maxHeight).toBe('1.000px');
expect(itm.classList.contains('open')).toBe(true);

// // on click
tl.play();
ticker.run(5);
ticker.run(4);
expect(ctn.style.maxHeight).toBe('5.000px');
expect(itm.classList.contains('open')).toBe(true);

Expand Down
37 changes: 31 additions & 6 deletions src/timing/timing.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const STATE_AFTER = 4;
*
*
* Timing works the same as in after effects
* duration must be at least 1ms
* if the duration is not at least 1ms the position is always 1 and either
* STATE_BEFORE or STATE_AFTER
*
* if the duration is 1ms seek 0 or 1 will always result in position 1
* because it is like one frame, so it's an image
Expand Down Expand Up @@ -50,7 +51,7 @@ export default class Timing {
this.alternate = props.alternate ?? true;
this.reversed = props.reversed ?? false;

this.position = 0;
this.position = this.duration > 0 ? 0 : 1;
this.state = STATE_BEFORE;

// progress does not take alternation into account and has no easing
Expand Down Expand Up @@ -83,9 +84,9 @@ export default class Timing {
return this.position * this.iterDuration + 1;
}

/// iterDuration will always be >=1
/// iterDuration should always be >=0
setDuration(iterDuration) {
this.iterDuration = Math.max(iterDuration, 1);
this.iterDuration = iterDuration;

this.duration = this.iterDuration;
if (this.repeat > -1) {
Expand All @@ -101,10 +102,20 @@ export default class Timing {
if (this.state >= STATE_AFTER)
return;

if (this.iterDuration <= 0) {
this._updateProgress(1);
return;
}

this._updateProgress(this._progress + change / this.iterDuration);
}

seekMs(ms) {
if (this.iterDuration <= 0) {
this._updateProgress(Math.sign(ms));
return;
}

this._updateProgress(ms / this.iterDuration);
}

Expand Down Expand Up @@ -167,6 +178,21 @@ export default class Timing {
}

_updateProgress(newProgress) {
// if duration is zero the position is always 1
// and the state is either BEFORE or AFTER
if (this.iterDuration <= 0) {
newProgress = Math.sign(newProgress);
this._progress = newProgress;
this.position = 1;

if (newProgress < 0)
this.state = STATE_BEFORE;
else
this.state = STATE_AFTER;

return;
}

this._progress = newProgress;

// since infinite repeat can never end let's ignore it
Expand Down Expand Up @@ -220,10 +246,9 @@ export function parseDuration(dur) {
if (typeof dur !== 'number')
throw new Error('duration is not a number');

// convert s to ms
dur = Math.round(dur);

return Math.max(dur, 1);
return Math.max(dur, 0);
}

export function parseEase(ease) {
Expand Down

0 comments on commit 258e405

Please sign in to comment.