-
Notifications
You must be signed in to change notification settings - Fork 0
/
animate.js
163 lines (156 loc) · 4.67 KB
/
animate.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
Plotly.d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv', function (err, data) {
// Create a lookup table to sort and regroup the columns of data,
// first by year, then by continent:
var lookup = {};
function getData(year, continent) {
var byYear, trace;
if (!(byYear = lookup[year])) {;
byYear = lookup[year] = {};
}
// If a container for this year + continent doesn't exist yet,
// then create one:
if (!(trace = byYear[continent])) {
trace = byYear[continent] = {
x: [],
y: [],
id: [],
text: [],
marker: {size: []}
};
}
return trace;
}
// Go through each row, get the right trace, and append the data:
for (var i = 0; i < data.length; i++) {
var datum = data[i];
var trace = getData(datum.year, datum.continent);
trace.text.push(datum.country);
trace.id.push(datum.country);
trace.x.push(datum.lifeExp);
trace.y.push(datum.gdpPercap);
trace.marker.size.push(datum.pop);
}
// Get the group names:
var years = Object.keys(lookup);
// In this case, every year includes every continent, so we
// can just infer the continents from the *first* year:
var firstYear = lookup[years[0]];
var continents = Object.keys(firstYear);
// Create the main traces, one for each continent:
var traces = [];
for (i = 0; i < continents.length; i++) {
var data = firstYear[continents[i]];
// One small note. We're creating a single trace here, to which
// the frames will pass data for the different years. It's
// subtle, but to avoid data reference problems, we'll slice
// the arrays to ensure we never write any new data into our
// lookup table:
traces.push({
name: continents[i],
x: data.x.slice(),
y: data.y.slice(),
id: data.id.slice(),
text: data.text.slice(),
mode: 'markers',
marker: {
size: data.marker.size.slice(),
sizemode: 'area',
sizeref: 200000
}
});
}
// Create a frame for each year. Frames are effectively just
// traces, except they don't need to contain the *full* trace
// definition (for example, appearance). The frames just need
// the parts the traces that change (here, the data).
var frames = [];
for (i = 0; i < years.length; i++) {
frames.push({
name: years[i],
data: continents.map(function (continent) {
return getData(years[i], continent);
})
})
}
// Now create slider steps, one for each frame. The slider
// executes a plotly.js API command (here, Plotly.animate).
// In this example, we'll animate to one of the named frames
// created in the above loop.
var sliderSteps = [];
for (i = 0; i < years.length; i++) {
sliderSteps.push({
method: 'animate',
label: years[i],
args: [[years[i]], {
mode: 'immediate',
transition: {duration: 300},
frame: {duration: 300, redraw: false},
}]
});
}
var layout = {
xaxis: {
title: 'Life Expectancy',
range: [30, 85]
},
yaxis: {
title: 'GDP per Capita',
type: 'log'
},
hovermode: 'closest',
// We'll use updatemenus (whose functionality includes menus as
// well as buttons) to create a play button and a pause button.
// The play button works by passing `null`, which indicates that
// Plotly should animate all frames. The pause button works by
// passing `[null]`, which indicates we'd like to interrupt any
// currently running animations with a new list of frames. Here
// The new list of frames is empty, so it halts the animation.
updatemenus: [{
x: 0,
y: 0,
yanchor: 'top',
xanchor: 'left',
showactive: false,
direction: 'left',
type: 'buttons',
pad: {t: 87, r: 10},
buttons: [{
method: 'animate',
args: [null, {
mode: 'immediate',
fromcurrent: true,
transition: {duration: 300},
frame: {duration: 500, redraw: false}
}],
label: 'Play'
}, {
method: 'animate',
args: [[null], {
mode: 'immediate',
transition: {duration: 0},
frame: {duration: 0, redraw: false}
}],
label: 'Pause'
}]
}],
// Finally, add the slider and use `pad` to position it
// nicely next to the buttons.
sliders: [{
pad: {l: 130, t: 55},
currentvalue: {
visible: true,
prefix: 'Year:',
xanchor: 'right',
font: {size: 20, color: '#666'}
},
steps: sliderSteps
}]
};
console.log(frames);
// Create the plot:
Plotly.newPlot('tester1', {
data: traces,
layout: layout,
frames: frames,
});
});