Skip to content

Commit 3eb0169

Browse files
authored
Fix DedicatedWorkerGlobalScope examples with correct time handling (#40953)
1 parent 4b20a85 commit 3eb0169

2 files changed

Lines changed: 100 additions & 27 deletions

File tree

  • files/en-us/web/api/dedicatedworkerglobalscope

files/en-us/web/api/dedicatedworkerglobalscope/cancelanimationframe/index.md

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,54 +34,91 @@ None ({{jsxref("undefined")}}).
3434

3535
## Examples
3636

37-
On the main thread, we start by transferring the control of a {{HTMLElement("canvas")}} element to an {{domxref("OffscreenCanvas")}}, using {{domxref("HTMLCanvasElement.transferControlToOffscreen()")}} and send to a message to `"start"` its work to the worker, with the offscreen canvas:
37+
Here's a complete example showing how to use `requestAnimationFrame()` in a dedicated worker with an `OffscreenCanvas`.
38+
39+
The HTML should contain:
40+
41+
```html
42+
<canvas width="100" height="100"></canvas>
43+
```
44+
45+
It should link to the following JavaScript:
3846

3947
```js
48+
const worker = new Worker("worker.js");
49+
50+
// Transfer canvas control to the worker
4051
const offscreenCanvas = document
4152
.querySelector("canvas")
4253
.transferControlToOffscreen();
4354

55+
// Start the animation
4456
worker.postMessage(
4557
{
4658
type: "start",
4759
canvas: offscreenCanvas,
4860
},
4961
[offscreenCanvas],
5062
);
63+
64+
// Stop the animation after 5 seconds
65+
setTimeout(() => {
66+
worker.postMessage({
67+
type: "stop",
68+
});
69+
}, 5000);
5170
```
5271

53-
When receiving the `"start"` message, the worker starts the animation, moving the rectangle from left to right. Upon reception of a `"stop"` message, it will stop the animation.
72+
**worker.js:**
5473

5574
```js
5675
let ctx;
5776
let pos = 0;
77+
let animationId;
78+
let isRunning = false;
79+
let lastTime = 0;
80+
81+
function draw(currentTime) {
82+
if (!isRunning) return;
5883

59-
function draw(dt) {
84+
// Calculate delta time for smooth animation
85+
if (lastTime === 0) lastTime = currentTime;
86+
const deltaTime = (currentTime - lastTime) / 1000;
87+
lastTime = currentTime;
88+
89+
// Clear and draw the moving rectangle
6090
ctx.clearRect(0, 0, 100, 100);
6191
ctx.fillRect(pos, 0, 10, 10);
62-
pos += 10 * dt;
63-
self.requestAnimationFrame(draw);
92+
pos += 50 * deltaTime; // Move 50 pixels per second
93+
94+
// Loop the animation
95+
if (pos > 100) pos = -10;
96+
97+
animationId = self.requestAnimationFrame(draw);
6498
}
6599

66100
self.addEventListener("message", (e) => {
67101
if (e.data.type === "start") {
68102
const transferredCanvas = e.data.canvas;
69103
ctx = transferredCanvas.getContext("2d");
70-
self.requestAnimationFrame(draw);
104+
isRunning = true;
105+
lastTime = 0;
106+
animationId = self.requestAnimationFrame(draw);
71107
}
72108
if (e.data.type === "stop") {
73-
self.cancelAnimationFrame(handle);
109+
isRunning = false;
110+
if (animationId) {
111+
self.cancelAnimationFrame(animationId);
112+
}
74113
}
75114
});
76115
```
77116

78-
Finally, if needed, the main thread can send a `"stop"` message to the worker to stop the animation:
117+
On the main thread, we start by transferring the control of a {{HTMLElement("canvas")}} element to an {{domxref("OffscreenCanvas")}}, using {{domxref("HTMLCanvasElement.transferControlToOffscreen()")}} and send a message to `"start"` its work to the worker, with the offscreen canvas.
79118

80-
```js
81-
worker.postMessage({
82-
type: "stop",
83-
});
84-
```
119+
In the worker file (`worker.js`), we handle the animation logic. When receiving the `"start"` message, the worker starts the animation, moving the rectangle from left to right. Upon reception of a `"stop"` message, it will stop the animation.
120+
121+
Finally, the main thread can send a `"stop"` message to the worker to stop the animation after a delay, allowing the animation to be visible before stopping.
85122

86123
## Specifications
87124

files/en-us/web/api/dedicatedworkerglobalscope/requestanimationframe/index.md

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,55 +48,91 @@ assumptions about it. You can pass this value to
4848

4949
## Examples
5050

51-
On the main thread, we start by transferring the control of a {{HTMLElement("canvas")}} element to an {{domxref("OffscreenCanvas")}}, using {{domxref("HTMLCanvasElement.transferControlToOffscreen()")}}, then send a message to the worker to `"start"` its work with the offscreen canvas:
51+
Here's a complete example showing how to use `requestAnimationFrame()` in a dedicated worker with an `OffscreenCanvas`.
52+
53+
The HTML should contain:
54+
55+
```html
56+
<canvas width="100" height="100"></canvas>
57+
```
58+
59+
It should link to the following JavaScript:
5260

5361
```js
62+
const worker = new Worker("worker.js");
63+
64+
// Transfer canvas control to the worker
5465
const offscreenCanvas = document
5566
.querySelector("canvas")
5667
.transferControlToOffscreen();
5768

69+
// Start the animation
5870
worker.postMessage(
5971
{
6072
type: "start",
6173
canvas: offscreenCanvas,
6274
},
6375
[offscreenCanvas],
6476
);
77+
78+
// Stop the animation after 5 seconds
79+
setTimeout(() => {
80+
worker.postMessage({
81+
type: "stop",
82+
});
83+
}, 5000);
6584
```
6685

67-
When receiving the `"start"` message, the worker starts the animation, moving the rectangle from left to right. Upon reception of a `"stop"` message, it will stop the animation.
86+
**worker.js:**
6887

6988
```js
7089
let ctx;
7190
let pos = 0;
72-
let handle;
91+
let animationId;
92+
let isRunning = false;
93+
let lastTime = 0;
94+
95+
function draw(currentTime) {
96+
if (!isRunning) return;
7397

74-
function draw(dt) {
98+
// Calculate delta time for smooth animation
99+
if (lastTime === 0) lastTime = currentTime;
100+
const deltaTime = (currentTime - lastTime) / 1000;
101+
lastTime = currentTime;
102+
103+
// Clear and draw the moving rectangle
75104
ctx.clearRect(0, 0, 100, 100);
76105
ctx.fillRect(pos, 0, 10, 10);
77-
pos += 10 * dt;
78-
handle = self.requestAnimationFrame(draw);
106+
pos += 50 * deltaTime; // Move 50 pixels per second
107+
108+
// Loop the animation
109+
if (pos > 100) pos = -10;
110+
111+
animationId = self.requestAnimationFrame(draw);
79112
}
80113

81114
self.addEventListener("message", (e) => {
82115
if (e.data.type === "start") {
83116
const transferredCanvas = e.data.canvas;
84117
ctx = transferredCanvas.getContext("2d");
85-
handle = self.requestAnimationFrame(draw);
118+
isRunning = true;
119+
lastTime = 0;
120+
animationId = self.requestAnimationFrame(draw);
86121
}
87122
if (e.data.type === "stop") {
88-
self.cancelAnimationFrame(handle);
123+
isRunning = false;
124+
if (animationId) {
125+
self.cancelAnimationFrame(animationId);
126+
}
89127
}
90128
});
91129
```
92130

93-
Finally, if needed, the main thread can send a `"stop"` message to the worker to stop the animation:
131+
On the main thread, we start by transferring the control of a {{HTMLElement("canvas")}} element to an {{domxref("OffscreenCanvas")}}, using {{domxref("HTMLCanvasElement.transferControlToOffscreen()")}} and send a message to `"start"` its work to the worker, with the offscreen canvas.
94132

95-
```js
96-
worker.postMessage({
97-
type: "stop",
98-
});
99-
```
133+
In the worker file (`worker.js`), we handle the animation logic. When receiving the `"start"` message, the worker starts the animation, moving the rectangle from left to right. Upon reception of a `"stop"` message, it will stop the animation.
134+
135+
Finally, the main thread can send a `"stop"` message to the worker to stop the animation after a delay, allowing the animation to be visible before stopping.
100136

101137
## Specifications
102138

0 commit comments

Comments
 (0)