···
1
+
import { trackVisibility, trackResizes, trackTextUpdates } from './observers';
const VERSION_300 = '#version 300 es';
···
class FragCanvas extends HTMLElement implements HTMLCanvasElement {
224
-
static observedAttributes = [];
226
+
static observedAttributes = ['pause'];
228
+
private subscriptions: (() => void)[] = [];
private state: ReturnType<typeof createState> | null = null;
private input: HTMLCanvasElement | HTMLImageElement | HTMLVideoElement;
private output: HTMLCanvasElement;
230
-
#mutationObserver = new MutationObserver(() => {
232
-
this.state.updateFragShader(this.source);
236
-
#resizeObserver = new ResizeObserver(entries => {
237
-
const entry = entries[0];
238
-
if (this.state && entry) {
239
-
const width = entry.devicePixelContentBoxSize[0].inlineSize;
240
-
const height = entry.devicePixelContentBoxSize[0].blockSize;
241
-
if (this.autoresize) {
242
-
this.input.width = width;
243
-
this.input.height = height;
245
-
this.state.updateViewport(width, height);
246
-
this.state.drawImmediate();
247
-
this.#rescheduleDraw();
232
+
public pause: boolean = false;
···
cancelAnimationFrame(this.#frameID);
this.#frameID = undefined;
378
-
this.#frameID = requestAnimationFrame(function draw(
379
-
timestamp: DOMHighResTimeStamp
382
-
self.state.draw(self.input, timestamp);
383
-
self.#frameID = requestAnimationFrame(draw);
362
+
this.#frameID = requestAnimationFrame(function draw(
363
+
timestamp: DOMHighResTimeStamp
365
+
if (self.state && !self.pause) {
366
+
self.state.draw(self.input, timestamp);
367
+
self.#frameID = requestAnimationFrame(draw);
374
+
this.pause = !!this.getAttribute('pause');
const gl = this.output.getContext('webgl2', {
···
const state = (this.state = gl && createState(gl, init));
403
-
this.#mutationObserver.observe(this, {
405
-
characterData: true,
407
-
this.#resizeObserver.observe(this, { box: 'device-pixel-content-box' });
390
+
this.subscriptions.push(
391
+
trackResizes(this, entry => {
392
+
const { inlineSize: width, blockSize: height } = entry;
393
+
if (this.autoresize) {
394
+
this.input.width = width;
395
+
this.input.height = height;
397
+
state.updateViewport(width, height);
398
+
state.drawImmediate();
399
+
this.#rescheduleDraw();
401
+
trackTextUpdates(this, () => {
402
+
state.updateFragShader(this.source);
404
+
trackVisibility(this, isVisible => {
405
+
this.pause = !isVisible;
406
+
this.#rescheduleDraw();
409
+
this.#rescheduleDraw();
413
+
attributeChangedCallback(
415
+
_oldValue: unknown,
418
+
if (name === 'pause') {
419
+
this.pause = !!newValue;
413
-
this.#mutationObserver.disconnect();
414
-
this.#resizeObserver.disconnect();
426
+
this.subscriptions.forEach(unsubscribe => unsubscribe());
427
+
this.subscriptions.length = 0;
if (this.#frameID !== undefined) {
cancelAnimationFrame(this.#frameID);
this.#frameID = undefined;