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