Skip to content

Commit 61fe0b9

Browse files
committed
Merge branch 'new-web-worker-demo' of git://github.com/joelrbrandt/html5demos
2 parents b7fe32f + e3bf525 commit 61fe0b9

File tree

5 files changed

+198
-129
lines changed

5 files changed

+198
-129
lines changed

demos/worker.html

+38-82
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,38 @@
1-
<title>Worker</title>
2-
<article>
3-
<p>Canvas is running whilst an prime number finder runs in a worker</p>
4-
<p>Prime found: <span id="status">0</span></p>
5-
<div><input type="button" value="start worker" id="toggleWorker" /></div>
6-
</article>
7-
<script>
8-
9-
buildSpinner({ x : 50, y : 50, size : 20, degrees : 30 });
10-
11-
var w = new Worker('/js/cruncher.js');
12-
13-
addEvent(document.getElementById('toggleWorker'), 'click', function () {
14-
w.postMessage('');
15-
});
16-
17-
w.onmessage = function (event) {
18-
if (event.data && (event.data+"").match(/^log:/i)) {
19-
console.log(event.data.match(/^log:\s*(.*)/)[1]);
20-
} else {
21-
document.querySelector('#status').innerHTML = event.data;
22-
}
23-
}
24-
25-
function buildSpinner(data) {
26-
27-
var canvas = document.createElement('canvas');
28-
canvas.height = 100;
29-
canvas.width = 300;
30-
document.querySelector('article').appendChild(canvas);
31-
var ctx = canvas.getContext("2d"),
32-
i = 0, degrees = data.degrees, loops = 0, degreesList = [];
33-
34-
for (i = 0; i < degrees; i++) {
35-
degreesList.push(i);
36-
}
37-
38-
// reset
39-
i = 0;
40-
41-
// so I can kill it later
42-
window.canvasTimer = setInterval(draw, 1000/degrees);
43-
44-
function reset() {
45-
ctx.clearRect(0,0,100,100); // clear canvas
46-
47-
var left = degreesList.slice(0, 1);
48-
var right = degreesList.slice(1, degreesList.length);
49-
degreesList = right.concat(left);
50-
}
51-
52-
function draw() {
53-
var c, s, e;
54-
55-
var d = 0;
56-
57-
if (i == 0) {
58-
reset();
59-
}
60-
61-
ctx.save();
62-
63-
d = degreesList[i];
64-
c = Math.floor(255/degrees*i);
65-
ctx.strokeStyle = 'rgb(' + c + ', ' + c + ', ' + c + ')';
66-
ctx.lineWidth = data.size;
67-
ctx.beginPath();
68-
s = Math.floor(360/degrees*(d));
69-
e = Math.floor(360/degrees*(d+1)) - 1;
70-
71-
ctx.arc(data.x, data.y, data.size, (Math.PI/180)*s, (Math.PI/180)*e, false);
72-
ctx.stroke();
73-
74-
ctx.restore();
75-
76-
i++;
77-
if (i >= degrees) {
78-
i = 0;
79-
}
80-
}
81-
}
82-
</script>
1+
<html>
2+
<head>
3+
<title>Worker</title>
4+
<style>
5+
body {
6+
font-family: sans-serif;
7+
}
8+
9+
#status {
10+
height: 200px;
11+
max-height: 200px;
12+
border: thin solid black;
13+
overflow-y: scroll;
14+
}
15+
16+
#square {
17+
position: absolute;
18+
left: 0px;
19+
top: 0px;
20+
width: 75px;
21+
height: 75px;
22+
background-color: rgba(0, 0, 220, 0.3);
23+
z-index: -1;
24+
}
25+
</style>
26+
</head>
27+
<body>
28+
<h1>Web Worker Demo</h1>
29+
<p>Works in Chrome, Safari, and Firefox. Web worker portion works in Opera.</p>
30+
<p>Use arrow keys to change the direction of the animated square. The square is animated with <em>requestAnimationFrame</em>.</p>
31+
<p>Click the button below to start or stop the worker.</p>
32+
<div><input type="button" value="start worker" id="toggleWorker" /></div>
33+
<h2>Messages from Worker:</h2>
34+
<div id="status"></div>
35+
<div id="square"></div>
36+
<script src="../js/worker-main.js"></script>
37+
</body>
38+
</html>

js/cruncher.js

-24
This file was deleted.

