2
votes

I'm using the chart.js 2.6.0 library.

I'm trying to made a comparation line chart like the Google Analytics compare functionality: Screenshot

I have to compare two revenue date periods of an ecommerce.

I would like to draw two x Axes with different labels, one x Axe for the first period, one for the second.

Now I can draw two lines, one for each period, and two xAxes, but I can use only one array of labels, giving me the following result: screeshot

Obviously wrongly, every period-two point on the line, is corresponding to the period 1 label (see the hover infowindow in the second screeshot)

This is my code

        var ctx = $("#ordersCompareChart");
        var chart = new Chart(ctx, {

            type: 'line',
            data: {

                labels: data.labels,
                datasets: [{

                    borderColor: "#E25F5F",
                    label: 'Period 1: From ' + $('#from_first').val() + ' to ' + $('#to_first').val(),
                    data: data.values_first,
                    borderWidth: 3,
                    xAxisID: "x-axis-1",
                },

                {

                    borderColor: "#2793DB",
                    label: 'Period 2: From ' + $('#from_second').val() + ' to ' + $('#to_second').val(),
                    data: data.values_second,
                    borderWidth: 3,
                    xAxisID: "x-axis-2",
                },


                ]

            },

            options: {
                scales: {
                    xAxes: [
                            {
                            display: true,
                            tipe: "time",
                            scaleLabel: {
                                display: true,
                                labelString: 'Period 1'
                            },
                            id: "x-axis-1"

                            },
                            {
                                display: true,
                                tipe: "time",
                                id: "x-axis-2",
                                labels: data.labels_second,
                                scaleLabel: {
                                    display: true,
                                    labelString: 'Period 2'

                                }, 
                                id: "x-axis-2"
                            }
                        ],
                    yAxes: [{
                    display: true,
                    scaleLabel: {
                        display: true,
                        labelString: 'Total'
                    },
                    ticks: {
                        callback: function(value, index, values) {

                            return value.toLocaleString("de-DE",{style:"currency", currency:"EUR"});

                        }
                    }
                    }]
                }
            }

        });

Thanks to whoever can answer

2
Did you find an answer for this one? Would appreciate it :)user5810842
Hi, yes :) i will answer to my question hereSpetty
I have resolved my problem. I'll post answer here also in couple of days..user5810842
@Spetty +1: would also love to see your answerBoris K
here you are guysSpetty

2 Answers

4
votes

i'm sorry if I didn't answer before.

Here a working fiddle https://jsfiddle.net/7L0fu4er/10/

Let's explain my solution:

With Charts.js you can use only one set of labels for both two x axes, the workaround is to populate the labels array with 2 dates every one value of the array, after that, you have to call a callback in the "ticks" method of every xAxe that will split dates with a delimiter ("#" in my case).

In our case, we want to show two periods (like the ecommerce revenue of every day, this week and the last week), your labels array will be like:

{labels: ["09/01/2018#02/01/2018","10/01/2018#03/01/2018"] ...}

If you see the first value "09/01/2018#02/01/2018", the date before the "#" character is for the period 1, the second one is for the period 2.

So

  • First. You have to build the labels array, the days for every period must be the same number for every period values

  • Give an unique Id for every xAxe

  • Call "ticks" callback for every xAxe that will elaborate every labels array value, so you can split and draw your correct date for every day

I hope I have helped you

0
votes

I Know its an old question but I found out a great solution for this, m using .net framework.

1- make a store procedure to get all the data from database for this year GroupBy the data and first 3 letter of the month:

 SELECT  sum(anything) AS something ,  MAX ( Convert(char(3), tb.date, 0)) AS ALL_MONTHS 
FROM table tb  WHERE  YEAR(tb.date) = YEAR(CURRENT_TIMESTAMP)    
GROUP BY YEAR(tb.date), MONTH(tb.date)
ORDER BY YEAR(tb.date), MONTH(tb.date)

2- make a store procedure to get all the data from database for last year, similar to step 1 but the where clause would be something like this:

.......... WHERE YEAR(tb.date) = YEAR(GETDATE()) - 1 ..........

means minus the current year.

3- after sending the data from controller to view, in the View page use JS to manipulate the data.

note: there are 12 month so make an array for 12 month so that way there will be only one label but the data will figure out there place of month according to the index that they will receive from the js loop function.

/////-- chart-----------------------------------------------------

   var salesChartCanvas = $('#salesChart').get(0).getContext('2d')

    var months = @Html.Raw(Json.Encode(Model.expChartMonths));
    var total = @Html.Raw(Json.Encode(Model.expChartTotal));
      var Lastmonths = @Html.Raw(Json.Encode(Model.expChartMonthsLast));
    var Lasttotal = @Html.Raw(Json.Encode(Model.expChartTotalLast));

    var arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    var arr2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

    function getMonthFromString(mon) {
        return new Date(Date.parse(mon + " 1, 2021")).getMonth()
    }

    function getMonth(mon) {
        return new Date(Date.parse(mon + " 1, 2021")).getMonth()
    }
    //this year
    for (var x = 0; x < months.length; x++) { arr2[getMonth(months[x])] = total[x] }
    //last year
    for (var i = 0; i < Lastmonths.length; i++) { arr[getMonthFromString(Lastmonths[i])] = Lasttotal[i] }


    var salesChartData = {
        labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
            datasets: [
                {
                    label: 'This Year Expenses',
                    fill: false,
                    backgroundColor: 'rgba(60,141,188,0.9)',
                    borderColor: 'rgba(60,141,188,0.8)',
                    pointRadius: 5,
                    pointColor: '#3b8bba',
                    pointStrokeColor: 'rgba(60,141,188,1)',
                    pointHighlightFill: '#fff',
                    pointHighlightStroke: 'rgba(60,141,188,1)',
                    data: arr2
                }
            ,
            {
                label: 'Last Year Expenses',
                fill: false,
                backgroundColor: 'rgba(210, 214, 222, 1)',
                borderColor: 'rgba(210, 214, 222, 1)',
                pointRadius: 5,
                pointColor: 'rgba(210, 214, 222, 1)',
                pointStrokeColor: '#c1c7d1',
                pointHighlightFill: '#fff',
                pointHighlightStroke: 'rgba(220,220,220,1)',
                data: arr
            }
        ]
    }