Saturday, 13 May 2023

Place Chart js data point in middle of week when x axis is time Cartesian with type week

I am trying generate one chart with chart js plugin (version 3) and trying to use the x axis as pe this doc with type being set to to time and time unit is week. I am using date-fns adapter which is recommended by it's author with chartjs library.

I am using alpine js for init purpose and to use it easily for date manipulation purpose. Everything is working fine.

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.12.0/dist/cdn.min.js"></script>


<div class="project-progress-chart-wrapper" style="position: relative; padding-top:50%; padding-top:min(50%,530px)">
                    <div style="position:absolute;width: 100%;height:100%;left: 0;top: 0">
                        <canvas  id="project-progress-chart"
                            @shownextdata.window="function() {
                                const nextDate = getFourWeeksNextDate();
                                currentDate = new Date(nextDate);
                                initChartData();
                            }"
                            @showpreviousdata.window="() => {
                                const prevDate = getFourWeeksEarlierDate();
                                currentDate = new Date(prevDate);
                                initChartData();
                            }"
                            x-data="{
                                chartInstance: null,
                                init() {
                                    this.initChartData();
                                },
                                currentDate: new Date(),
                                numberOfProgressWeeks: 24,
                                getFourWeeksEarlierDate(){
                                    const date = new Date(this.currentDate);
                                    date.setDate(date.getDate() - (this.numberOfProgressWeeks * 7));
                                    return date;
                                },
                                getFourWeeksNextDate(){
                                    const date = new Date(this.currentDate);
                                    date.setDate(date.getDate() + (this.numberOfProgressWeeks * 7));
                                    return date;
                                },

                                generateChartData() {
                                    const data = [],
                                        lastSunday = this.getLastSunday(),
                                        tempLoopDate = new Date(lastSunday);

                                    while(this.getFourWeeksEarlierDate() <= tempLoopDate) {
                                        data.push({
                                            x: new Date(tempLoopDate).toISOString().split('T')[0],
                                            y: Math.floor(Math.random() * 50)
                                        })
                                        tempLoopDate.setDate(tempLoopDate.getDate() - 7)
                                    }

                                    return data;

                                   
                                },
                                getLastSunday() {
                                    const lastSunday = new Date(this.currentDate);
                                    lastSunday.setDate(this.currentDate.getDate() -  this.currentDate.getDay());
                                    return lastSunday;
                                },
                               
                                initChartData() {
                                    //setting up data
                                    const data = this.generateChartData(),
                                        progressChartData =  {
                                            datasets: [
                                                {
                                                    label: 'This Week',
                                                    fill: !0,
                                                    backgroundColor: 'transparent',
                                                    borderColor: 'rgba(2, 132, 199, 1)',
                                                    pointBackgroundColor: 'rgba(2, 132, 199, 1)',
                                                    pointBorderColor: '#fff',
                                                    pointHoverBackgroundColor: '#fff',
                                                    pointHoverBorderColor: 'rgba(2, 132, 199, 1)',
                                                    data: data,
                                                }
                                            ],
                                        };

                                    //setting up config

                                    const config = {
                                        type: 'line',
                                        data: progressChartData,
                                        options: {
                                            maintainAspectRatio: false,
                                            plugins: {
                                                legend: {
                                                    display: false
                                                },
                                                tooltip: {
                                                    
                                                }
                                            },
                                            scales: {
                                                x: {
                                                    type: 'time',
                                                    time: {
                                                        unit: 'week',
                                                        displayFormats: {
                                                            quarter: 'MMM yyyy'
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    this.chartInstance && this.chartInstance.destroy();

                                    //initialization
                                    null !== this.$el && (this.chartInstance = new Chart(this.$el, config));
                                }
                            }">
                        </canvas>
                    </div>
                    
            </div>

But what i am trying to achive is to associate the chart js x-data with kind of week rather than date and thus trying to place data point in the middle of week instead of at the edge of date.

I am trying to achive something like this where it is even possible to hover and change week background as data is associated with week and not date. And also as we can see, month only starts when first sunday of month comes. Sometimes month is longer when 5 weeks and sometimes shorter. enter image description here

But what I finally end up with is this. enter image description here

Can anyone please help how to associate data with weeks and thus trying to generate array of objects where week should be in focus and not date?

i.e. array of {x: '2023-W1', y: 10} instead of {x: '2023-01-01', y: 10} so that 10 (which is y value) comes in middle of week 1?

Thank you in advance.



from Place Chart js data point in middle of week when x axis is time Cartesian with type week

No comments:

Post a Comment