Speed up filled charts by down-sampling.
[dygraphs.git] / tests / plotters.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9">
5 <title>Plotters demo</title>
6 <!--[if IE]>
7 <script type="text/javascript" src="../excanvas.js"></script>
8 <![endif]-->
9 <script type="text/javascript" src="../dygraph-dev.js"></script>
10
11 <script type="text/javascript" src="data.js"></script>
12 <style type="text/css">
13 body {
14 max-width: 750px;
15 }
16 div.chart {
17 width: 640px;
18 height: 320px;
19 }
20 </style>
21 </head>
22 <body>
23 <p>This page demonstrates how to build custom plotters with dygraphs.
24 The <a href="http://dygraphs.com/options.html#plotter">plotter</a> option
25 allows you to write your own drawing logic. This can be used to achieve
26 powerful customization. View source to see how the examples work.</p>
27
28 <h2>Bar Chart</h2>
29 <p>Here a specialized <a
30 href="http://dygraphs.com/options.html#plotter">plotter</a> is used to draw
31 a bar plot rather than a line plot:</p>
32 <div id="demodiv" class=chart></div>
33
34 <h2>Candle Chart</h2>
35 <p>Here a specialized <a
36 href="http://dygraphs.com/options.html#plotter">plotter</a> is used to
37 combined four series into a unified "Candle" plot:</p>
38 <div id="candlechart" class=chart></div>
39
40 <h2>Bar &amp; Line Chart</h2>
41 <p>The <a href="http://dygraphs.com/options.html#plotter">plotter</a>
42 option may be set on a per-series basis to create mixed charts:</p>
43 <div id="barlinechart" class="chart"></div>
44
45 <h2>Multi-column Bar Chart</h2>
46 <div id="multibar" class="chart"></div>
47
48 <h2>Mixed Error Bars and Lines</h2>
49 <p>You can tweak the standard plotters list to achieve effects which would
50 be difficult otherwise, e.g. drawing series with only confidence intervals
51 and showing error bars only for some series.</p>
52 <div id="mixed-error" class="chart"></div>
53
54 <h2>Smooth Lines</h2>
55 <p>See the <a href="smooth-plots.html">smooth-plots demo</a> for an example of a custom plotter which connects points using bezier curves instead of straight lines.</p>
56
57 <script type="text/javascript">
58 // Darken a color
59 function darkenColor(colorStr) {
60 // Defined in dygraph-utils.js
61 var color = Dygraph.toRGB_(colorStr);
62 color.r = Math.floor((255 + color.r) / 2);
63 color.g = Math.floor((255 + color.g) / 2);
64 color.b = Math.floor((255 + color.b) / 2);
65 return 'rgb(' + color.r + ',' + color.g + ',' + color.b + ')';
66 }
67
68 // This function draws bars for a single series. See
69 // multiColumnBarPlotter below for a plotter which can draw multi-series
70 // bar charts.
71 function barChartPlotter(e) {
72 var ctx = e.drawingContext;
73 var points = e.points;
74 var y_bottom = e.dygraph.toDomYCoord(0);
75
76 ctx.fillStyle = darkenColor(e.color);
77
78 // Find the minimum separation between x-values.
79 // This determines the bar width.
80 var min_sep = Infinity;
81 for (var i = 1; i < points.length; i++) {
82 var sep = points[i].canvasx - points[i - 1].canvasx;
83 if (sep < min_sep) min_sep = sep;
84 }
85 var bar_width = Math.floor(2.0 / 3 * min_sep);
86
87 // Do the actual plotting.
88 for (var i = 0; i < points.length; i++) {
89 var p = points[i];
90 var center_x = p.canvasx;
91
92 ctx.fillRect(center_x - bar_width / 2, p.canvasy,
93 bar_width, y_bottom - p.canvasy);
94
95 ctx.strokeRect(center_x - bar_width / 2, p.canvasy,
96 bar_width, y_bottom - p.canvasy);
97 }
98 }
99
100 g = new Dygraph(
101 document.getElementById("demodiv"),
102 "Date,Widgets Sold\n" +
103 "2012/07/21,10\n" +
104 "2012/07/22,12\n" +
105 "2012/07/23,9\n" +
106 "2012/07/24,16\n" +
107 "2012/07/25,10\n",
108 {
109 legend: 'always',
110 title: 'Daily Widget Sales',
111 includeZero: true,
112 dateWindow: [ Date.parse("2012/07/20"), Date.parse("2012/07/26") ],
113 animatedZooms: true,
114 drawXGrid: false,
115 plotter: barChartPlotter
116 }
117 );
118
119 // The Candle chart plotter is adapted from code written by
120 // Zhenlei Cai (jpenguin@gmail.com)
121 // https://github.com/danvk/dygraphs/pull/141/files
122
123 var BAR_WIDTH = 8;
124 function candlePlotter(e) {
125 // This is the officially endorsed way to plot all the series at once.
126 if (e.seriesIndex !== 0) return;
127
128 var setCount = e.seriesCount;
129 if (setCount != 4) {
130 throw "Exactly 4 prices each point must be provided for candle chart (open close high low)";
131 }
132
133 var prices = [];
134 var price;
135 var sets = e.allSeriesPoints;
136 for (var p = 0 ; p < sets[0].length; p++) {
137 price = {
138 open : sets[0][p].yval,
139 close : sets[1][p].yval,
140 high : sets[2][p].yval,
141 low : sets[3][p].yval,
142 openY : sets[0][p].y,
143 closeY : sets[1][p].y,
144 highY : sets[2][p].y,
145 lowY : sets[3][p].y
146 };
147 prices.push(price);
148 }
149
150 var area = e.plotArea;
151 var ctx = e.drawingContext;
152 ctx.strokeStyle = '#202020';
153 ctx.lineWidth = 0.6;
154
155 for (p = 0 ; p < prices.length; p++) {
156 ctx.beginPath();
157
158 price = prices[p];
159 var topY = area.h * price.highY + area.y;
160 var bottomY = area.h * price.lowY + area.y;
161 var centerX = area.x + sets[0][p].x * area.w;
162 ctx.moveTo(centerX, topY);
163 ctx.lineTo(centerX, bottomY);
164 ctx.closePath();
165 ctx.stroke();
166 var bodyY;
167 if (price.open > price.close) {
168 ctx.fillStyle ='rgba(244,44,44,1.0)';
169 bodyY = area.h * price.openY + area.y;
170 }
171 else {
172 ctx.fillStyle ='rgba(44,244,44,1.0)';
173 bodyY = area.h * price.closeY + area.y;
174 }
175 var bodyHeight = area.h * Math.abs(price.openY - price.closeY);
176 ctx.fillRect(centerX - BAR_WIDTH / 2, bodyY, BAR_WIDTH, bodyHeight);
177 }
178
179 }
180
181 var candleData = "Date,Open,Close,High,Low\n" +
182 "2011-12-06,392.54,390.95,394.63,389.38\n" +
183 "2011-12-07,389.93,389.09,390.94,386.76\n" +
184 "2011-12-08,391.45,390.66,395.50,390.23\n" +
185 "2011-12-09,392.85,393.62,394.04,391.03\n" +
186 "2011-12-12,391.68,391.84,393.90,389.45\n" +
187 "2011-12-13,393.00,388.81,395.40,387.10\n" +
188 "2011-12-14,386.70,380.19,387.38,377.68\n" +
189 "2011-12-15,383.33,378.94,383.74,378.31\n" +
190 "2011-12-16,380.36,381.02,384.15,379.57\n" +
191 "2011-12-19,382.47,382.21,384.85,380.48\n" +
192 "2011-12-20,387.76,395.95,396.10,387.26\n" +
193 "2011-12-21,396.69,396.45,397.30,392.01\n" +
194 "2011-12-22,397.00,398.55,399.13,396.10\n" +
195 "2011-12-23,399.69,403.33,403.59,399.49\n" +
196 "2011-12-27,403.10,406.53,409.09,403.02\n" +
197 "2011-12-28,406.89,402.64,408.25,401.34\n" +
198 "2011-12-29,403.40,405.12,405.65,400.51\n" +
199 "2011-12-30,403.51,405.00,406.28,403.49\n" +
200 "2012-01-03,409.50,411.23,412.50,409.00\n" +
201 "2012-01-04,410.21,413.44,414.68,409.28\n" +
202 "2012-01-05,414.95,418.03,418.55,412.67\n" +
203 "2012-01-06,419.77,422.40,422.75,419.22\n" +
204 "2012-01-09,425.52,421.73,427.75,421.35\n" +
205 "2012-01-10,425.91,423.24,426.00,421.50\n" +
206 "2012-01-11,422.59,422.55,422.85,419.31\n" +
207 "2012-01-12,422.41,421.39,422.90,418.75\n" +
208 "2012-01-13,419.53,419.81,420.45,418.66\n" +
209 "2012-01-17,424.20,424.70,425.99,422.96\n" +
210 "2012-01-18,426.87,429.11,429.47,426.30\n" +
211 "2012-01-19,430.03,427.75,431.37,426.51\n" +
212 "2012-01-20,427.49,420.30,427.50,419.75\n" +
213 "2012-01-23,422.67,427.41,428.45,422.30\n" +
214 "2012-01-24,425.10,420.41,425.10,419.55\n" +
215 "2012-01-25,454.26,446.66,454.45,443.73\n" +
216 "2012-01-26,448.45,444.63,448.79,443.14\n" +
217 "2012-01-27,444.37,447.28,448.48,443.77\n" +
218 "2012-01-30,445.71,453.01,453.90,445.39\n" +
219 "2012-01-31,455.85,456.48,458.24,453.07\n" +
220 "2012-02-01,458.49,456.19,458.99,455.55\n" +
221 "2012-02-02,455.90,455.12,457.17,453.98\n" +
222 "2012-02-03,457.30,459.68,460.00,455.56\n" +
223 "2012-02-06,458.38,463.97,464.98,458.20\n" +
224 "2012-02-07,465.25,468.83,469.75,464.58\n" +
225 "2012-02-08,470.50,476.68,476.79,469.70\n" +
226 "2012-02-09,480.95,493.17,496.75,480.56\n" +
227 "2012-02-10,491.17,493.42,497.62,488.55\n" +
228 "2012-02-13,499.74,502.60,503.83,497.09\n" +
229 "2012-02-14,504.70,509.46,509.56,502.00\n" ;
230
231 g2 = new Dygraph(
232 document.getElementById("candlechart"),
233 candleData,
234 {
235 plotter: candlePlotter
236 });
237
238
239 // Bar and Line chart
240 var short_data = data_nolabel();
241 short_data = short_data.split('\n').slice(0, 20).join('\n');
242
243 g3 = new Dygraph(
244 document.getElementById("barlinechart"),
245 short_data,
246 {
247 labels: ['Date', 'A', 'B'],
248 includeZero: true,
249 "A": {
250 strokeWidth: 2
251 },
252 "B": {
253 plotter: barChartPlotter
254 }
255 });
256
257
258 // Multiple column bar chart
259 function multiColumnBarPlotter(e) {
260 // We need to handle all the series simultaneously.
261 if (e.seriesIndex !== 0) return;
262
263 var g = e.dygraph;
264 var ctx = e.drawingContext;
265 var sets = e.allSeriesPoints;
266 var y_bottom = e.dygraph.toDomYCoord(0);
267
268 // Find the minimum separation between x-values.
269 // This determines the bar width.
270 var min_sep = Infinity;
271 for (var j = 0; j < sets.length; j++) {
272 var points = sets[j];
273 for (var i = 1; i < points.length; i++) {
274 var sep = points[i].canvasx - points[i - 1].canvasx;
275 if (sep < min_sep) min_sep = sep;
276 }
277 }
278 var bar_width = Math.floor(2.0 / 3 * min_sep);
279
280 var fillColors = [];
281 var strokeColors = g.getColors();
282 for (var i = 0; i < strokeColors.length; i++) {
283 fillColors.push(darkenColor(strokeColors[i]));
284 }
285
286 for (var j = 0; j < sets.length; j++) {
287 ctx.fillStyle = fillColors[j];
288 ctx.strokeStyle = strokeColors[j];
289 for (var i = 0; i < sets[j].length; i++) {
290 var p = sets[j][i];
291 var center_x = p.canvasx;
292 var x_left = center_x - (bar_width / 2) * (1 - j/(sets.length-1));
293
294 ctx.fillRect(x_left, p.canvasy,
295 bar_width/sets.length, y_bottom - p.canvasy);
296
297 ctx.strokeRect(x_left, p.canvasy,
298 bar_width/sets.length, y_bottom - p.canvasy);
299 }
300 }
301 }
302
303 g4 = new Dygraph(
304 document.getElementById("multibar"),
305 short_data,
306 {
307 includeZero: true,
308 plotter: multiColumnBarPlotter
309 });
310
311 // Mixed Error Bars and Lines
312 g5 = new Dygraph(
313 document.getElementById("mixed-error"),
314 NoisyData(),
315 {
316 errorBars: true,
317 'A': {
318 plotter: Dygraph.Plotters.errorPlotter
319 },
320 'B': {
321 plotter: Dygraph.Plotters.linePlotter,
322 strokePattern: Dygraph.DASHED_LINE
323 }
324 });
325
326 </script>
327 </body>
328 </html>