I just wanted to see how webworkers worked and if they weren't really blocking the main loop.
I took an implementation for calculating the nth decimal of PI, and run some animations on the main loop. I keep the time of each iteration and build a graph with it. You can notice some jitter on the start, it should be the spawning of the thread. You can notice that complexity of the implementation by looking at the graph
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<title>Basic Axes</title>
<script src="https://d3js.org/d3.v3.min.js"></script>
</head>
<style>
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
font: 10px sans-serif;
}
.axis .grid-line{
stroke: black;
shape-rendering: crispEdges;
stroke-opacity: .2;
}
.line{
fill: none;
stroke: steelblue;
stroke-width: 2;
}
text {
font: bold 48px monospace;
}
.enter {
fill: green;
}
</style>
<body>
</body>
<script>
var width = "400px";
var height = "500px";
var timeSeries = [{x:0,y:0}];
var clock = Date.now();
var myWorker = new Worker("piWorker.js");
var PIDIV = d3.select("body").append("div")
.style("position","absolute")
.style("width", width)
.style("height", height)
.style("font-size","10px");
myWorker.postMessage({what:"start"});
myWorker.onmessage = function (oEvent) {
var now = Date.now();
var current = oEvent.data.current;
timeSeries.push({x:current,y:now-clock});
clock = now;
var pi = oEvent.data.result;
PIDIV.text(pi);
myWorker.postMessage({what:"next"});
/*if (current>10)
{
chart.x(d3.scale.linear().domain([0,90]))
chart.updateAxis();
}*/
chart.render();
};
var chart = lineChart()
.x(d3.scale.linear().domain([0, 300]))
.y(d3.scale.linear().domain([0, 500]));
chart.addSeries(timeSeries);
//add an animation to pile main loop
var width2 = 400,
height2 = 360;
var svg2 = d3.select("body").append("svg")
.attr("width", width2)
.attr("height", height2)
.style("position","absolute")
.style("top","100px");
svg2.append("g")
.attr("transform", "translate(" + (width2 / 2) + "," + (height2 / 2) + ")")
.append("path")
.attr("d", d3.svg.symbol().type("cross").size(10000))
.each(cycle);
svg2.append("text").attr("x",10).attr("y",50).attr("class","enter").text("WORKING....")
function cycle() {
d3.select(this).transition()
.duration(3000)
.attrTween("transform", function() { return d3.interpolateString("rotate(0)", "rotate(720)"); })
.each("end", cycle);
}
function lineChart() {
var _chart = {};
var _width=600, _height=300,
_margins = {top:30, left:30, right:30, bottom:30},
_x, _y,
_data = [],
_colors = d3.scale.category10(),
_svg,
_bodyG,
_line;
var _xAxis, _yAxis;
//define SVG element
_chart.render = function() {
if (!_svg) {
_svg = d3.select("body").append("svg").attr("height",_height).attr("width",_width);
// little cheat
_svg.style("position","absolute").style("left","410px");
renderAxes(_svg);
defineBodyClip(_svg);
}
renderBody(_svg);
}
_chart.updateAxis = function () {
updateAxis(_svg);
}
function updateAxis() {
//var t = svg.transition().duration(10);
d3.select("g .x.axis").call(_xAxis);
}
function renderAxes(svg) {
var axesG = svg.append("g").attr("class","axes");
renderXAxis(axesG);
renderYAxis(axesG);
}
function renderXAxis(axesG) {
_xAxis = d3.svg.axis()
.scale(_x.range([0, quadrantWidth()]))
.orient("bottom");
axesG.append("g")
.attr("class", "x axis")
.attr("transform", function () {
return "translate(" + xStart() + "," + yStart() + ")";
})
.call(_xAxis);
d3.selectAll("g.x g.tick")
.append("line")
.classed("grid-line",true)
.attr("x1",0)
.attr("y1",0)
.attr("x2",0)
.attr("y2", - quadrantHeight());
}
function renderYAxis(axesG) {
_yAxis = d3.svg.axis()
.scale(_y.range([quadrantHeight(), 0]))
.orient("left");
axesG.append("g")
.attr("class", "y axis")
.attr("transform", function () {
return "translate(" + xStart() + "," + yEnd() + ")";
})
.call(_yAxis);
d3.selectAll("g.y g.tick")
.append("line")
.classed("grid-line", true)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", quadrantWidth())
.attr("y2", 0);
}
//SVG clip path defines the drawing zone
// defs define shapes that an be later used with <use> tag
function defineBodyClip(svg) {
var padding = 5;
svg.append("defs")
.append("clipPath")
.attr("id","body-clip")
.append("rect")
.attr("x",0-padding)
.attr("y",0)
.attr("width",quadrantWidth()+2*padding)
.attr("height",quadrantHeight());
}
function renderBody(svg) { // <-2D
if (!_bodyG)
_bodyG = svg.append("g")
.attr("class", "body")
.attr("transform", "translate("
+ xStart() + ","
+ yEnd() + ")") // <-2E
.attr("clip-path", "url(#body-clip)");
// the body of the graph has clip path defined
// padding of the clip path is used to let the point overflows the quadrant
// they would be clipped if they was nothing
renderLines();
renderDots();
}
function renderLines() {
_line = d3.svg.line() //<-4A
.x(function (d) { return _x(d.x); })
.y(function (d) { return _y(d.y); });
_bodyG.selectAll("path.line")
.data(_data)
.enter() //<-4B
.append("path")
.style("stroke", function (d, i) {
return _colors(i); //<-4C
})
.attr("class", "line");
_bodyG.selectAll("path.line")
.data(_data)
.transition() //<-4D
.attr("d", function (d) { return _line(d); });
}
function renderDots() {
_data.forEach(function (list, i) {
_bodyG.selectAll("circle._" + i) //<-4E
.data(list)
.enter()
.append("circle")
.attr("class", "dot _" + i)
.attr("r",0);
_bodyG.selectAll("circle._" + i)
.data(list)
.style("stroke", function (d) {
return _colors(i); //<-4F
})
.transition(1000) //<-4G
.attr("cx", function (d) { return _x(d.x); })
.attr("cy", function (d) { return _y(d.y); })
.attr("r", 2);
});
}
function xStart() {
return _margins.left;
}
function yStart() {
return _height - _margins.bottom;
}
function xEnd() {
return _width - _margins.right;
}
function yEnd() {
return _margins.top;
}
//quadrant is where graph is draws
function quadrantWidth() {
return _width - _margins.left - _margins.right;
}
function quadrantHeight() {
return _height - _margins.top - _margins.bottom;
}
//accessor
_chart.width = function (w) {
if (!arguments.length) return _width;
_width = w;
return _chart;
};
_chart.height = function (h) { // <-1C
if (!arguments.length) return _height;
_height = h;
return _chart;
};
_chart.margins = function (m) {
if (!arguments.length) return _margins;
_margins = m;
return _chart;
};
_chart.colors = function (c) {
if (!arguments.length) return _colors;
_colors = c;
return _chart;
};
_chart.x = function (x) {
if (!arguments.length) return _x;
_x = x;
return _chart;
};
_chart.y = function (y) {
if (!arguments.length) return _y;
_y = y;
return _chart;
};
_chart.addSeries = function (series) { // <-1D
_data.push(series);
return _chart;
};
return _chart; // <-1E
}
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js