Mémo Chart.js

Michel Llibre, mai 2025.

Mémo Chart.js

La structuration des données (Chart.data)

Les options (Chart.options)


Voir documentation ici : https://www.chartjs.org/docs/latest/

Pour pouvoir utiliser la librairie graphique Chart.js une méthode simple consiste à inclure la ligne suivante dans le head de la page html :
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

Les graphiques chart.js sont crées dans un élément Canvas du DOM (Document object Model).

Chart : Le constructeur

Le constructeur Chart du graphique est appélé comme suit :

const chart = new Chart(canvas, config);

Il a pour premier argument un élément Canvas du DOM et pour deuxième argument l'objet JSON de configuration du graphique à tracer. Ici config, chart et canvas sont des noms d'instance arbitraires. L'instance canvas a, par exemple, été créé au préalable par l'instruction :

const canvas = document.getElementById('myCanvas');

dans le cas où l'élément Canvas aurait été inclus dans la partie HTML du body par l'instruction :

<canvas id="myCanvas" class ="chart-container"></canvas>

Le deuxième argument du constructeur Chart, config, est un objet JSON préalablement créé qui a deux attributs obligatoires : type et data, et un troisième attribut optionnel options :

const config = {
    type: 'line',
    data: MesData,
    options : {} // non requis
};

C'est par le biais de ces 3 attributs que le graphique est spécifié.

La mise à jour : update()

Avant d'entrer dans le détail de la définition d'un graphique, notons qu'un graphique étant spécifié et tracé, on peut modifier un quelconque de ses éléments et mettre à jour le tracé à l'aide de la méthode Chart.update().

Les différents types de graphique (Chart.type)

En suivant la tendance générale, nous noterons Chart l'élément racine de l'objet qui décrit la configuration. Il aurait peut-être été plus judicieux de le noter Config. Avec cette notation universelle, le type de graphique est spécifié par un string (line, bar...) affecté à l'attribut Chart.type. Voici la liste des principaux strings définissant un type de graphique :

La structuration des données (Chart.data)

Les données numériques du tracé sont incluses dans un objet JSON affecté à l'attribut Chart.data. Les deux principaux attributs de cet objet sont labels généralement utilisé pour les données en abscisse et datasets généralement utilisé pour les données des différents graphes en ordonnées :

const MesData = {
    labels : tX,
    datasets: myDatasets
}

Les abscisses (Chart.data.labels)

Généralement les abscisses sont un simple tableau de nombres ou de strings affecté à l'attribut Chart.data.labels. Ci dessus, il est noté tX.

Les datasets (chart.data.datasets)

Comme plusieurs graphes peuvent être affichés simultanément, les ordonnées sont toujours associées à un attribut chart.data.datasets qui est un tableau, même s’il ne contient qu’un seul jeu de données. Dans ce dernier cas le tableau est de dimension 1.
Exemple : Voici en préalable la génération d'un tableau d'abscisses tX et de deux tableaux d'ordonnées tY[0] et tY[1] qui seront utilisés ensuite dans la définition des attributs labels et datasets de l'objet Chart.data :

const tX = new Array(), tY = new Array();
tY[0] = new Array(), tY[1] = new Array();
for (let i = 0; i <= 40; i++) {
    x = i - 20; tX[i] = x;
    tY[0][i] = x * x;
    tY[1][i] = 16 * (x + 20);
}
const myDatasets = tY.map(vals => ({ data:vals }));

L'objet datasets a de nombreux attributs. Ci-dessus nous en construisons une instance myDatasets qui est un tableau de 2 d'objets qui n'ont qu'un seul attribut data auquel est affecté le tableau des ordonnées correspondantes. Cette syntaxe très concise est assez obscure. Une syntaxe plus explicite aurait consisté à écrire :

const myDatasets = new Array();
myDatasets[0] = {data: tY[0]}
myDatasets[1] = {data: tY[1]}

et ci-dessous une syntaxe encore plus concise et obscure :

