Skip to content

Commit 2f8ed4b

Browse files
committed
real-time graphing now uses a canvas overlay
This speeds up real-time graphing of 5000 points by a factor of 4.
1 parent 20a640b commit 2f8ed4b

File tree

3 files changed

+85
-17
lines changed

3 files changed

+85
-17
lines changed

avalanche2d.html

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ <h1 id="title">Avalanche-JS Demo</h1>
157157
<fieldset>
158158
<legend>Rendering</legend>
159159
<label><input id="show-visualization" type="checkbox" checked/> Visualization</label>
160-
<label><input id="show-graph" type="checkbox" /> Graph</label>
160+
<label><input id="show-graph" type="checkbox" checked/> Graph</label>
161161
<label><input id="show-data-table" type="checkbox"/> Folder-Desk Array</label>
162162
</fieldset>
163163
</form>
@@ -300,6 +300,7 @@ <h3>Folder-Desk Data Array:</h3>
300300
displayStats();
301301
avalanche2d.displayFolderCanvas(canvas, model);
302302
};
303+
graph.hide_canvas();
303304
graph.new_data(graph_data);
304305
step_model_inputs[0].checked = true;
305306
};
@@ -312,6 +313,7 @@ <h3>Folder-Desk Data Array:</h3>
312313
displayStats();
313314
avalanche2d.displayFolderCanvas(canvas, model);
314315
};
316+
graph.hide_canvas();
315317
graph.new_data(graph_data);
316318
if (model.indexOfStep >= 5000) displayResetWarning();
317319
step_model_inputs[0].checked = true;
@@ -324,6 +326,10 @@ <h3>Folder-Desk Data Array:</h3>
324326
step_model_inputs[0].checked = true;
325327
} else {
326328
start_time = +new Date();
329+
if (show_graph.checked) {
330+
graph.initialize_canvas();
331+
graph.show_canvas();
332+
};
327333
modelRunRequest = requestAnimFrame(runModelLoop, visualizations);
328334
}
329335
};
@@ -335,6 +341,7 @@ <h3>Folder-Desk Data Array:</h3>
335341
folder_data.innerHTML = '';
336342
step_count.innerHTML = '';
337343
step_model_warning.innerHTML = null;
344+
graph.hide_canvas();
338345
graph_data = [2];
339346
graph.new_data(graph_data);
340347
step_model_inputs[0].checked = true;
@@ -372,7 +379,8 @@ <h3>Folder-Desk Data Array:</h3>
372379
model.nextStep();
373380
graph_data.push(model.averageFolders);
374381
if (show_visualization.checked) avalanche2d.displayFolderCanvas(canvas, model);
375-
if (show_graph.checked) graph.add_point(model.averageFolders);
382+
// if (show_graph.checked) graph.add_point(model.averageFolders);
383+
if (show_graph.checked) graph.add_canvas_point(model.averageFolders);
376384
if (show_data_table.checked) avalanche2d.displayFolderTable(folder_data, model);
377385
sample_time = +new Date();
378386
sample_duration = sample_time - last_sample_time;
@@ -397,7 +405,6 @@ <h3>Folder-Desk Data Array:</h3>
397405
modelStop()
398406
}
399407
};
400-
401408
});
402409
};
403410
</script>

src/grapher.js

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,23 @@
1515
graph.add_point = function(p) {
1616
add_point(p);
1717
};
18+
19+
graph.add_canvas_point = function(p) {
20+
add_canvas_point(p);
21+
};
22+
23+
graph.initialize_canvas = function() {
24+
initialize_canvas();
25+
};
26+
27+
graph.show_canvas = function() {
28+
show_canvas();
29+
};
30+
31+
graph.hide_canvas = function() {
32+
hide_canvas();
33+
};
34+
1835

1936
var size = [500, 350],
2037
padding = [20, 30, 20, 40], // top right bottom left
@@ -42,6 +59,10 @@
4259
downy = Math.NaN,
4360
dragged = null,
4461
selected = points[0];
62+
63+
var plot, gcanvas, gctx;
64+
65+
var chart = document.getElementById("chart");
4566

