Support Online
Skip to main content

HTML5 Canvas Control and Graphics Drawing with Vue.js

In this guide, you will learn how to use the Vue.js component structure with the HTML5 Canvas API.
The aim is to draw reactive and fluid graphics without burdening the DOM.

As an example, we will develop a live bar chart that represents the load on GenixNode servers.
This method; Ideal for trackpads, graphics and games.

🧠 Technical Summary

This guide explains HTML5 Canvas integration with Vue.js.
Problem: Managing canvas drawings synchronously with Vue reactivity.
Solution: Transferring the drawing context to the components with the provide / inject structure.


Prerequisites

  • Node.js must be installed on your computer
  • Basic knowledge of Vue.js is sufficient

1️⃣ Creating the Project

Start a new project with Vue CLI.

npx @vue/cli create genixnode-grafik-panel
  • This command creates Vue project with default settings.
cd genixnode-grafik-panel
  • This command switches to the project directory.

2️⃣ Preparing the Canvas Container (Provider)

  1. We create the main component that manages the Canvas area. This component distributes drawing authority to subcomponents.
src/components/MyCanvas.vue

<template>
<div class="canvas-wrapper">
<canvas ref="my-canvas"></canvas>
<slot></slot>
</div>
</template>

<script>
export default {
data() {
return {
provider: {
context: null,
},
};
},

provide() {
return {
provider: this.provider,
};
},

mounted() {
const canvas = this.$refs['my-canvas'];
this.provider.context = canvas.getContext('2d');
canvas.width = canvas.parentElement.clientWidth;
canvas.height = canvas.parentElement.clientHeight;
},
};
</script>
  • This code transfers the Canvas context to subcomponents reactively.

3️⃣ Creating a Renderless Drawing Component

  1. This component does not print HTML to the DOM. Draws directly on the canvas.
src/components/MyBox.vue

<script>
const pxX = (p, ctx) => Math.floor((ctx.canvas.width / 100) * p);
const pxY = (p, ctx) => Math.floor((ctx.canvas.height / 100) * p);

export default {
inject: ['provider'],

props: {
x1: Number,
y1: Number,
x2: Number,
y2: Number,
deger: Number,
renk: String,
},

data() {
return {
oncekiKutu: { x: 0, y: 0, w: 0, h: 0 },
};
},

computed: {
hesaplananKutu() {
const ctx = this.provider.context;
if (!ctx) return null;

const kutu = {
x: pxX(this.x1, ctx),
y: pxY(this.y1, ctx),
w: pxX(this.x2 - this.x1, ctx),
h: pxY(this.y2 - this.y1, ctx),
};

this.oncekiKutu = kutu;
return kutu;
},
},

render() {
if (!this.provider.context) return;

const ctx = this.provider.context;
const k = this.hesaplananKutu;

ctx.clearRect(this.oncekiKutu.x, this.oncekiKutu.y, this.oncekiKutu.w, this.oncekiKutu.h);
ctx.fillStyle = this.renk;
ctx.fillRect(k.x, k.y, k.w, k.h);

ctx.fillStyle = '#000';
ctx.font = '20px Arial';
ctx.textAlign = 'center';
ctx.fillText(`${Math.floor(this.deger)}%`, k.x + k.w / 2, k.y - 10);
},
};
</script>
  • This structure automatically updates Canvas when Vue reactivity changes.

4️⃣ Combining the Application

  1. Let's create the main component that simulates server loads.
src/App.vue

<template>
<div id="app">
<h2>GenixNode - Sunucu Yük İzleme</h2>

<my-canvas style="width:100%; height:500px; border:1px solid #ccc">
<my-box
v-for="(sunucu, index) in sunucuMetrikleri"
:key="index"
:x1="(index / sunucuMetrikleri.length) * 100"
:x2="(index / sunucuMetrikleri.length) * 100 + 100 / sunucuMetrikleri.length"
:y1="100"
:y2="100 - sunucu.yuk"
:renk="sunucu.renk"
:deger="sunucu.yuk"
/>
</my-canvas>
</div>
</template>

<script>

import MyCanvas from './components/MyCanvas.vue';
import MyBox from './components/MyBox.vue';

export default {
components: { MyCanvas, MyBox },

data() {
return {
sunucuMetrikleri: [
{ yuk: 45, renk: '#ff6b6b' },
{ yuk: 20, renk: '#4ecdc4' },
{ yuk: 78, renk: '#ffe66d' },
{ yuk: 12, renk: '#1a535c' },
],
};
},

mounted() {
setInterval(() => {
const i = Math.floor(Math.random() * this.sunucuMetrikleri.length);
let v = this.sunucuMetrikleri[i].yuk + (Math.random() - 0.5) * 10;
this.sunucuMetrikleri[i].yuk = Math.max(0, Math.min(100, v));
}, 100);
},
};
</script>
  • This structure simulates live data streaming.

❓ Frequently Asked Questions

1. Why is Canvas preferred? Provides high performance and low DOM cost.

2. Do I have to use render instead of template? Yes for canvas drawing.

3. Is it mobile friendly? Yes, all modern browsers support it.

4. Does it work in Vue 3? The logic is the same, API adaptation required.


🎯 Result

You've drawn on HTML5 Canvas without losing Vue.js reactivity. You can develop trackpads, graphics, and games with this method.

You can publish your projects immediately by hosting them on the GenixNode infrastructure. 🚀