const myDatasets = tY.map(data => ({data}));

Voici une vision plus globale de l'objet configuration :

const config = {
    type: 'line',
    data: {// Objet JSON décrivant les données
        labels : tX, // Les abscisses
        datasets : [// tableau configuration des ordonnées
            { // [0]
                data: tY[0]
            }, 
            // [1]
            { 
                data: tY[1]
            }
        ],
    }
};

Cas des courbes indépendantes

On peut définir des courbes dont les ordonnées ne correspondents pas aux mêmes abscisses, comme ceci :

data: {
  datasets: [
    {
      label: "Azimut",
      data: [
        { x: 1.0, y: 10 },
        { x: 1.5, y: 20 },
        { x: 2.0, y: 30 }
      ]
    },
    {
      label: "Hauteur",
      data: [
        { x: 1.2, y: 5 },
        { x: 1.5, y: 10 },
        { x: 1.8, y: 15 }
      ]
    }
  ]
}

Au lieu de fournir pour chaque chart.data.datasets.data un tableau tY[] d'ordonnées simples, on fournit un tableau d'objets points {x:valX, y:valY}.

Les attributs des datasets

Chaque élément d'un datasets est un objet JSON ayant de nombreuses attributs en plus de l'attribut' data déjà vu. Voici les plus utiles, avec la signification de leur valeur.

Voici les valeurs utilisables pour pointStyle :

On peut utiliser une image personnalisée en fournissant un objet Image ou un chemin vers une image.

Exemple de configuration pour un graphique en lignes :

// Configuration du graphique
const config = {
    type: 'line',
    data: {
        labels: tX,
        datasets: [{
            label: "Dataset 1",
            data: tY[0],
            borderColor: "yellow",
            borderWidth: 2,
            pointStyle : "rect",
            pointBorderColor: "red",
            pointBackgroundColor: "green",
            pointRadius : 10

        }, {
            label: "Dataset 2",
            data: tY[1],
            backgroundColor: "yellow",
            borderColor: "blue",
            borderWidth: 2
        }]
    }
};

Les options (Chart.options)

Le troisième attribut options de l'argument config du constructeur est, comme son nom l'indique, optionnel. Il permet de configurer divers aspects du graphique, tels que les échelles, les légendes, les titres, et bien plus encore.
Voici quelques-uns des principaux attributs que l'on peut utiliser dans cet objet :

layout: {
    padding: {left: 10, right: 10, top: 10, bottom: 10}
}
elements: {
    line: {tension: 0.4, borderWidth: 2},
    point: {radius: 5, backgroundColor: 'rgba(0, 0, 0, 1)'
    }
}

Les échelles (Chart.options.scales)

Les graduations des échelles sont configurées au moyen de l'objet attribué à la propriété Chart.options.scales. cet objet possède les attributs x pour l'échelle des abscisses, y pour l'échelle des ordonnées et r dans le cas d'un graphique de type radial.

Attributs de x, y et/ou r

Les principaux attributs que l'on utilise pour x, y et r sont :

Exemple :

scales: {
    x: {beginAtZero: true, type: 'linear', position: 'bottom'},
    y: {min: -10, max: 40, position: 'right'}
}

Pour la légende de l'axe (title) on utilise les attributs classique d'une légenge. Exemple :

    x: {
        title: {
            display: true,       // ← rend le titre visible, invisible par défaut
            text: 'Temps (s)',   // ← le texte du titre
            color: 'black',
            font: {size: 14, weight: 'bold'}
        }
    },
    y: {
        title: {
            display: true,
            text: 'Vitesse (m/s)'
        }
    }

Échelles multiples

Les attributs x et y sont des attributs par défaut offerts pour les labels et l'ensemble des datasets, mais on peut définir un échelle individualisée pour un dataset en fournissant un nom d'attribut d'échelle spécifique pour ce dataset, à l'aide de l'attribut Chart.data.datasets[i].yAxisID. Par défaut on a yAxisID:'y' quand rien n'est spécifié, mais on peut mettre yAxisID:'y2' ce qui permet ensuite d'utiliser y2 comme attribut pour définir les échelles de ce dataset :

