AJ-
AJ-

Reputation: 1783

How can I display fixed labels on X-axis while having data on that axis?

I just started using Chart.js, and I have an issue.

First of all, what I need to display in my simple line chart is something like this:

enter image description here

This is my current chart, on the Y-axis I have possible grades (for student's exams), ranging from 1 to 6.

On the X-axis I have the possible Points that can be achieved in a given exam.

Now it gets more complicated, this chart is being updated based on the inputs and selection of a dropdown.

Grades (Y-axis) can be of 5 increment types: Integer, Halves, Quarters, Decimal and Hundredths

This is chosen with a dropdown, default value is Quarters, meaning with Quarters selected my Array of Numbers for the grades would look like:

grades = [1, 1.25, 1.50, 1.75, 2....., 5.75, 6]

meanwhile with Hundredths selected, it would look like:

grades = [1, 1.01, 1.02, 1.03, .... 5.97, 5.98, 5.99, 6]

And for each grade, a set amount of Points (X-axis) is needed to achieve it. The points needed are calculated with a formula that I put in a function:

mySecretFormula(grades: Array<Number>) {
    grades.forEach(g => {
    const currentPoints = g * mySecretFormula;

    this.points.push(currentPoints);
}

so basically I pass my Grades in this function, and it returns another Array of numbers with the same number of elements (as each grade corresponds to a score)

example, if I had selected Integer Grades, meaning my grade array looks like:

grades = [1, 2, 3, 4, 5, 6]

the return I would get for my scores would be:

scores = [0, 5, 10, 15, 25, 30] 

if the max points were set to 30 (the max score is defined in an input)

Then finally I used chart.js to display my data like this:

this.canvas.data.labels = this.points;
this.canvas.data.datasets[0].data = this.grades;
this.canvas.update();

so everytime I change the dropdown regarding the increments of the grades, this function gets fired and updates the chart.

Let's say it's working, but it's far from optimal.

What I want to achieve is simple.

It should look like this:

enter image description here

This is what the Chart looks like when I select Integer grades, so only 6 different grades and 6 different scores.

I want the Chart to always look like this, no matter what increment is selected, so always 5 or 6 grid lines and always the same tick points for the X-axis.

Then if the current increment selected is Integer, I'll have only 6 intersection, but if I were to swap to Decimal or Hundredths, so with a lot of intersections, the chart looks exactly like this, BUT when you hover on the line with the mouse, I'll get the tooltip for each valid intersection.

Now if I swap to Decimal increments, my Chart updates into this:

enter image description here

(ignore the rounding, forgot to round them to 2 decimals) so as you see the tickpoints change, the grid width changes, and the height of the whole chart changes.

But the intersections work correctly, if I hover the mouse along the line, I ll get a tooltip for each point for these pairs:

decimal increments equal to:

grades = [1, 1.1, 1.2, 1.3, 1.4, .... 5.9, 6] points = [0, 0.7, 1.4, 2.1, 2.8, .... 34.3, 35]

so to achieve this same result, BUT with the chart that is always the same, always the same tick points and height and width, because the range of the grades and the scores will always be the same, but depending on the increment chosen, there could be from a minimum of 6 intersection (integer) to over 500 intersections (hundredths)!

Hope I made myself clear, thank you very much

Edit: managed with your help to add a custom tooltip on 2 lines with this:

afterBody: function([tooltipItem], data): any {
                            const multistringText = ["Points: " + tooltipItem.xLabel];
                            multistringText.push("Grade: " + tooltipItem.yLabel);

                            return multistringText;
                        }

works perfectly, but how can I now remove the original tooltip string above it? look the image, above my 2 lines custom tooltip I have another line that I want to hide!

enter image description here

And finally, always looking at this image, how can I make the grid lines on the X-axis of the same width? as you can see the first 4 are bigger than the last! I want them to be always the same width! thank you

Upvotes: 1

Views: 3453

Answers (1)

barbsan
barbsan

Reputation: 3468

I advise to convert your chart to xy chart, set axis options and customize tooltips

var ctx = document.getElementById("myChart").getContext('2d');
var precision = 0;
var data = getData();

var myChart = new Chart(ctx, {
  type:"scatter",
    data: {
        datasets: [{
            label: 'grades',
            data: data,
            fill: false,
            pointRadius: 0,
            pointHitRadius: 3
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true,
                    max:6
                }
            }],
            xAxes: [{
                ticks: {
                    beginAtZero:true,
                    max:35,
                    stepSize: 1,
                    callback: function(value){
                      if (value < 5){
                        return value;
                      } else {
                        if (value% 5 === 0){
                          return value;
                        }
                      }
                    }
                }
            }]
        },
        tooltips: {
            callbacks: {
                label: function(tooltipItem, data) {
                    var label = [
                    'X: ' + tooltipItem.xLabel.toFixed(precision),
                    'Y: ' + tooltipItem.yLabel.toFixed(precision)
                    ];
                    return label;
                }
            }
        }
    }
});

function getData(){
  var step = 10**-precision;
  var arr = [];
  for (var i=0; i<=6; i+=step){
    arr.push({y: i, x: 35*i/6})
  }
  return arr;
}

setTimeout(function(){
    precision = 1;
    myChart.data.datasets[0].data = getData();
    myChart.update();

}, 2000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.js"></script>
<canvas id="myChart" width="100" height="100"></canvas>

Upvotes: 1

Related Questions