====== Chart.js ======
Simple yet flexible JavaScript charting for designers & developers.
* https://www.chartjs.org
* https://www.chartjs.org/docs/
===== Plugins =====
==== AlignZero ====
Aligner les zéros des axes Y.
/**
* Plugin pour aligner les zéros des axes Y multiples dans un graphique Chart.js.
* Ce plugin ajuste dynamiquement les échelles des axes Y pour que leurs zéros soient alignés,
* améliorant ainsi la lisibilité des graphiques avec plusieurs axes Y.
*
* Fonctionnement :
* 1. Calcule le ratio de zéro pour chaque axe Y (proportion de l'axe en dessous de zéro)
* 2. Détermine le ratio dominant parmi tous les axes
* 3. Ajuste les échelles des autres axes pour qu'ils utilisent le même ratio dominant
* 4. Met à jour le graphique pour appliquer les nouvelles échelles
*
* Le plugin s'exécute une seule fois après la mise en page initiale du graphique
* et évite les boucles infinies en utilisant un drapeau _alignZeroRunning.
*/
const alignZeroPlugin = {
id: 'alignZero',
_alignZeroRunning: false,
afterLayout(chart) {
if (this._alignZeroRunning)
return;
this._alignZeroRunning = true;
const yAxes = Object.values(chart.scales).filter(s => s.axis === 'y');
if (yAxes.length < 2) return;
const getZeroRatio = (min, max) => {
if (min >= 0) return 0;
if (max <= 0) return 1;
return Math.abs(min) / (Math.abs(min) + Math.abs(max));
};
const ratios = yAxes.map(ax => getZeroRatio(ax.min, ax.max));
const dominantRatio = Math.max(...ratios);
if (dominantRatio === 0 || dominantRatio === 1)
return;
yAxes.forEach((ax, i) => {
if (getZeroRatio(ax.min, ax.max) !== dominantRatio) {
const absMax = Math.max(Math.abs(ax.min), Math.abs(ax.max));
const newMin = Math.round(-absMax * (dominantRatio / (1 - dominantRatio)));
const newMax = Math.round(absMax * ((1 - dominantRatio) / dominantRatio));
// Écriture dans les options pour que Chart.js en tienne compte
const scaleId = ax.id;
chart.options.scales[scaleId].min = ax.min < 0 ? ax.min : newMin;
chart.options.scales[scaleId].max = ax.max > 0 ? ax.max : newMax;
}
});
// Forcer le recalcul des scales avec les nouvelles options
chart.update('none'); // 'none' = pas d'animation, pas de boucle infinie
this._alignZeroRunning = false;
}
};
==== Crosshair ====
Ligne de viseur (crosshair) sur toute la hauteur de l'axe Y.
/**
* Plugin pour afficher une ligne de viseur (crosshair) verticale sur le graphique.
* Ce plugin permet de visualiser plus facilement les valeurs des données en traçant
* une ligne verticale qui suit le mouvement de la souris.
*
* Fonctionnement :
* 1. Initialise un objet crosshair dans le contexte du graphique pour suivre la position X
* 2. Écoute les événements de la souris (mousemove et mouseout)
* 3. Dessine une ligne verticale à la position actuelle de la souris lors du survol
* 4. Supprime la ligne lorsque la souris quitte la zone du graphique
*
* La ligne de viseur est dessinée avec une opacité réduite pour ne pas masquer les données
* et s'étend sur toute la hauteur de l'axe Y du graphique.
*/
const crosshairPlugin = {
id: 'customCrosshair',
afterInit(chart) {
chart.crosshair = { x: null };
},
afterEvent(chart, { event }) {
if (!chart.crosshair) chart.crosshair = { x: null };
if (event.type === 'mousemove') {
chart.crosshair.x = event.x;
chart.draw();
} else if (event.type === 'mouseout') {
chart.crosshair.x = null;
chart.draw();
}
},
afterDraw(chart) {
if (!chart.crosshair || chart.crosshair.x == null) return;
const y = chart.scales.y;
if (!y) return;
const ctx = chart.ctx;
ctx.save();
ctx.beginPath();
ctx.moveTo(chart.crosshair.x, y.top);
ctx.lineTo(chart.crosshair.x, y.bottom);
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(0,0,0,0.4)';
ctx.stroke();
ctx.restore();
}
};