options: {
    scales: {
        y: {type: 'linear', display: true, position: 'left',
        },
        y2: {type: 'linear', display: true, position: 'right',
            grid: {drawOnChartArea: false,}, // Désactive le quadrillage pour cet axe
        },
        x: {type: 'category',display: true,}
    }

Les plugins (Chart.options.plugins)

L'attribut Chart.options.plugins permet de préciser de nombreux éléments du graphique, comme les légendes des différentes courbes, le titre général, les tooltips....

Les légendes (Chart.options.plugins.legend)

Cette rubrique fixe les propriétés des légendes également appelés labels qui sont les noms associés à chaque graphe ou courbe, ainsi que le titre général. Les légendes sont configurées par Chart.defaults.plugins.legend (on n'intervient généralement pas à ce niveau) et par Chart.options.plugins.legend, à l'aide des attributs suivants :

Titre (Chart.options.plugins.legend.title)

Les propriétés du titre sont définies dans Chart.options.plugins.legend.title. Ses principaux attributs sont :

Les Labels (Chart.options.plugins.legend.labels)

Ce sont les étiquettes affichant les noms de chacune des courbes. Leurs propriétés globales sont fixées par les attributs de Chart.options.plugins.legend. L'attribut spécifique Chart.options.plugins.legend.labels permet d'agir individuellement sur chacun d'eux par le biais da la fonction Filter décrite ci'après.

Fontion filter

La fonction filter permet de masquer sélectivement certains éléments, comme des légendes ou des graduations. Pour cela, dans le champ options.plugins.legend.labels, on utilise l'attribut filter : avec pour valeur une callback function(item, chart) où l'argument item est le label testé (le deuxième argument chart qui est l'objet Chart est facultatif). Cette callback renvoie true si le label doit être pris en compte et false s'il doit être ignoré. Ainsi, pour ne pas écrire la légende du label intitulé "Graphique 2", on ajoutera le couple :
filter: item => item.text !== 'Graphique 2'
qui est un raccouci pour :
filter: function(item) {return item.text !== 'Graphique 2';}

En plus de
'options.plugins.legend.labels.filter,
la fonction filter peut être utilisée pour valider/invalider des ticks en x ou en y, avec :
options.scales.x.ticks.filter
et
options.scales.y.ticks.filter.

tooltip

Dans la rubrique de l'attribut tooltip on peut au moyen de l'attibut callbacks faire de nombreuses modifications. Voici par exemple comment modifier le texte des popups qui affichent les coordonnées des points sélectionnés qui en standard sont limités à :
x: <valeur>
<label du dataset>: <valeur y>
Pour ajouter un texte devant la valeur des abscisses on fera :

options: {
  plugins: {
    tooltip: {
      callbacks: {
        title: function(tooltipItems) {
          // tooltipItems est un tableau, on prend le premier (il y en a un par point survolé)
          const xValue = tooltipItems[0].parsed.x;
          return 'Temps : ' + xValue.toFixed(1) + ' s';
        }
      }
    }
  }
}

Pour modifier le label qui apparait devant la valeur des ordonnées c'est un peu plus complexe lorsqu'il y a plusieurs courbes. Voici un exemple qui correspond au fait qu'o a deux courbes dans la rubrique datasets avec pour labels 'Azimut' et 'Hauteur', comme ceci :

      datasets: [
        {
            label: 'Azimut',
            ............. 
        },
        {
            label: 'Hauteur',
            ......
        }

La modification des labels des tooltips se fera par exemple comme ceci :

            tooltip: {
                callbacks: {
                  title: function(tooltipItems) { // Modif label des x
                    const xValue = tooltipItems[0].parsed.x;
                    return 'Angle hor. : ' + xValue.toFixed(3) + ' h';

                  },
                  label: function(tooltipItem) {  // Modif label des y
                    const y = tooltipItem.parsed.y;
                    const datasetLabel = tooltipItem.dataset.label;
                    if (datasetLabel === 'Azimut') {
                      return 'Azimut : ' + y.toFixed(2) + '°';
                    } else if (datasetLabel === 'Hauteur') {
                      return 'Hauteur : ' + y.toFixed(2) + '°';
                    } else {
                      return datasetLabel + ' : ' + y.toFixed(2);
                    }
                  }
                }
              }  

modification qui nécessite de tester le tooltipItem.dataset.label pour savoir pour quelle des 2 courbes la callback est appelée.

Animations (Chart.options.animations)

l’attribut Chart.options.animations permet d’animer toutes les propriétés numériques, toutes les couleurs, toutes les propriétés définies dans les datasets ou dans les éléments de type (comme elements.line, elements.point...).
Attention : Même non renseignée, une animation par défaut est appliquée à chaque update du graphique pour le rendre plus fluide, ce qui ralentit considérablement cet update. Il faut donc donner la valeur false à animation pour interdire des interpolations entre l'ancien graphique et le nouveau lorsqu'on désire des updates instantanés.
Voici une liste des attributs couramment utilisés pour des animations :

La valeur modifiée l'est par le biais d'un objet animation ayant les attributs suivants :

Pour aller, sur la durée duration, de la valeur initiale à la valeur finale, on utilise une des fonctions d'avance temporelle suivantes :

Annotations

Annotations est un plugin additionnel qui permet d'ajouter des lignes, des marques, du texte... que l'on peut utiliser en incluant le script :
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/1.4.0/chartjs-plugin-annotation.js"></script>
ou bien :
src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@1.4.0/dist/chartjs-plugin-annotation.min.js"></script>

Les éléments additionnels sont définis dans Chart.options.plugins.annotation.annotations sous un nom d’attribut arbitraire. Ce nom est libre (ex. maLigne) et c’est le contenu de l’objet qui en détermine la nature.. Exemple pour ajouter une ligne horizontale d'ordonnée y = 20 :

options: { plugins: { annotation: {annotations: {
    maLigne: {type: 'line', yMin: 20, yMax: 20}}}}}

Les attributs les plus fréquemment utilisés pour spécifier les éléments additionnels sont :

Dans le cas d'une ligne horizontale, on n'utilisera que yMin et yMax avec la même valeur. Dans le cas d'une ligne verticale, on n'utilisera que xMin et xMax avec la même valeur.

Des problèmes de positionnement (offsets) peuvent survenir si les axes (scales) ne sont pas explicitement définis.

Interaction avec la souris

Pour l'interaction avec la souris, lors d'un événement mousedown, pour savoir où il s'est produit on utilise la méthode getElementsAtEvent:

const tabElem = chart.getElementsAtEventForMode(event, mode, options, useFinalPosition)

où :

{
  datasetIndex: 0, // Index de la courbe (du dataset)
  index: 3, // index de l'abscisse de l'élément 
  element: {...} // objet graphique (point, barre…)
}

Généralement on cherche à obtenir les coordonnées d'un point du graphique. Elles sont obtenues par :

let di = tabElem.datasetIndex; // série concernée
let pi = tabElem.index;        // position dans cette série
let x = chart.data.labels[pi];
let valeur = chart.data.datasets[di].data[pi];

Pour placer un point au niveau de la souris, il faut convertir les coordonnées souris en coordonnées graphique. Les coordonnées de la souris sont données par :

mouseX = evt.offsetX;
mouseY = evt.offsetY;

Il faut vérifier que ces coordonnées sont à l'intérieur du domaine graphique :

(mouseX >= chart.chartArea.left && mouseX <= chart.chartArea.right)
(mouseY >= chart.chartArea.top && mouseY <= chart.chartArea.bottom)

Elles sont converties en coordonnées trajectoire par :

const xValue = (chart.scales.x).getValueForPixel(mouseX);
const yValue = (chart.scales.y).getValueForPixel(mouseY);