I'm doing a project using vue3, TypeScript and chartJs. Already implemented the date-fns-adapter and made vars {}(just for testing purposes) ⇾ (day, week, month) that work when I change manually the time unit. Even from what I saw on vueDevTools and console.log chart the units are changing from ref.value but there's a big failure in chart.update() and I can't find the reason. If anyone can help me it would be really appreciated. Code:
<template>
<div>
<div class="relative">
<canvas ref="ctx" width="360" height="256" />
<span
class="absolute right-4 bottom-8 text-3xl text-primary font-semibold"
>
{{ currentRating }}
</span>
</div>
<footer class="ml-8 mr-2 flex justify-between gap-4">
<button @click="periodChange('day')">Day</button>
<button @click="periodChange('week')">Week</button>
<button @click="periodChange('month')">Month</button>
<button @click="periodChange('year')">">Year</button>
</footer>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, computed, watch, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { useStore } from 'vuex'
import { useI18n } from 'vue-i18n'
import { formatISO, sub, intlFormat } from 'date-fns'
import { Rating, RatingHistory } from '@package/lib/types/Rating'
import 'chartjs-adapter-date-fns'
import { enUS } from 'date-fns/locale'
import {
Chart,
ChartItem,
ChartArea,
LineElement,
PointElement,
LineController,
CategoryScale,
LinearScale,
Filler,
Tooltip,
TimeScale
} from 'chart.js'
//import { ClickFeedback } from 'aws-sdk/clients/kendra'
Chart.register(
LineElement,
PointElement,
LineController,
CategoryScale,
LinearScale,
Filler,
Tooltip,
TimeScale
)
export default defineComponent({
name: 'RatingHistoryGraph',
props: {
verified: {
type: Boolean,
default: false
}
},
setup(props) {
const route = useRoute()
const store = useStore()
const { t, locale } = useI18n()
const ctx = ref<HTMLCanvasElement | null>(null)
let chart: any
// GMT 0000,+ 12 hours => That's why the time is allways 12:00.
const day = [
{ x: Date.parse('2019-06-14 00:00: GMT+1200'), y: 1 },
{ x: Date.parse('2019-09-06 00:00: GMT+1200'), y: 3 },
{ x: Date.parse('2020-03-11 00:00: GMT+1200'), y: 2.5 },
{ x: Date.parse('2021-07-11 00:00: GMT+1200'), y: 7 },
{ x: Date.parse('2022-03-06 00:00: GMT+1200'), y: 6 },
{ x: Date.parse('2022-06-18 00:00: GMT+1200'), y: 15 }
] // This is time in miliSeconds
const week = [
{ x: Date.parse('2020-06-31 00:00: GMT+1200'), y: 1 },
{ x: Date.parse('2020-06-07 00:00: GMT+1200'), y: 1 },
{ x: Date.parse('2020-06-14 00:00: GMT+1200'), y: 4 },
{ x: Date.parse('2020-06-21 00:00: GMT+1200'), y: 10 }
]
const month = [
{ x: Date.parse('2019-03-14 00:00: GMT+1200'), y: 1 },
{ x: Date.parse('2019-07-06 00:00: GMT+1200'), y: 3 },
{ x: Date.parse('2020-04-11 00:00: GMT+1200'), y: 2.5 },
{ x: Date.parse('2021-03-11 00:00: GMT+1200'), y: 7 },
{ x: Date.parse('2022-05-06 00:00: GMT+1200'), y: 6 },
{ x: Date.parse('2022-06-18 00:00: GMT+1200'), y: 15 }
]
type Period =
| false
| 'year'
| 'day'
| 'month'
| 'week'
| 'millisecond'
| 'second'
| 'minute'
| 'hour'
| 'quarter'
| undefined
const period = ref<Period>('year')
const generateChart = () => {
if (!ctx.value) return
let width = 0
let height = 0
let gradient: CanvasGradient
const getGradient = (
ctx: CanvasRenderingContext2D,
chartArea: ChartArea
): CanvasGradient => {
const chartWidth = chartArea.right - chartArea.left
const chartHeight = chartArea.bottom - chartArea.top
if (!gradient || width !== chartWidth || height !== chartHeight) {
width = chartWidth
height = chartHeight
gradient = ctx.createLinearGradient(
0,
chartArea.bottom,
0,
chartArea.top
)
gradient.addColorStop(0, 'rgba(222, 45, 119, 0.05)')
gradient.addColorStop(1, 'rgba(222, 45, 119, 0.25)')
}
return gradient
}
Chart.defaults.font.weight = 'bold'
chart = new Chart(ctx.value.getContext('2d') as ChartItem, {
type: 'line',
data: {
datasets: [
{
label: 'Rating',
//data: chartData.value.map(data => data.rating),
data: day,
fill: true,
backgroundColor: context => {
const chart = context.chart
const { ctx, chartArea } = chart
if (!chartArea) return
return getGradient(ctx, chartArea)
},
borderColor: 'rgb(222, 45, 119)',
tension: 0.4
}
]
},
// Configuration options go here.
options: {
scales: {
x: {
type: 'time',
time: {
unit: period.value
},
min: '2019-01-01', // How to make it dinamic?
max: Date.now(),
adapters: {
date: {
locale: enUS // DINAMIC need.
}
}
},
y: {
suggestedMin: 0,
suggestedMax: 21,
grid: {
color: 'rgb(242, 244, 246)',
borderColor: 'rgb(242, 244, 246)'
},
ticks: {
maxTicksLimit: 22
}
}
},
responsive: true,
plugins: {
legend: {
display: false
},
tooltip: {
boxWidth: 100
}
}
}
})
}
const periodChange = (timeFrame: Period): void => {
console.log(chart)
period.value = timeFrame
chart.update()
}
onMounted(() => {
generateChart()
})
return {
t,
// currentRating,
ctx,
// chartData,
actions,
showHistoryFrom,
fromOptions,
id,
to,
from,
changeFromOptions,
timeFrame
}
}
})
</script>