4667
var vis = d3.select("#chart").append("svg:svg")
4768
.attr("width", size[0] + padding[3] + padding[1])
@@ -70,6 +91,8 @@
7091
.attr("class", "line")
7192
.attr("d", line(points));
7293

94+
initialize_canvas();
95+
7396
// variables for speeding up dynamic plotting
7497
var line_path = vis.select("path")[0][0];
7598
var line_seglist = line_path.pathSegList;
@@ -118,23 +141,60 @@
118141
points.push(point);
119142
var newx = x.call(self, len, len);
120143
var newy = y.call(self, p, len);
144+
line_seglist.appendItem(line_path.createSVGPathSegLinetoAbs(newx, newy));
145+
};
146+
147+
function add_canvas_point(p) {
148+
var len = points.length;
149+
var oldx = x.call(self, len-1, len-1);
150+
var oldy = y.call(self, points[len-1].y, len-1);
151+
var point = { x: len, y: p };
152+
points.push(point);
153+
var newx = x.call(self, len, len);
154+
var newy = y.call(self, p, len);
155+
gctx.beginPath();
156+
gctx.moveTo(oldx, oldy);
157+
gctx.lineTo(newx, newy);
158+
gctx.closePath();
159+
gctx.stroke();
160+
// FIXME: FireFox bug
161+
};
162+
163+
function show_canvas() {
164+
gcanvas.style.zIndex = 100;
165+
};
121166

122-
// adding circle points with dom manipulation
123-
// var c2 = cpoint.cloneNode(false);
124-
// c2.setAttribute("cx", newx);
125-
// c2.setAttribute("cy", newy);
126-
// vis_node.appendChild(c2);
167+
function hide_canvas() {
168+
gcanvas.style.zIndex = -100;
169+
};
127170

128-
// adding circle points with d3
129-
// vis.append("svg:circle").attr('cx',newx).attr('cy',newy).attr('r',1)
130-
131-
// adding new line segments with dom manipulation
132-
line_seglist.appendItem(line_path.createSVGPathSegLinetoAbs(newx, newy));
171+
function initialize_canvas() {
172+
plot = {}
173+
plot.rect = chart.children[0].getElementsByTagName("rect")[0]
174+
plot.width = plot.rect.width['baseVal'].value
175+
plot.height = plot.rect.height['baseVal'].value
176+
plot.left = plot.rect.getCTM().e
177+
plot.top = plot.rect.getCTM().f
133178

134-
// adding new line segments with d3 and custom attribute generation
135-
// vis.select("path").attr("d", generate_path_attribute([point], x, y));
179+
gcanvas = document.createElement('canvas');
180+
chart.appendChild(gcanvas);
181+
gcanvas.style.position = 'absolute'
182+
gcanvas.width = plot.width;
183+
gcanvas.height = plot.height;
184+
gcanvas.offsetLeft = plot.left;
185+
gcanvas.offsetTop = plot.top;
186+
gcanvas.style.left = plot.left + 'px'
187+
gcanvas.style.top = plot.top + 'px'
188+
gctx = gcanvas.getContext( '2d' );
189+
gctx.globalCompositeOperation = "destination-atop";
190+
gctx.lineWidth = 1;
191+
gctx.fillStyle = "rgba(0,255,0, 0.05)";
192+
gctx.fillRect(0, 0, gcanvas.width, gcanvas.height);
193+
gctx.strokeStyle = "rgba(255,65,0, 1.0)";
194+
gcanvas.style.border = 'solid 1px red'
195+
gcanvas.style.zIndex = -100
136196
};
137-
197+
138198
function update() {
139199
var lines = vis.select("path").attr("d", line(points));
140200

stylesheets/style.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ fieldset {
5050
background-color: #f7f2c5;
5151
width: 560px;
5252
height: 400px;
53-
border: solid 1px #cccccc; }
53+
border: solid 1px #cccccc;
54+
position: relative; }
5455

5556
.line {
5657
fill: none;

0 commit comments

Comments
 (0)