Created
March 6, 2023 13:39
-
-
Save gordonbrander/01726958af83536370143941265fd2e0 to your computer and use it in GitHub Desktop.
RenderingElement - A custom element that batches updates on animation frame
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// RenderingElement | |
// A custom element that batches state updates on animation frame. | |
export class RenderingElement extends HTMLElement { | |
// Element state to render | |
#state = this.defaults(); | |
// Has an animation frame been scheduled? | |
#isAnimationFrameScheduled = false | |
// Perform a render and flag that animationFrame has completed. | |
// Hard-bound so we can pass as a callback to requestAnimationFrame. | |
#frame = () => { | |
this.#isAnimationFrameScheduled = false | |
this.render(this.#state) | |
} | |
constructor() { | |
super() | |
this.attachShadow({mode: 'open'}) | |
// Render initial markup | |
this.setup(this.#state) | |
} | |
// Set next state and schedule a render on next animation frame. | |
// Batches renders, so that if a render is already pending, it will | |
// just wait for that one. | |
state(next) { | |
this.#state = next | |
if (!this.#isAnimationFrameScheduled) { | |
this.#isAnimationFrameScheduled = true | |
requestAnimationFrame(this.#frame) | |
} | |
} | |
// Initial state | |
defaults() { | |
return null | |
} | |
// Set up element. Runs once, immediately upon construction. | |
setup(state) {} | |
// Render state. | |
// When you set `this.state(...)`, this will be called during the next | |
// animation frame. | |
render(state) {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment