Skip to content

Commit

Permalink
refactor!: change onCanvasResize to useResizeObserver and provide…
Browse files Browse the repository at this point in the history
… controls on the observer
  • Loading branch information
jsulpis committed Nov 11, 2024
1 parent 3cdbbac commit 31e38ff
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 18 deletions.
4 changes: 2 additions & 2 deletions lib/playground/src/pages/post-processing/bloom.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import Layout from "../../layouts/Layout.astro";
<script>
import {
useEffectPass,
onCanvasResize,
useWebGLContext,
useCompositor,
useRenderPass,
useResizeObserver,
} from "usegl";
import {
fragmentShaderSource,
Expand Down Expand Up @@ -84,7 +84,7 @@ import Layout from "../../layouts/Layout.astro";
combinePass,
]);

onCanvasResize(canvas, ({ devicePixelSize }) => {
useResizeObserver(canvas, ({ devicePixelSize }) => {
resizeCanvas(devicePixelSize.width, devicePixelSize.height);

compositor.setSize(devicePixelSize);
Expand Down
32 changes: 24 additions & 8 deletions lib/src/helpers/resize.ts → lib/src/hooks/useResizeObserver.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,55 @@
/**
* Listen for resize of the canvas itself instead of the whole window
* Listen for changes to the size of an element.
*/
export function onCanvasResize(
canvas: HTMLCanvasElement,
export function useResizeObserver(
target: HTMLElement,
callback: (args: {
/**
* canvas size in CSS pixels
* size of the observed element in CSS pixels
*/
size: { width: number; height: number };
/**
* canvas size in device pixels
* size of the observed element in device pixels
*/
devicePixelSize: { width: number; height: number };
/**
* untouched, native observer entries
*/
entries: ResizeObserverEntry[];
}) => void,
) {
let size: ResizeObserverSize;
let devicePixelSize: ResizeObserverSize;

const observer = new ResizeObserver((entries) => {
const entry = entries.find((entry) => entry.target === canvas)!;
const entry = entries.find((entry) => entry.target === target)!;

size = entry.contentBoxSize[0];
devicePixelSize = entry.devicePixelContentBoxSize?.[0] || {
blockSize: Math.round(size.blockSize * window.devicePixelRatio),
inlineSize: Math.round(size.inlineSize * window.devicePixelRatio),
};

// resize after next paint, otherwise there are glitches if a render loop is active
// call the callback after the next paint, otherwise there are glitches when resizing a canvas
// with an active render loop
setTimeout(() => {
callback({
size: { width: size.inlineSize, height: size.blockSize },
devicePixelSize: { width: devicePixelSize.inlineSize, height: devicePixelSize.blockSize },
entries,
});
}, 0);
});

observer.observe(canvas);
observer.observe(target);

return {
disconnect: observer.disconnect,
observe: () => {
observer.observe(target);
},
unobserve: () => {
observer.unobserve(target);
},
};
}
15 changes: 8 additions & 7 deletions lib/src/hooks/useWebGLCanvas.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { onCanvasResize } from "../helpers/resize";
import { useResizeObserver } from "./useResizeObserver";
import type { Attribute, DrawMode, PostEffect, Uniforms } from "../types";
import { useWebGLContext } from "./useWebGLContext";
import { useQuadRenderPass } from "./useQuadRenderPass";
Expand Down Expand Up @@ -83,12 +83,12 @@ export const useWebGLCanvas = <U extends Uniforms>(props: Props<U>) => {
));
}

if (canvas instanceof HTMLCanvasElement) {
// Don't listen for resize on an OffscreenCanvas (possibly in a worker)
onCanvasResize(canvas, ({ size }) => {
setSize({ width: size.width * dpr, height: size.height * dpr });
});
}
const resizeObserver =
canvas instanceof HTMLCanvasElement
? useResizeObserver(canvas, ({ size }) => {
setSize({ width: size.width * dpr, height: size.height * dpr });
})
: null; // Don't listen for resize on an OffscreenCanvas (possibly in a worker)

return {
gl,
Expand All @@ -102,5 +102,6 @@ export const useWebGLCanvas = <U extends Uniforms>(props: Props<U>) => {
onUpdated: primaryPass.onUpdated,
onBeforeRender: primaryPass.onBeforeRender,
onAfterRender: primaryPass.onAfterRender,
resizeObserver,
};
};
2 changes: 1 addition & 1 deletion lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ export { useRenderPass } from "./hooks/useRenderPass";
export { useWebGLCanvas } from "./hooks/useWebGLCanvas";
export { useWebGLContext } from "./hooks/useWebGLContext";
export { useLoop, playAllLoops, pauseAllLoops } from "./hooks/useLoop";
export { useResizeObserver } from "./hooks/useResizeObserver";

export { onPointerEvents } from "./helpers/pointer";
export { onCanvasResize } from "./helpers/resize";

0 comments on commit 31e38ff

Please sign in to comment.