Merge branch 'new-web-worker-demo' of git://github.com/joelrbrandt/html5demos
This commit is contained in:
commit
61fe0b95f6
|
@ -1,82 +1,38 @@
|
|||
<title>Worker</title>
|
||||
<article>
|
||||
<p>Canvas is running whilst an prime number finder runs in a worker</p>
|
||||
<p>Prime found: <span id="status">0</span></p>
|
||||
<div><input type="button" value="start worker" id="toggleWorker" /></div>
|
||||
</article>
|
||||
<script>
|
||||
|
||||
buildSpinner({ x : 50, y : 50, size : 20, degrees : 30 });
|
||||
|
||||
var w = new Worker('/js/cruncher.js');
|
||||
|
||||
addEvent(document.getElementById('toggleWorker'), 'click', function () {
|
||||
w.postMessage('');
|
||||
});
|
||||
|
||||
w.onmessage = function (event) {
|
||||
if (event.data && (event.data+"").match(/^log:/i)) {
|
||||
console.log(event.data.match(/^log:\s*(.*)/)[1]);
|
||||
} else {
|
||||
document.querySelector('#status').innerHTML = event.data;
|
||||
}
|
||||
}
|
||||
|
||||
function buildSpinner(data) {
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.height = 100;
|
||||
canvas.width = 300;
|
||||
document.querySelector('article').appendChild(canvas);
|
||||
var ctx = canvas.getContext("2d"),
|
||||
i = 0, degrees = data.degrees, loops = 0, degreesList = [];
|
||||
|
||||
for (i = 0; i < degrees; i++) {
|
||||
degreesList.push(i);
|
||||
}
|
||||
|
||||
// reset
|
||||
i = 0;
|
||||
|
||||
// so I can kill it later
|
||||
window.canvasTimer = setInterval(draw, 1000/degrees);
|
||||
|
||||
function reset() {
|
||||
ctx.clearRect(0,0,100,100); // clear canvas
|
||||
|
||||
var left = degreesList.slice(0, 1);
|
||||
var right = degreesList.slice(1, degreesList.length);
|
||||
degreesList = right.concat(left);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
var c, s, e;
|
||||
|
||||
var d = 0;
|
||||
|
||||
if (i == 0) {
|
||||
reset();
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
|
||||
d = degreesList[i];
|
||||
c = Math.floor(255/degrees*i);
|
||||
ctx.strokeStyle = 'rgb(' + c + ', ' + c + ', ' + c + ')';
|
||||
ctx.lineWidth = data.size;
|
||||
ctx.beginPath();
|
||||
s = Math.floor(360/degrees*(d));
|
||||
e = Math.floor(360/degrees*(d+1)) - 1;
|
||||
|
||||
ctx.arc(data.x, data.y, data.size, (Math.PI/180)*s, (Math.PI/180)*e, false);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.restore();
|
||||
|
||||
i++;
|
||||
if (i >= degrees) {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<html>
|
||||
<head>
|
||||
<title>Worker</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#status {
|
||||
height: 200px;
|
||||
max-height: 200px;
|
||||
border: thin solid black;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#square {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
background-color: rgba(0, 0, 220, 0.3);
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Web Worker Demo</h1>
|
||||
<p>Works in Chrome, Safari, and Firefox. Web worker portion works in Opera.</p>
|
||||
<p>Use arrow keys to change the direction of the animated square. The square is animated with <em>requestAnimationFrame</em>.</p>
|
||||
<p>Click the button below to start or stop the worker.</p>
|
||||
<div><input type="button" value="start worker" id="toggleWorker" /></div>
|
||||
<h2>Messages from Worker:</h2>
|
||||
<div id="status"></div>
|
||||
<div id="square"></div>
|
||||
<script src="../js/worker-main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
var running = false;
|
||||
|
||||
onmessage = function (event) {
|
||||
// doesn't matter what the message is, just toggle the worker
|
||||
if (running == false) {
|
||||
running = true;
|
||||
run();
|
||||
} else {
|
||||
running = false;
|
||||
}
|
||||
};
|
||||
|
||||
function run() {
|
||||
var n = 1;
|
||||
search: while (running) {
|
||||
n += 1;
|
||||
for (var i = 2; i <= Math.sqrt(n); i += 1)
|
||||
if (n % i == 0)
|
||||
continue search;
|
||||
// found a prime!
|
||||
postMessage(n);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, browser: true */
|
||||
/*global postMessage, addEventListener */
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var WHEN_TO_STOP = 10000000;
|
||||
var COMPUTE_BLOCK_SIZE = 1000000;
|
||||
|
||||
var running = false;
|
||||
var count = 0;
|
||||
|
||||
// We have to compute in blocks of ~1 second of computation in order to make sure
|
||||
// that we read our message queue occasionally. Worker threads are not preemptive
|
||||
// (like all JS), so if we don't pause computation to read the message queue, we'll
|
||||
// be unresponsive to user requests.
|
||||
function compute(start) {
|
||||
var n = start;
|
||||
var i, hasDivisor;
|
||||
|
||||
if (!running) { // got a message to stop before this call to compute
|
||||
postMessage("Stopped!");
|
||||
} else {
|
||||
while (n < start + COMPUTE_BLOCK_SIZE) {
|
||||
hasDivisor = false;
|
||||
for (i = 2; i <= Math.sqrt(n); i += 1) {
|
||||
if (n % i === 0) {
|
||||
hasDivisor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasDivisor) {
|
||||
// found a prime!
|
||||
count++;
|
||||
}
|
||||
n += 1;
|
||||
}
|
||||
|
||||
if (n < WHEN_TO_STOP) {
|
||||
// allow for event loop to actually forward messages to the worker
|
||||
setTimeout(function () { compute(n); }, 1);
|
||||
} else {
|
||||
// we reached the end
|
||||
running = false;
|
||||
postMessage("Done!");
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, always report how many primes we've found so far
|
||||
postMessage("Found " + count + " primes between 2 and " + (n - 1));
|
||||
|
||||
}
|
||||
|
||||
addEventListener('message', function (event) {
|
||||
// doesn't matter what the message is, just toggle the worker
|
||||
if (running === false) {
|
||||
postMessage("Starting...");
|
||||
count = 0;
|
||||
running = true;
|
||||
compute(1);
|
||||
} else {
|
||||
postMessage("Stopping...");
|
||||
running = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}());
|
|
@ -0,0 +1,92 @@
|
|||
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, browser: true */
|
||||
/*global Worker */
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var SQUARE_SIZE = 75;
|
||||
var MOVEMENT_STEP = 3;
|
||||
|
||||
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
|
||||
|
||||
|
||||
// Set up the worker
|
||||
var running = false;
|
||||
var statusDiv = document.getElementById('status');
|
||||
var button = document.getElementById('toggleWorker');
|
||||
var worker = new Worker('../js/worker-cruncher.js'); // path is relative to the main HTML file
|
||||
worker.addEventListener('message', function (event) {
|
||||
var currentStatus = statusDiv.innerHTML;
|
||||
statusDiv.innerHTML = "<p>" + event.data + "</p>" + currentStatus;
|
||||
if (event.data === "Done!") {
|
||||
running = false;
|
||||
button.value = "start worker";
|
||||
}
|
||||
});
|
||||
|
||||
button.onclick = function () {
|
||||
running = !running;
|
||||
if (running) {
|
||||
statusDiv.innerHTML = "";
|
||||
button.value = "stop worker";
|
||||
} else {
|
||||
button.value = "start worker";
|
||||
}
|
||||
worker.postMessage('');
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Set up the animated square
|
||||
var square = document.getElementById('square');
|
||||
var direction = 39; // right
|
||||
|
||||
square.style.top = 0;
|
||||
square.style.left = 20;
|
||||
square.style.height = SQUARE_SIZE;
|
||||
square.style.width = SQUARE_SIZE;
|
||||
|
||||
function moveSquare() {
|
||||
var left = parseInt(square.style.left, 10);
|
||||
var top = parseInt(square.style.top, 10);
|
||||
var right = left + SQUARE_SIZE;
|
||||
var bottom = top + SQUARE_SIZE;
|
||||
|
||||
switch (direction) {
|
||||
case 37: // left
|
||||
if (left > 0) {
|
||||
square.style.left = left - MOVEMENT_STEP;
|
||||
}
|
||||
break;
|
||||
case 38: // up
|
||||
if (top > 0) {
|
||||
square.style.top = top - MOVEMENT_STEP;
|
||||
}
|
||||
break;
|
||||
case 39: //right
|
||||
if (right < document.documentElement.clientWidth) {
|
||||
square.style.left = left + MOVEMENT_STEP;
|
||||
}
|
||||
break;
|
||||
case 40: // down
|
||||
if (bottom < document.documentElement.clientHeight) {
|
||||
square.style.top = top + MOVEMENT_STEP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
requestAnimationFrame(moveSquare);
|
||||
}
|
||||
|
||||
window.onkeydown = function (event) {
|
||||
if (event.keyCode >= 37 && event.keyCode <= 40) { // is an arrow key
|
||||
direction = event.keyCode;
|
||||
}
|
||||
};
|
||||
|
||||
// start the square animating
|
||||
requestAnimationFrame(moveSquare);
|
||||
|
||||
}());
|
23
js/worker.js
23
js/worker.js
|
@ -1,23 +0,0 @@
|
|||
var running = false;
|
||||
var ctr = 0;
|
||||
|
||||
function log(s) {
|
||||
postMessage('log:' + s);
|
||||
}
|
||||
|
||||
onmessage = function (event) {
|
||||
// doesn't matter what the message is, just toggle the worker
|
||||
if (running == false) {
|
||||
running = true;
|
||||
run();
|
||||
} else {
|
||||
running = false;
|
||||
}
|
||||
};
|
||||
|
||||
function run() {
|
||||
while (running) {
|
||||
postMessage(ctr);
|
||||
ctr++;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue