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