0

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

AJ-
  • 1,638
  • 1
  • 24
  • 49
  • Can't you set [ticks options](https://www.chartjs.org/docs/latest/axes/cartesian/linear.html#tick-configuration-options) for axis (like min, max, precision/stepSize)? – barbsan Oct 18 '18 at 12:30
  • I tried this: 'scales: { xAxes: [ { ticks: { stepSize: 5 },' but It won't do anything, ticks are always the same! I want the ticks to be at the same point as the range will always be the same (e.g 0-30) – AJ- Oct 18 '18 at 13:05
  • So rather than accept my answer on your ng2-charts question recommending chart.js, you delete the question, start using chart.js and then ask another question about chart.js? – Marshal Oct 18 '18 at 13:06
  • hey! I asked the same question, as I saw that ng2-charts wasn't working, and I deleted it to not leave useless questions around! didnt mean to annoy you if that's how you felt! sorry! – AJ- Oct 18 '18 at 13:07
  • Not annoyed, just getting clarification on your logic to start using the recommended technology but deleting the question without accepting the answer. – Marshal Oct 18 '18 at 13:11
  • my bad then, didn't consider it as an answer for the question asked so I thought to make a more complete question using chart.js, so sorry – AJ- Oct 18 '18 at 13:13
  • @barbsan the problem is, I need to set a stepSize on the Y axis, but the points on that axis are label strings (I have numbers but I convert them to string), so I think that s why stepsize won't work, is it possible to have also data in the X axis instead of only labels? – AJ- Oct 18 '18 at 13:14
  • Could you create working snippet of your chart? Propably it would be better to use [x y chart](https://stackoverflow.com/questions/45098211/chart-js-plot-line-graph-with-x-y-coordinates), properly set axis and configure [tooltip label](https://www.chartjs.org/docs/latest/configuration/tooltip.html#label-callback) – barbsan Oct 18 '18 at 13:25

1 Answers1

1

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>
barbsan
  • 3,418
  • 11
  • 21
  • 28
  • thank you very much for this nice answer! I have some questions! First of all, with your code, when I paste it in my controller, the output is the chart, but the line is invisible! I can hover with the mouse and get the tooltips, but the line doesn't show! If I change pointRadius to 1, I ll get a dotted line, otherwise nothing! Then, how can I have the tooltip with x: value, y: value on 2 lines? I tried attacching + "" but won't work! And I also had to remove your toFixed() part because the yLabel and xLabel are strings for me! doesn't allow me to use toFixed!2nd part in my next comment – AJ- Oct 19 '18 at 07:06
  • so now to implement my data, I'll just need to pass an array of objects {x: foo, y: bar} to the datasets and it should work I guess, gonna make some tests, but I knew I had to be able to put data on the X axis, just didn't know how! One last thing, the max number of points will be set on an input, can I somehow for the ticks label on the X axis put a condition to display different ticks based on the max number of points? so for example: – AJ- Oct 19 '18 at 07:08
  • if max points are >50, a grid line (tick) every 5, then 100 < 50, a grid line every 10, then for 100+ but >200, grid line every 20, and for 200+ and >500 grid lines every 40 – AJ- Oct 19 '18 at 07:10
  • What version of chartjs are you using? Here's list of [properties](https://www.chartjs.org/docs/latest/charts/line.html#dataset-properties), `borderColor` and/or `borderWidth` should make it visible – barbsan Oct 19 '18 at 07:12
  • And for custom ticks propably you'll need [this](https://www.chartjs.org/docs/latest/axes/labelling.html#creating-custom-tick-formats) - create callback and if tick should be hidden return `null` or `undefined` – barbsan Oct 19 '18 at 07:17
  • ok adding: showLine: true, fixed the invisible line issue! one last thing, could you kindly give me an example for the custom tick? so let's say the max Points are set to 100, so I want to show a grid line on the X-axis every 10 points, what should I do? something like modulo? -> 100 % 10 ? so it will return true only every 10? thank you – AJ- Oct 19 '18 at 07:24
  • and I m using version "2.7.38", and I forgot, any clue on how to make the tooltip labels for X and Y on 2 lines instead of one? – AJ- Oct 19 '18 at 07:25
  • multiline tooltips: https://stackoverflow.com/questions/29302392/chartjs-tooltip-line-breaks – barbsan Oct 19 '18 at 07:26
  • Updated with example of custom axis ticks (note to set `stepSize` as small as the smaller interval you'll need). – barbsan Oct 19 '18 at 07:39
  • thank you so so much! you really helped me out! I edited my OP with a new image at the bottom and 2 quick questions, if you have any idea on how to fix that let me know! meanwhile setting your answer as correct and thank you again!! – AJ- Oct 19 '18 at 07:52
  • Open new question instead of adding new questions to this one. In this way it may help other people with the same problem. (Actually fixed step axis was beyond this question) – barbsan Oct 19 '18 at 07:59