Skip to content

Instantly share code, notes, and snippets.

@redblobgames
Last active April 11, 2023 07:31
Show Gist options
  • Save redblobgames/fc3717945e9b533496bbc727e8751fe6 to your computer and use it in GitHub Desktop.
Save redblobgames/fc3717945e9b533496bbc727e8751fe6 to your computer and use it in GitHub Desktop.
Vue component for canvas with automatic dependency tracking
/** Canvas component
A generic canvas component that calls a draw function to draw the
contents, and automatically calls it again when anything the draw
function depends on changes. Blog entry:
http://simblob.blogspot.com/2018/03/using-vue-with-canvas.html
Example:
<a-canvas width="500" height="200"
:draw="(canvas, ctx) => { ctx.fillRect(x,y,1,1); }" />
This will call the draw function when the canvas is created,
and also update it whenever x or y changes, because the draw
function depends on them. Typical use: pass in a method from the
parent component.
Note:
This function will clear the canvas contents before calling the
draw function. It will wrap the call in save()/restore() to reset
the drawing state back to the default.
*/
Vue.component('a-canvas', {
props: ['width', 'height', 'draw'],
data() { return { ctx: null, }; },
template: `<canvas :data-dummyvalue="ctx &amp;&amp; redraw"/>`,
mounted() { this.ctx = this.$el.getContext('2d'); },
computed: {
redraw() {
let canvas = this.$el;
canvas.width = this.width;
canvas.height = this.height;
this.ctx.clearRect(0, 0, this.width, this.height);
this.ctx.save();
this.draw(canvas, this.ctx);
this.ctx.restore();
},
},
});
/* Implementation note: I set data-automatic="ctx && redraw" to make
the DOM depend on this computed property. The first time it's calculated,
the canvas doesn't exist yet. Subsequent calculations invoke the computed
property "redraw", which calls the draw function, which sets up the automatic
dependency tracking in Vue. This redraw function also uses the
width, height, and draw properties, so if any of those change, it
will trigger a redraw. */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment