Skip to content

Commit bf989ad

Browse files
committed
checkpoint
1 parent 0929e9b commit bf989ad

File tree

3 files changed

+121
-107
lines changed

3 files changed

+121
-107
lines changed

web-workers/offscreen-canvas-worker/index.html

Lines changed: 58 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,93 +7,104 @@
77
</head>
88
<body>
99
<header>
10-
<div id="support-div">Your browser does not support OffscreenCanvas</div>
11-
</header>
12-
13-
<main>
14-
<h2>Simulate a heavy process:</h2>
10+
<h1>OffscreenCanvas and worker threads</h1>
11+
<p>This example has two canvases with incrementing counters.</p>
1512

16-
<button id="main-button" onclick="slowMainThread()">Canvas A</button>
17-
<button id="worker-button" onclick="slowdownWorker()">Canvas B</button>
13+
<p>
14+
Canvas A is being drawn to on the main thread. Canvas B uses an
15+
OffscreenCanvas so that we can draw to it in a worker thread. The
16+
purpose of this example is to show how a worker thread can keep the rest
17+
of our UI responsive.
18+
</p>
1819

19-
<div class="ui-example">
20-
<button>Hover example</button><button>Hover example</button
21-
><button>Hover example</button><button>Hover example</button>
22-
</div>
20+
<p>
21+
The button below each canvas creates <b>blocking work</b> on either the
22+
main thread (Canvas A) or a worker thread (Canvas B). When a thread is
23+
blocked, the canvas' counter in that thread is blocked.
24+
</p>
25+
</header>
2326

24-
<h2>Counters:</h2>
25-
<div class="visualisation">
27+
<main>
28+
<div class="canvases">
2629
<div>
2730
<span class="canvas-title">Canvas A</span>
28-
<canvas id="canvas main" width="400" height="400"></canvas>
31+
<canvas id="canvas main" width="200" height="200"></canvas>
32+
<div>
33+
<button id="main-button" onclick="slowMainThread()">
34+
Main thread
35+
</button>
36+
</div>
2937
</div>
3038
<div>
3139
<span class="canvas-title">Canvas B</span>
32-
<canvas id="canvas worker" width="400" height="400"></canvas>
40+
<canvas id="canvas worker" width="200" height="200"></canvas>
41+
42+
<div>
43+
<button id="worker-button" onclick="slowdownWorker()">
44+
Worker thread
45+
</button>
46+
</div>
3347
</div>
3448
</div>
49+
<div id="canvas-description">
50+
<p>
51+
<b>When the main thread is blocked</b>, all UI elements are frozen.
52+
The hover effect on all buttons is affected:
53+
</p>
54+
<button>Example button</button>
55+
<p>
56+
<b>When the worker thread is blocked</b>, the main thread is free to
57+
do work such as the element hover effects and animations. Blocking the
58+
worker thread will still prevent Canvas B's counter from being
59+
updated, but the UI stays responsive while this happens.
60+
</p>
61+
</div>
3562
</main>
3663

3764
<script>
38-
document
39-
.querySelector("#support-div")
40-
.classList.add(
41-
"OffscreenCanvas" in window ? "supported" : "not-supported"
42-
);
43-
44-
document.querySelector("#support-div").innerHTML =
45-
"OffscreenCanvas" in window
46-
? "Your browser supports the OffscreenCanvas API "
47-
: "Your browser does not support OffscreenCanvas";
48-
4965
const requestAnimationFrame = window.requestAnimationFrame;
5066

51-
// Init Canvas A (running on the current page)
5267
const canvasA = document.getElementById("canvas main");
53-
const indicator = document.getElementById("indicator");
54-
const ctxA = canvasA.getContext("2d");
68+
const canvasB = document.getElementById("canvas worker");
5569

70+
const ctxA = canvasA.getContext("2d");
5671
const canvasWidth = ctxA.width;
5772
const canvasHeight = ctxA.height;
5873

59-
// Setup the counter for Canvas A
74+
// Create a counter for Canvas A
6075
let counter = 0;
6176
setInterval(function () {
6277
redrawCanvasA();
6378
counter++;
6479
}, 100);
6580

66-
// Redraw Canvas A text
81+
// Redraw Canvas A counter
6782
function redrawCanvasA() {
6883
ctxA.clearRect(0, 0, canvasA.width, canvasA.height);
69-
ctxA.font = "16px Verdana";
84+
ctxA.font = "24px Verdana";
7085
ctxA.textAlign = "center";
71-
ctxA.fillText(
72-
"Counter: " + counter,
73-
canvasA.width / 2,
74-
canvasA.height / 2
75-
);
86+
ctxA.fillText(counter, canvasA.width / 2, canvasA.height / 2);
7687
}
7788

78-
// Using the OffscreenCanvas API and starting the worker
79-
var cWorker = document
80-
.getElementById("canvas worker")
81-
.transferControlToOffscreen();
82-
var worker = new Worker("worker.js");
83-
worker.postMessage({ canvas: cWorker }, [cWorker]);
84-
85-
// Fibonacci function to add some delay to the thread
89+
// This function creates heavy (blocking) work on a thread
8690
function fibonacci(num) {
8791
if (num <= 1) return 1;
8892
return fibonacci(num - 1) + fibonacci(num - 2);
8993
}
9094

95+
// Call our Fibonacci function on the main thread
9196
function slowMainThread() {
9297
fibonacci(42);
9398
}
9499

95-
// Initiate the slowing down of Canvas B
96-
// By sending a message to the worker
100+
// Set up a worker thread to render Canvas B
101+
const worker = new Worker("worker.js");
102+
103+
// Use the OffscreenCanvas API and send to the worker thread
104+
const canvasWorker = canvasB.transferControlToOffscreen();
105+
worker.postMessage({ canvas: canvasWorker }, [canvasWorker]);
106+
107+
// A 'slowDown' message we can catch in the worker to start heavy work
97108
function slowdownWorker() {
98109
worker.postMessage("slowDown");
99110
}

web-workers/offscreen-canvas-worker/style.css

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,85 @@
11
html,
22
body {
3-
margin: 0;
4-
padding: 0;
5-
background: whitesmoke;
6-
font-family: Arial, Helvetica, sans-serif;
3+
font-family: sans-serif;
4+
margin: 2rem;
75
}
86

9-
#support-div {
10-
font-size: 2em;
11-
text-align: center;
12-
min-height: 1em;
13-
line-height: 1.5em;
7+
main {
8+
display: flex;
9+
align-content: left;
10+
justify-content: left;
11+
flex-direction: column;
12+
flex-wrap: wrap;
13+
text-align: left;
14+
margin-bottom: 4rem;
1415
}
1516

16-
.supported {
17-
background: lightgreen;
17+
header {
18+
font-size: 1em;
19+
min-height: 1em;
20+
line-height: 1.5em;
21+
margin: 1rem;
22+
max-width: 50%;
1823
}
1924

20-
.not-supported {
21-
background: crimson;
25+
button, canvas {
26+
border-radius: 10px;
2227
}
2328

2429
canvas {
25-
border: 1px solid black;
26-
background: #fff;
27-
}
28-
29-
.canvas-title {
30-
display: block;
31-
text-align: center;
32-
font-size: 1.4em;
33-
font-weight: bold;
34-
margin-bottom: 20px;
35-
}
36-
37-
main,
38-
footer {
39-
display: flex;
40-
align-content: center;
41-
justify-content: center;
42-
flex-direction: column;
43-
flex-wrap: wrap;
44-
text-align: center;
45-
}
46-
47-
ul {
48-
list-style: none;
30+
border: 2px solid black;
31+
margin: 2rem;
4932
}
5033

5134
button {
52-
background: #acacac;
35+
background: #797676;
5336
padding: 10px;
5437
margin: 10px;
5538
border: 0;
56-
border-radius: 10px;
5739
color: white;
5840
font-size: 1em;
41+
max-width: 150px;
42+
}
43+
44+
/* Hover effect for buttons */
45+
button:hover,
46+
canvas:hover {
47+
background: rgb(242, 134, 102);
48+
transition: transform 0.5s;
49+
transform: scale(1.3, 1.3);
50+
color: black;
51+
}
52+
53+
#canvas-description {
54+
max-width: 50%;
55+
text-align: center;
56+
}
57+
58+
#canvas-description>p {
59+
text-align: left;
5960
}
6061

61-
button:hover {
62-
background: rgb(235, 86, 41);
62+
.ui-example {
63+
margin: 2rem;
6364
}
6465

6566
.ui-example button:hover {
66-
transition: transform 0.5s;
67+
transition: transform 0.5s;
6768
transform: scale(1.3, 1.3);
69+
}
6870

71+
.canvas-title {
72+
display: block;
73+
font-size: 1.4em;
74+
font-weight: bold;
75+
margin-bottom: 1rem;
6976
}
7077

71-
.visualisation {
78+
.canvases {
79+
text-align: center;
7280
display: flex;
7381
flex-wrap: wrap;
74-
justify-content: center;
75-
align-content: center;
82+
justify-content: left;
83+
align-content: left;
84+
padding: 2rem;
7685
}
77-
78-
.visualisation>div {
79-
margin: 5px;
80-
}
Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
var canvasB = null;
2-
var ctxWorker = null;
1+
let canvasB = null;
2+
let ctxWorker = null;
33

44
// Waiting to receive the OffScreenCanvas
55
self.onmessage = function (e) {
6-
if (typeof e.data == "string") {
6+
if (e.data === "slowDown") {
7+
// canvasB.style.border = "2px solid red";
78
fibonacci(42);
89
} else {
910
canvasB = e.data.canvas;
10-
ctxWorker = canvasB.getContext("2d");
1111

12+
ctxWorker = canvasB.getContext("2d");
13+
// canvasB.style.border = "1px solid black";
1214
startCounting();
1315
}
1416
};
@@ -20,7 +22,7 @@ function fibonacci(num) {
2022
}
2123

2224
// Start the counter for Canvas B
23-
var counter = 0;
25+
let counter = 0;
2426
function startCounting() {
2527
setInterval(function () {
2628
redrawCanvasB();
@@ -31,11 +33,7 @@ function startCounting() {
3133
// Redraw Canvas B text
3234
function redrawCanvasB() {
3335
ctxWorker.clearRect(0, 0, canvasB.width, canvasB.height);
34-
ctxWorker.font = "16px Verdana";
36+
ctxWorker.font = "24px Verdana";
3537
ctxWorker.textAlign = "center";
36-
ctxWorker.fillText(
37-
"Counter: " + counter,
38-
canvasB.width / 2,
39-
canvasB.height / 2
40-
);
38+
ctxWorker.fillText(counter, canvasB.width / 2, canvasB.height / 2);
4139
}

0 commit comments

Comments
 (0)