Reputation: 71
I want to create a chart using WebSocket to display real-time information in Vue using vue-chartjs and chart.js. The issue is that for some reason, the data is not displaying. The array of numbers stored in chartData.value.datasets[0].data
updates its values correctly, but when updating the component, only the labels are updated in real-time, not the data array. Why could this be happening? Essentially: the labels update in real-time, but the data does not
On each new socket event updating the price, update both the price itself and the timestamp of when it was updated
This is my code
<script lang="ts" setup>
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from 'chart.js'
import { onMounted, ref, watch } from 'vue';
import { Line } from 'vue-chartjs'
interface SocketData {
bitcoin: string;
}
const bitcoinPrices = ref<number[]>([]);
const bitcoinLabels = ref<string[]>([]);
onMounted(async () => {
const pricesWs = new WebSocket('wss://ws.coincap.io/prices?assets=bitcoin')
pricesWs.onmessage = function (msg) {
const socketData = JSON.parse(msg.data) as SocketData;
const price = Number(socketData.bitcoin);
bitcoinPrices.value = [...bitcoinPrices.value, price];
bitcoinLabels.value = [...bitcoinLabels.value, new Date().toLocaleTimeString()];
updateChartData();
}
});
const {label, bgColor, title} = defineProps<{ label: string, bgColor: string, title: string }>();
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);
const chartData = ref({
labels: [] as string[],
datasets: [
{
label: label,
data: [] as number[],
backgroundColor: bgColor,
borderColor: bgColor,
borderWidth: 2,
pointBackgroundColor: bgColor
},
],
});
const chartOptions = {
plugins: {
title: {
display: true,
text: title,
font: {
size: 24
}
}
},
maintainAspectRatio: false
};
function updateChartData() {
chartData.value.labels = [...bitcoinLabels.value]
chartData.value.datasets[0].data = [...bitcoinPrices.value];
chartData.value = { ...chartData.value };
}
watch([bitcoinPrices, bitcoinLabels], updateChartData);
</script>
<template>
<div class="h-96">
<Line
:options="chartOptions"
:data="chartData"
/>
</div>
</template>
Upvotes: 0
Views: 131