js/worker-cruncher.js

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, browser: true */
2+
/*global postMessage, addEventListener */
3+
4+
(function () {
5+
"use strict";
6+
7+
var WHEN_TO_STOP = 10000000;
8+
var COMPUTE_BLOCK_SIZE = 1000000;
9+
10+
var running = false;
11+
var count = 0;
12+
13+
// We have to compute in blocks of ~1 second of computation in order to make sure
14+
// that we read our message queue occasionally. Worker threads are not preemptive
15+
// (like all JS), so if we don't pause computation to read the message queue, we'll
16+
// be unresponsive to user requests.
17+
function compute(start) {
18+
var n = start;
19+
var i, hasDivisor;
20+
21+
if (!running) { // got a message to stop before this call to compute
22+
postMessage("Stopped!");
23+
} else {
24+
while (n < start + COMPUTE_BLOCK_SIZE) {
25+
hasDivisor = false;
26+
for (i = 2; i <= Math.sqrt(n); i += 1) {
27+
if (n % i === 0) {
28+
hasDivisor = true;
29+
break;
30+
}
31+
}
32+
if (!hasDivisor) {
33+
// found a prime!
34+
count++;
35+
}
36+
n += 1;
37+
}
38+
39+
if (n < WHEN_TO_STOP) {
40+
// allow for event loop to actually forward messages to the worker
41+
setTimeout(function () { compute(n); }, 1);
42+
} else {
43+
// we reached the end
44+
running = false;
45+
postMessage("Done!");
46+
}
47+
}
48+
49+
// Finally, always report how many primes we've found so far
50+
postMessage("Found " + count + " primes between 2 and " + (n - 1));
51+
52+
}
53+
54+
addEventListener('message', function (event) {
55+
// doesn't matter what the message is, just toggle the worker
56+
if (running === false) {
57+
postMessage("Starting...");
58+
count = 0;
59+
running = true;
60+
compute(1);
61+
} else {
62+
postMessage("Stopping...");
63+
running = false;
64+
}
65+
});
66+
67+
68+
}());

js/worker-main.js

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, browser: true */
2+
/*global Worker */
3+
4+
(function () {
5+
"use strict";
6+
7+
var SQUARE_SIZE = 75;
8+
var MOVEMENT_STEP = 3;
9+
10+
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
11+
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
12+
13+
14+
// Set up the worker
15+
var running = false;
16+
var statusDiv = document.getElementById('status');
17+
var button = document.getElementById('toggleWorker');
18+
var worker = new Worker('../js/worker-cruncher.js'); // path is relative to the main HTML file
19+
worker.addEventListener('message', function (event) {
20+
var currentStatus = statusDiv.innerHTML;
21+
statusDiv.innerHTML = "<p>" + event.data + "</p>" + currentStatus;
22+
if (event.data === "Done!") {
23+
running = false;
24+
button.value = "start worker";
25+
}
26+
});
27+
28+
button.onclick = function () {
29+
running = !running;
30+
if (running) {
31+
statusDiv.innerHTML = "";
32+
button.value = "stop worker";
33+
} else {
34+
button.value = "start worker";
35+
}
36+
worker.postMessage('');
37+
38+
};
39+
40+
41+
// Set up the animated square
42+
var square = document.getElementById('square');
43+
var direction = 39; // right
44+
45+
square.style.top = 0;
46+
square.style.left = 20;
47+
square.style.height = SQUARE_SIZE;
48+
square.style.width = SQUARE_SIZE;
49+
50+
function moveSquare() {
51+
var left = parseInt(square.style.left, 10);
52+
var top = parseInt(square.style.top, 10);
53+
var right = left + SQUARE_SIZE;
54+
var bottom = top + SQUARE_SIZE;
55+
56+
switch (direction) {
57+
case 37: // left
58+
if (left > 0) {
59+
square.style.left = left - MOVEMENT_STEP;
60+
}
61+
break;
62+
case 38: // up
63+
if (top > 0) {
64+
square.style.top = top - MOVEMENT_STEP;
65+
}
66+
break;
67+
case 39: //right
68+
if (right < document.documentElement.clientWidth) {
69+
square.style.left = left + MOVEMENT_STEP;
70+
}
71+
break;
72+
case 40: // down
73+
if (bottom < document.documentElement.clientHeight) {
74+
square.style.top = top + MOVEMENT_STEP;
75+
}
76+
break;
77+
default:
78+
break;
79+
}
80+
requestAnimationFrame(moveSquare);
81+
}
82+
83+
window.onkeydown = function (event) {
84+
if (event.keyCode >= 37 && event.keyCode <= 40) { // is an arrow key
85+
direction = event.keyCode;
86+
}
87+
};
88+
89+
// start the square animating
90+
requestAnimationFrame(moveSquare);
91+
92+
}());

js/worker.js

-23
This file was deleted.

0 commit comments

Comments
 (0)