Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@wethegit/react-wtc-gl",
"version": "0.1.0",
"version": "0.1.1",
"description": "React components and hooks for wtc-gl recipes.",
"type": "module",
"files": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const defaultCanvasStyle: CSSProperties = {
position: 'fixed',
inset: 0,
width: '100%',
height: '100%',
height: '100lvh',
pointerEvents: 'none',
zIndex: 0
}
Expand Down
3 changes: 2 additions & 1 deletion packages/site/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export default defineConfig({
'@wethegit/react-wtc-gl': resolvePath('../react/src/index.ts')
},
dedupe: ['react', 'react-dom']
}
},
server: { host: true }
})
2 changes: 1 addition & 1 deletion packages/wtc-gl/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wtc-gl",
"version": "1.3.0",
"version": "1.3.1",
"description": "Typescript simple Web GL library.",
"type": "module",
"files": [
Expand Down
42 changes: 30 additions & 12 deletions packages/wtc-gl/src/recipes/ScrollRenderer/ScrollRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export class ScrollRenderer {
#playing: boolean = false
#ownsCanvas: boolean
#cleared: boolean = false
#resizeObserver: ResizeObserver | null = null

constructor({
rendererProps = {},
Expand All @@ -99,7 +100,10 @@ export class ScrollRenderer {
this.render = this.render.bind(this)
this.resize = this.resize.bind(this)

window.addEventListener('resize', this.resize)
if (typeof ResizeObserver !== 'undefined') {
this.#resizeObserver = new ResizeObserver(this.resize)
this.#resizeObserver.observe(this.canvas)
}
this.resize()
}

Expand All @@ -109,19 +113,29 @@ export class ScrollRenderer {
}

/**
* Synchronises the GL canvas buffer size with the layout viewport.
* Synchronises the GL canvas buffer size with the canvas element's CSS size.
*
* Uses `document.documentElement.clientWidth/clientHeight` rather than
* `window.innerWidth/innerHeight` because on systems with classic
* (non-overlay) scrollbars `innerWidth` includes the scrollbar gutter,
* while a `position:fixed; width:100%` canvas does not — causing every
* scissor rect to clip a few pixels short on the trailing edge.
* Measures the canvas (`clientWidth`/`clientHeight`) so the buffer
* can never disagree with how the element is laid out. Falls back to the
* document's client size when the canvas isn't in the DOM yet (or has no
* layout size), which also avoids the scrollbar-gutter offset that
* `window.innerWidth/innerHeight` would introduce.
*
* Called automatically on construction and on every `resize` event.
* Called automatically on construction, and when canvas resizeObsever triggers
* and at the start of every rendered frame.
*/
resize() {
const el = document.documentElement
this.renderer.dimensions = new Vec2(el.clientWidth, el.clientHeight)
const canvas = this.canvas
let width = canvas.clientWidth
let height = canvas.clientHeight
if (!width || !height) {
const el = document.documentElement
width = el.clientWidth
height = el.clientHeight
}
const current = this.renderer.dimensions
if (current && current.width === width && current.height === height) return
this.renderer.dimensions = new Vec2(width, height)
}

/**
Expand Down Expand Up @@ -177,6 +191,9 @@ export class ScrollRenderer {
}
this.#cleared = false

// Catch element size changes that haven't been observed yet
this.resize()

const { gl } = this
const { dpr } = this.renderer
const canvasWidth = this.renderer.dimensions.width * dpr
Expand Down Expand Up @@ -268,7 +285,7 @@ export class ScrollRenderer {
}

/**
* Stops the render loop, removes the resize listener, and destroys all
* Stops the render loop, disconnects the resize observer, and destroys all
* registered scenes (disconnecting their `IntersectionObserver`s).
*
* When the renderer created its own canvas, the WebGL context is also
Expand All @@ -288,7 +305,8 @@ export class ScrollRenderer {
*/
destroy(): HTMLCanvasElement {
this.playing = false
window.removeEventListener('resize', this.resize)
this.#resizeObserver?.disconnect()
this.#resizeObserver = null
this.#scenes.forEach((s) => s.destroy())
this.#scenes = []
if (this.#ownsCanvas)
Expand Down
Loading