merge
[dygraphs.git] / gallery / drawing.js
CommitLineData
c1f22b5a
RK
1Gallery.register(
2 'drawing',
3 {
4 name: 'Time Series Drawing Demo',
5 title: 'Time Series Drawing Demo',
6 setup: function(parent) {
605b6119
RK
7 parent.innerHTML = [
8 "<div id='toolbar'>",
9 "<div id='tool_zoom'></div>",
10 "<div id='tool_pencil'></div>",
11 "<div id='tool_eraser'></div>",
12 "</div>",
10eef8e9 13 "<div id='draw_div' style='width: 600px; height: 300px;'></div>",
605b6119
RK
14 "<p style='font-size: 10pt'>Toolbar/cursor icons are CC-licensed from ",
15 "<a href='http://www.fatcow.com/free-icons'>FatCow</a>.</p>"].join("\n");
c1f22b5a 16 },
3c10a0f3 17
c1f22b5a 18 run: function() {
3c10a0f3
RK
19 var zoom = document.getElementById('tool_zoom');
20 zoom.onclick = function() { change_tool(zoom) };
21 var pencil = document.getElementById('tool_pencil');
22 pencil.onclick = function() { change_tool(pencil) };
7e464a91 23 var eraser = document.getElementById('tool_eraser');
3c10a0f3
RK
24 eraser.onclick = function() { change_tool(eraser) };
25
c1f22b5a
RK
26 var start_date = new Date("2002/12/29").getTime();
27 var end_date = new Date().getTime();
28 var data = [];
29 for (var d = start_date; d < end_date; d += 604800 * 1000) {
30 var millis = d + 2 * 3600 * 1000;
31 data.push( [ new Date(new Date(millis).strftime("%Y/%m/%d")), 50 ]);
32 }
3c10a0f3
RK
33
34 var isDrawing = false;
35 var lastDrawRow = null, lastDrawValue = null;
36 var tool = 'pencil';
37 var valueRange = [0, 100];
38
39 function setPoint(event, g, context) {
464b5f50
DV
40 var graphPos = Dygraph.findPos(g.graphDiv);
41 var canvasx = Dygraph.pageX(event) - graphPos.x;
42 var canvasy = Dygraph.pageY(event) - graphPos.y;
3c10a0f3
RK
43 var xy = g.toDataCoords(canvasx, canvasy);
44 var x = xy[0], value = xy[1];
45 var rows = g.numRows();
46 var closest_row = -1;
47 var smallest_diff = -1;
48 // TODO(danvk): binary search
49 for (var row = 0; row < rows; row++) {
50 var date = g.getValue(row, 0); // millis
51 var diff = Math.abs(date - x);
52 if (smallest_diff < 0 || diff < smallest_diff) {
53 smallest_diff = diff;
54 closest_row = row;
55 }
c1f22b5a 56 }
3c10a0f3
RK
57
58 if (closest_row != -1) {
59 if (lastDrawRow === null) {
60 lastDrawRow = closest_row;
61 lastDrawValue = value;
62 }
63 var coeff = (value - lastDrawValue) / (closest_row - lastDrawRow);
64 if (closest_row == lastDrawRow) coeff = 0.0;
65 var minRow = Math.min(lastDrawRow, closest_row);
66 var maxRow = Math.max(lastDrawRow, closest_row);
67 for (var row = minRow; row <= maxRow; row++) {
68 if (tool == 'pencil') {
69 var val = lastDrawValue + coeff * (row - lastDrawRow);
70 val = Math.max(valueRange[0], Math.min(val, valueRange[1]));
71 data[row][1] = val;
72 if (val == null || isNaN(val)) console.log(val);
73 } else if (tool == 'eraser') {
74 data[row][1] = null;
75 }
76 }
c1f22b5a
RK
77 lastDrawRow = closest_row;
78 lastDrawValue = value;
3c10a0f3
RK
79 g.updateOptions({ file: data });
80 g.setSelection(closest_row); // prevents the dot from being finnicky.
c1f22b5a 81 }
3c10a0f3
RK
82 }
83
84 function finishDraw() {
85 isDrawing = false;
86 lastDrawRow = null;
87 lastDrawValue = null;
88 }
89
90 var change_tool = function(tool_div) {
91 var ids = ['tool_zoom', 'tool_pencil', 'tool_eraser'];
92 for (var i = 0; i < ids.length; i++) {
93 var div = document.getElementById(ids[i]);
94 if (div == tool_div) {
95 div.style.backgroundPosition = -(i * 32) + 'px -32px';
96 } else {
97 div.style.backgroundPosition = -(i * 32) + 'px 0px';
c1f22b5a
RK
98 }
99 }
3c10a0f3
RK
100 tool = tool_div.id.replace('tool_', '');
101
102 var dg_div = document.getElementById("draw_div");
103 if (tool == 'pencil') {
104 dg_div.style.cursor = 'url(images/cursor-pencil.png) 2 30, auto';
105 } else if (tool == 'eraser') {
106 dg_div.style.cursor = 'url(images/cursor-eraser.png) 10 30, auto';
107 } else if (tool == 'zoom') {
108 dg_div.style.cursor = 'crosshair';
c1f22b5a
RK
109 }
110 }
3c10a0f3
RK
111 change_tool(document.getElementById("tool_pencil"));
112
113 g = new Dygraph(document.getElementById("draw_div"), data,
114 {
115 valueRange: valueRange,
116 labels: [ 'Date', 'Value' ],
117 interactionModel: {
118 mousedown: function (event, g, context) {
119 if (tool == 'zoom') {
120 Dygraph.defaultInteractionModel.mousedown(event, g, context);
c1f22b5a 121 } else {
3c10a0f3
RK
122 // prevents mouse drags from selecting page text.
123 if (event.preventDefault) {
124 event.preventDefault(); // Firefox, Chrome, etc.
125 } else {
126 event.returnValue = false; // IE
127 event.cancelBubble = true;
128 }
129 isDrawing = true;
130 setPoint(event, g, context);
c1f22b5a 131 }
3c10a0f3
RK
132 },
133 mousemove: function (event, g, context) {
134 if (tool == 'zoom') {
135 Dygraph.defaultInteractionModel.mousemove(event, g, context);
136 } else {
137 if (!isDrawing) return;
138 setPoint(event, g, context);
139 }
140 },
141 mouseup: function(event, g, context) {
142 if (tool == 'zoom') {
143 Dygraph.defaultInteractionModel.mouseup(event, g, context);
144 } else {
145 finishDraw();
146 }
147 },
148 mouseout: function(event, g, context) {
149 if (tool == 'zoom') {
150 Dygraph.defaultInteractionModel.mouseout(event, g, context);
151 }
152 },
153 dblclick: function(event, g, context) {
154 Dygraph.defaultInteractionModel.dblclick(event, g, context);
155 },
156 mousewheel: function(event, g, context) {
157 var normal = event.detail ? event.detail * -1 : event.wheelDelta / 40;
158 var percentage = normal / 50;
159 var axis = g.xAxisRange();
160 var xOffset = g.toDomCoords(axis[0], null)[0];
161 var x = event.offsetX - xOffset;
162 var w = g.toDomCoords(axis[1], null)[0] - xOffset;
163 var xPct = w == 0 ? 0 : (x / w);
164
165 var delta = axis[1] - axis[0];
166 var increment = delta * percentage;
167 var foo = [increment * xPct, increment * (1 - xPct)];
168 var dateWindow = [ axis[0] + foo[0], axis[1] - foo[1] ];
169
170 g.updateOptions({
171 dateWindow: dateWindow
172 });
173 Dygraph.cancelEvent(event);
c1f22b5a
RK
174 }
175 },
3c10a0f3
RK
176 strokeWidth: 1.5,
177 gridLineColor: 'rgb(196, 196, 196)',
178 drawYGrid: false,
179 drawYAxis: false
180 });
181 window.onmouseup = finishDraw;
182 }
464b5f50 183 });