Skip to content

Commit

Permalink
Add offscreen canvas demo
Browse files Browse the repository at this point in the history
  • Loading branch information
SlicedSilver committed May 2, 2024
1 parent 14f0348 commit bf4b57d
Show file tree
Hide file tree
Showing 13 changed files with 522 additions and 2 deletions.
1 change: 1 addition & 0 deletions examples/offscreen/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
93 changes: 93 additions & 0 deletions examples/offscreen/bouncing-ball-model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
CanvasElementBitmapSizeBinding,
createCanvasRenderingTarget2D,
Size,
} from 'fancy-canvas';
import { BouncingBallRenderer, Position } from './bouncing-ball-renderer.js';

type Canvas = CanvasElementBitmapSizeBinding<boolean>['canvas'];

export class BouncingBallModel {
private readonly _canvas: Canvas;
private readonly _color: string;
private _running: boolean = false;
private _size: Size;
private _mediaSize: Size;
private _renderer: BouncingBallRenderer;
private _position: Position = {
x: 10,
y: 10,
};
private _velocity: Position = {
x: 10,
y: 5,
};

public constructor(

Check failure on line 26 in examples/offscreen/bouncing-ball-model.ts

View workflow job for this annotation

GitHub Actions / build

Constructor has too many parameters (4). Maximum allowed is 3
canvas: Canvas,
color: string,
size: Size,
mediaSize: Size

Check failure on line 30 in examples/offscreen/bouncing-ball-model.ts

View workflow job for this annotation

GitHub Actions / build

Missing trailing comma
) {
this._canvas = canvas;
this._color = color;
this._size = size;
this._mediaSize = mediaSize;
this._renderer = new BouncingBallRenderer(this._color);
this.start();
}

public updateSize(
size: Size,
mediaSize: Size,
isOffscreen?: boolean

Check failure on line 43 in examples/offscreen/bouncing-ball-model.ts

View workflow job for this annotation

GitHub Actions / build

Missing trailing comma
): void {
this._size = size;
this._mediaSize = mediaSize;
if (isOffscreen) {
(this._canvas as OffscreenCanvas).height = size.height;
(this._canvas as OffscreenCanvas).width = size.width;
}
}

public start(): void {
this._running = true;
this._animate();
}

public stop(): void {
this._running = false;
}

private _animate(): void {
const newPos: Position = {
x: this._position.x + this._velocity.x,
y: this._position.y + this._velocity.y,
};
if (newPos.x <= 10 || newPos.x >= this._mediaSize.width - 10) {
this._velocity.x *= -1;
newPos.x = Math.min(
Math.max(10, newPos.x),
this._mediaSize.width - 10

Check failure on line 71 in examples/offscreen/bouncing-ball-model.ts

View workflow job for this annotation

GitHub Actions / build

Missing trailing comma
);
}
if (newPos.y <= 10 || newPos.y >= this._mediaSize.height - 10) {
this._velocity.y *= -1;
newPos.y = Math.min(
Math.max(10, newPos.y),
this._mediaSize.height - 10

Check failure on line 78 in examples/offscreen/bouncing-ball-model.ts

View workflow job for this annotation

GitHub Actions / build

Missing trailing comma
);
}
const target = createCanvasRenderingTarget2D({
get2DContext: options => this._canvas.getContext('2d', options),
bitmapSize: this._size,
canvasElementClientSize: this._mediaSize,
});
this._renderer.updatePos(newPos);
this._renderer.draw(target);
this._position = newPos;
if (this._running) {
requestAnimationFrame(this._animate.bind(this));
}
}
}
45 changes: 45 additions & 0 deletions examples/offscreen/bouncing-ball-renderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {
CanvasRenderingTarget2D,
MediaCoordinatesRenderingScope,
} from 'fancy-canvas';

export interface Position {
x: number;
y: number;
}

export class BouncingBallRenderer {
private readonly _color: string;
private _position: Position | undefined;

public constructor(color: string) {
this._color = color;
}

public updatePos(position: Position) {
this._position = position;
}

public draw(target: CanvasRenderingTarget2D): void {
target.useMediaCoordinateSpace(
(scope: MediaCoordinatesRenderingScope) => {
scope.context.clearRect(
0,
0,
scope.mediaSize.width,
scope.mediaSize.height

Check failure on line 30 in examples/offscreen/bouncing-ball-renderer.ts

View workflow job for this annotation

GitHub Actions / build

Missing trailing comma
);
scope.context.beginPath();
scope.context.arc(
this._position?.x ?? 0,
this._position?.y ?? 0,
10,
0,
2 * Math.PI

Check failure on line 38 in examples/offscreen/bouncing-ball-renderer.ts

View workflow job for this annotation

GitHub Actions / build

Missing trailing comma
);
scope.context.fillStyle = this._color;
scope.context.fill();
}

Check failure on line 42 in examples/offscreen/bouncing-ball-renderer.ts

View workflow job for this annotation

GitHub Actions / build

Missing trailing comma
);
}
}
40 changes: 40 additions & 0 deletions examples/offscreen/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
body {
font-family: -apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto,
Ubuntu, sans-serif;
}

#header,
#content,
.actions {
max-width: 680px;
margin: 0 auto;
}

.actions {
display: flex;
flex-direction: row;
gap: 12px;
margin-block: 12px;
}

#header {
font-size: 36px;
width: 100%;
}

#content {
display: flex;
flex-direction: column;
gap: 24px;
}

.example h3 {
color: var(--example-color);
margin: 12px 0;
}

.example-canvas {
border: 2px solid var(--example-color);
height: 150px;
width: 100%;
}
41 changes: 41 additions & 0 deletions examples/offscreen/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Fancy Canvas - Offscreen Demo</title>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<div>
<h2 id="header">Offscreen demos</h2>
</div>
<div class="actions">
<button id="start-button">Start</button>
<button id="pause-button">Pause</button>
<button id="task-button">Long Task on Main Thread</button>
</div>
<div id="content">
<div class="example" style="--example-color: #f23645">
<h3>Offscreen Disabled</h3>
<canvas
id="offscreen-canvas-disabled"
class="example-canvas"
></canvas>
</div>
<div class="example" style="--example-color: #2962ff">
<h3>Offscreen Main Thread</h3>
<canvas
id="offscreen-canvas-main"
class="example-canvas"
></canvas>
</div>
<div class="example" style="--example-color: #089981">
<h3>Offscreen Worker Thread</h3>
<canvas
id="offscreen-canvas-worker"
class="example-canvas"
></canvas>
</div>
</div>
</body>
<script src="index.js"></script>
</html>
Loading

0 comments on commit bf4b57d

Please sign in to comment.