Skip to content

Commit eee87c3

Browse files
committed
Merge pull request #2 from kennethormandy/ko-looping
Adds support for looping
2 parents f3b3f4d + ed57dae commit eee87c3

2 files changed

Lines changed: 62 additions & 3 deletions

File tree

lib/keyframes.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,29 @@ export default class Keyframes extends React.Component {
77
children: PropTypes.arrayOf(PropTypes.element).isRequired,
88
component: PropTypes.any,
99
delay: PropTypes.number,
10+
loop: PropTypes.oneOfType([
11+
React.PropTypes.string,
12+
React.PropTypes.number,
13+
React.PropTypes.bool
14+
]),
1015
onStart: PropTypes.func,
1116
onEnd: PropTypes.func
1217
};
1318

1419
static defaultProps = {
1520
component: 'span',
1621
delay: 0,
22+
loop: 1,
1723
onStart: noop,
1824
onEnd: noop
1925
};
2026

2127
constructor (props) {
2228
super(props);
23-
this.state = { frameNum: this.props.delay ? -1 : 0 };
29+
this.state = {
30+
frameNum: this.props.delay ? -1 : 0,
31+
loopNum: 0
32+
};
2433
this.timer = null;
2534
}
2635

@@ -65,9 +74,19 @@ export default class Keyframes extends React.Component {
6574
requestNextFrame () {
6675
this.waitForDelay(() => {
6776
const frameNum = this.state.frameNum + 1;
77+
const loopNum = this.state.loopNum + 1;
6878
if (this.props.children.length <= frameNum) {
69-
this.props.onEnd();
70-
return;
79+
if (this.props.loop === true || this.props.loop === 'infinite' || loopNum < this.props.loop) {
80+
this.setState({
81+
frameNum: 0,
82+
loopNum
83+
});
84+
this.requestNextFrame();
85+
return;
86+
} else {
87+
this.props.onEnd();
88+
return;
89+
}
7190
}
7291

7392
this.setState({ frameNum });

test/index.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,43 @@ test('set component', (t) => {
8888
t.same(node.tagName, 'PRE');
8989
t.same(node.className, 'woot');
9090
});
91+
92+
test('Infinite loop', (t) => {
93+
const container = document.createElement('div');
94+
const onStart = () => onStart.called = true;
95+
const onEnd = () => onEnd.called = true;
96+
render(
97+
<Keyframes onStart={onStart} onEnd={onEnd} loop>
98+
<Frame duration={100}>foo</Frame>
99+
<Frame duration={100}>bar</Frame>
100+
</Keyframes>,
101+
container
102+
);
103+
104+
t.ok(onStart.called);
105+
clock.tick(100);
106+
t.notOk(onEnd.called);
107+
clock.tick(200);
108+
t.notOk(onEnd.called);
109+
});
110+
111+
test('Finite loop', (t) => {
112+
const container = document.createElement('div');
113+
const onStart = () => onStart.called = true;
114+
const onEnd = () => onEnd.called = true;
115+
render(
116+
<Keyframes onStart={onStart} onEnd={onEnd} loop={3}>
117+
<Frame duration={100}>foo</Frame>
118+
<Frame duration={100}>bar</Frame>
119+
</Keyframes>,
120+
container
121+
);
122+
123+
t.ok(onStart.called);
124+
clock.tick(100);
125+
t.notOk(onEnd.called);
126+
clock.tick(200);
127+
t.notOk(onEnd.called);
128+
clock.tick(300);
129+
t.ok(onEnd.called);
130+
});

0 commit comments

Comments
 (0)