-
Notifications
You must be signed in to change notification settings - Fork 2
/
timeline.js
85 lines (70 loc) · 2.16 KB
/
timeline.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// Timeline object
function timelineobj()
{
this.timeline=[]; // Array of actions
this.timelinepos=0; // Point in time of last update
this.timelineepoch=0; // Epoch when timeline was started
this.callback=null; // Optional callback on each timeline "tick"
this.running=false; // Start in non-running state
// Add a new function to timeline with a given start time
this.add=function(itemstart, newitem)
{
var newobj={start:itemstart, item:newitem, done:false};
this.timeline.push(newobj);
// Keep timeline sorted by start time of items
this.timeline.sort(function(a,b) {return ((b.start<a.start)?1:(b.start==a.start)?0:-1)});
};
// Add a timeline callback
this.addcallback=function(item)
{
this.callback=item;
};
// Animation frame callback
this.timelineraf=function(timestamp)
{
var remain=0;
// Stop further processing if we're not running
if (!this.running) return;
// If this is the first call then just record the epoch
if (this.timelinepos==0)
{
this.timelineepoch=timestamp;
}
else
{
// Calculate delta time since timeline start
var delta=timestamp-this.timelineepoch;
// Look through timeline array for jobs not run which should have
for (var i=0; i<this.timeline.length; i++)
{
if ((!this.timeline[i].done) && (this.timeline[i].start<delta))
{
this.timeline[i].done=true;
this.timeline[i].item();
}
// Keep a count of all remaining jobs
if (!this.timeline[i].done)
remain++;
}
// If a callback was requested, then call it
if (this.callback!=null)
this.callback();
}
// Record new timeline position
this.timelinepos=timestamp;
// If there is more jobs then request another callback
if ((this.timelinepos==this.timelineepoch) || (remain>0))
window.requestAnimationFrame(this.timelineraf.bind(this));
};
// Start the timeline running
this.begin=function()
{
this.running=true;
window.requestAnimationFrame(this.timelineraf.bind(this));
};
// Stop the timeline running
this.end=function()
{
this.running=false;
};
}