Hi,
I posted an issue in the Github
repo, but posting here too in case there's more interest here.
I have a number of fairly high refresh rate charts all being rendered at once. To take pressure off the main thread, I was wondering if I could use web workers to offload the rendering.
Below is the code that I've tried so far. As you can see, I had to mock the window object and the getAttribute() calls for height and width. I'm now facing an error: `Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The image source is detached`, which I understand to mean that no frame is ready to draw.
Any insights would be greatly appreciated.
```
<!-- src/components/SmoothieChart.vue -->
<template>
<div>
<canvas ref="onscreenCanvas" :width="width" :height="height"></canvas>
</div>
</template>
<script>
import { onMounted, ref } from 'vue';
import Smoothie from 'smoothie';
export default {
props: {
width: {
type: Number,
required: true,
},
height: {
type: Number,
required: true,
},
},
setup(props) {
const onscreenCanvas = ref(null);
onMounted(() => {
const offscreenCanvas = new OffscreenCanvas(props.width, props.height);
const worker = new Worker(new URL('./smoothieWorker.js', import.meta.url));
worker.postMessage({ offscreenCanvas }, [offscreenCanvas]);
const ctx = onscreenCanvas.value.getContext('2d');
worker.onmessage = (event) => {
if (event.data.type === 'frameReady') {
ctx.drawImage(offscreenCanvas, 0, 0);
}
};
});
return { onscreenCanvas };
},
};
</script>
```
```
// src/components/smoothieWorker.js
self.window = self;
importScripts('
https://cdn.jsdelivr.net/npm/smoo...@1.37.0/smoothie.js');
self.addEventListener('message', (event) => {
const { offscreenCanvas } = event.data;
createSmoothieChart(offscreenCanvas);
});
function createSmoothieChart(offscreenCanvas) {
const smoothieChart = new Smoothie.SmoothieChart({
grid: { strokeStyle: 'rgba(255, 255, 255, 0.1)', lineWidth: 1 },
labels: { fillStyle: 'rgba(255, 255, 255, 0.8)' },
millisPerPixel: 20,
responsive: true,
});
const timeSeries = new Smoothie.TimeSeries();
smoothieChart.addTimeSeries(timeSeries, { lineWidth: 2, strokeStyle: 'rgb(0, 255, 0)' });
smoothieChart.streamTo(offscreenCanvas, 1000 / 60);
setInterval(() => {
timeSeries.append(new Date().getTime(), Math.random() * 100);
self.postMessage({ type: 'frameReady' }); // Send a message back when a frame is ready
}, 1000);
}
```