Hé ben, avec la méthode Highcharts décrite ici, ça marche pas
Pourquoi
- 1: Lorsqu'il y a plusieurs courbes sur un même graphique, seul le plus grand maxi des courbes est pris.
- 2: Également, seul le plus petit mini des courbes est pris.
- 3: Lorsque la courbe est de type "areaspline", si le maxi est bon, la valeur du mini est toujours 0
Mais alors, comment qu-c'est-y qui fait
Rien de plus simple en apparence, il faut ruser et dupliquer les yAxis et les series[] . Cependant, pour que subterfuge fonctionne, il faut prendre quelques précautions pour ne pas voir le double des courbes et des yAxis. C'est ce que je vais expliquer dans ce tuto.
Dans ce tuto, je fait volontairement abstraction du code pour la connexion à la BDD, l'extraction des données, l'encodage en json, etc..., Pierre-André l'a très bien fait dans sont tuto Tutoriel MySQL - Highcharts.
Le tuto suivant prend en exemple, ce graphique Le vent des dernières 48 heures.
Dans un premier temps, il vous faut un petit script que j'ai trouver sur le net pour mettre en forme les nombres du résultat.
Code : Tout sélectionner
// Copyright (c) 2003 cnx.claude
function ValideNombre(Objet) {
//var checkOK = "0123456789-.+";
var checkStr = Objet.value;
var allValid = true;
//var validGroups = true;
//var decPoints = 0;
//var allNum = "";
//élimine les espaces Mise en forme préparatoire
modele= / /g;
checkStr=checkStr.replace(modele,"");//remplace les espaces par rien donc élimine les espaces
Objet.value=checkStr;
//recherche + et - vérifie si c'est bien la première position
modele= /[+-]/;
retour1=modele.test(checkStr);
if (retour1) {
//retour =vrai donc + ou - ont été touvé
longueur=checkStr.length;
chaine=checkStr.substring(1, longueur);
retour2=modele.test(chaine);
if (retour2) allValid=false;// une deuxième occurence a été trouvée
}
//recherche le point décimal et vérifie l'absence d'autre point décimal dans la chaine
modele=/[.]/;
position1=checkStr.search(modele);
if (position1) {
longueur=checkStr.length;
chaine=checkStr.substring(position1+1, longueur);
//alert(chaine);
retour2=modele.test(chaine);
//alert(retour2);
if (retour2) allValid=false;// une deuxième occurence a été trouvée
}
//recherche un caractère qui soit différent de + - 0-9 et .
modele= /[^+-.\d]/;
retour=modele.test(checkStr);
if (retour) allValid=false; //un autre caractère a été trouvé!
if (!allValid) {
alert("Ne tapez que chiffre/caractères (allvalid) dans le champ " + Objet.name );
return (false);
}
return (true);
}
function formatNombre(nombre, nombreDecimale) {
//Met en forme le nombre
C=Math.pow(10, nombreDecimale);
nombre=(Math.round(nombre*C)/C);
nombre=nombre+"";
//document.write(nombre + "<br>");
longueurNombre=nombre.length;
//recherche du nombre derrière la virgule (décimale)
placePointDecimal=nombre.indexOf(".",0);
(placePointDecimal==-1)?decimale="." : decimale=nombre.substring(placePointDecimal, longueurNombre);
longueurDecimale=decimale.length;
while (longueurDecimale<=nombreDecimale) {
decimale=decimale + "0";
longueurDecimale=decimale.length;
}
if (nombreDecimale==0) decimale="";
(placePointDecimal==-1)?entier=nombre : entier=nombre.substring(0, placePointDecimal);
longueurEntier=entier.length;
chaine="";
i=1;
while (longueurEntier>0) {
Position1=longueurEntier-3;
if (Position1<0) Position1=0;
Position2=longueurEntier;
sousChaine=entier.substring(Position1, Position2);
(chaine=="")?chaine=sousChaine: chaine=sousChaine+ " " +chaine;
entier=entier.substring(0, Position1);
longueurEntier=longueurEntier-3;
i++;
}
nombreFormate=entier+chaine;
nombreFormate=nombreFormate+decimale;
/* voilà l'affichage est correct et paramètrable en nombre de décimale
toutefois le résultat obtenu est une chaine de caractère et non pas un nombre
pour retourner à nouveau un nombre utiliser la fonction retourneNombre()
*/
return nombreFormate;
}
function formatNombreFormulaire(Objet, nombreDecimale) {
//utilisable avec un formulaire
OK=ValideNombre(Objet);//vérifie que Objet est un nombre
if (OK==true) {
nombre=Objet.value;
nombreFormate=formatNombre(nombre, nombreDecimale);
/* voilà l'affichage est correct et paramètrable en nombre de décimale
toutefois le résultat obtenu est une chaine de caractère et non pas un nombre
pour retourner à nouveau un nombre utiliser la fonction retourneNombre()
*/
Objet.value= nombreFormate;
}
else {
//Objet.value="";
Objet.focus();
}
}
function retourneNombre(nombreFormate) {
//pour retrouver le nombre arrondi aux décimales près faire:
tableau = nombreFormate.split(" "); //tableau = chaine.split(" ")
longueurTableau=tableau.length; //donne la dimension du tableau
newNombre="";
for (i=0 ; i<longueurTableau; i++) {
newNombre=newNombre + tableau[i];
}
newNombre=newNombre*1;//voilà c'est un nombre!
return newNombre;
}
function firstUpperCase(chaine) {
//retourne la chaine avec sa première lettre en majuscule
position=0;// premier caractère position 0
premiereLettre= chaine.charAt(position);//isole le premier caractère
premiereLettre=premiereLettre.toUpperCase();//met en majuscule le premier caractère
//alert(premiereLettre);
position1=1;
position2=chaine.length;
souschaine=chaine.substring(position1, position2);
//alert(souschaine);
chaine= premiereLettre + souschaine;
return chaine;
}
function firstUpperCaseForm(Objet) {
//retourne la chaine avec sa première lettre en majuscule pour formulaire
chaine=Objet.value;
chaine=firstUpperCase(chaine);
Objet.value=chaine;
}
Appelez ce script avec cette ligne entre les balises <head> et </head> de votre code html
Code : Tout sélectionner
<script type="text/javascript" src="../Scripts/formatNombre.js"></script>
Toujours entre les balises <head> et </head> de votre code html ou dans votre fichier de style CSS si vous en avez un, ajouter ce code qui mettra en forme le résultat.
Code : Tout sélectionner
</style>
<style type="text/css">
.extreme_maxi {
font-family: "Comic Sans MS", cursive;
font-size: 14px;
font-weight: bolder;
text-align: left;
color: #FF0000;
}
.extreme_mini {
font-family: "Comic Sans MS", cursive;
font-size: 14px;
font-weight: bolder;
text-align: left;
color: #0000FF;
}
</style>
Voici le code de cet yAxis dans l'exemple. Il porte le numero 0
Code : Tout sélectionner
{ // 1er yAxis (numero 0 axe vitesse du vent)
gridLineWidth: 1,
opposite: false,
lineColor: '#990033',
lineWidth: 2,
tickColor: '#990033',
tickWidth: 2,
min: 0,
labels: {
y: 3,
formatter: function() {
return this.value +' km/h';
},
style: {
color: '#990033'
}
},
title: {
text: 'Vitesse (km/h)',
style: {
color: '#990033'
}
},
},
Ils portent respectivement les numéros 2 et 3. Ceci est important pour la suite
Ils portent les numéros 2 et 3 car dans mon exemple, l'yAxis 1 est celui de la direction des vents.
Voici le code que je vais expliquez après.
Code : Tout sélectionner
{ // répétition de l'yAxis 0 pour affichage getExtremes rafale (numero 2)
gridLineWidth: 0,
lineWidth: 0,
tickWidth: 0,
linkedTo: 0,
labels: {
enabled: false,
},
title: {
enabled: false
},
},
{ // répétition de l'yAxis 0 pour affichage getExtremes vitesse (numero 3)
gridLineWidth: 0,
lineWidth: 0,
tickWidth: 0,
linkedTo: 0,
labels: {
enabled: false,
},
title: {
enabled: false
},
},
Explications.
Les paramètres gridLineWidth, lineWidth, tickWidth, ont tous pour valeur 0.
Ceci permet d'avoir un yAxis qui existe et que l'on peut utiliser mais qui est totalement invisible.
L'affichage des paramètres labels et title est désactivé grace à la valeur enabled: false
Nous avons enfin un paramètre important. C'est le paramètre linkedTo. Celui-ci permet de lier l'yAxis à un autre afin que, lors d'un zoom par exemple, les échelles restent les mêmes et que les courbes continues à se chevaucher afin de rester invisibles.
Ici, ce paramètre a la valeur 0. Les deux yAxis dupliqués, sont donc liés à l'yAxis de la vitesse du vent.
Dans d'autres cas comme dans ce graphique, La pluviométrie des 31 derniers jours, les paramètres min, top, height, et offset, peuvent être nécessaire.
Maintenant, nous allons dupliquer les séries dont nous voulons les extrêmes afin de les afficher respectivement sur les yAxis que nous avons dupliqués.
Important
Le code de chaque série dupliquée, doit être immédiatement avant le code de la série à dupliquer. Ceci afin que la courbe de la série dupliquée, qui elle est visible, soit masquée par la série que l'on duplique.
Voici le code de la série rafale de vent de l'exemple.
Code : Tout sélectionner
{ // chart.serie[0] : duplication des données rafales pour affichage getExtremes sur yAxis 2
name: 'Rafale-2',
color: '#0080C0',
yAxis: 2,
type: 'spline',
showInLegend: false,
enableMouseTracking: false,
data: comArr(windgust),
},
{ // chart.serie[1] Rafale de vent
name: 'Rafale de vent',
yAxis: 0,
type: 'areaspline',
color: '#0080C0',
fillColor: {
linearGradient: [0, 0, 0, 240],
stops: [
[0, 'rgba(112, 112, 112, .8)'],
[1, 'rgba(0, 204 , 255, .3)']
]
},
events: {
legendItemClick: function () {
var chart = $('#container').highcharts(),
visibility = this.visible ? 'visible' : 'hidden';
if (visibility == "visible") {
chart.series[0].setVisible(false,true);
}
else {
chart.series[0].setVisible(true,true);
}
},
},
data: comArr(windgust),
},
},
Explications des paramètres de la série dupliquée :
- name: 'Rafale-2', : On peut donner n'importe quel nom, ça n'a aucune importance.
- color: '#0080C0', : Ce paramètre doit avoir la même valeur que celui de la série qui est dupliquée.
- yAxis: 2, : On attribue ici le numéro d'un yAxis que l'on a dupliqué.
- type: 'spline', : Impératif, le type doit être line ou spline. La méthode getExtremes ne fonctionne qu'avec ces types de graphique.
- showInLegend: false, : La valeur doit être false afin que la courbe n'apparaisse pas dans la légende.
- enableMouseTracking: false, : Ce paramètre doit avoir la valeur false. Ceci empêche l'affichage de la valeur de la courbe dans le tooltip lors du survol du graphique par la souris.
- data: comArr(windgust), : Enfin la valeur du paramètre data doit être la même que celui de la série à dupliquer.
Explications des paramètres de la série qui est dupliquée :
On retrouve tous les paramètres habituels. Pour ma part, le type "areaspline" me plait bien (affaire de gout).
Cependant, notez l’existence d'un paramètre que l'on ne croise pas souvent. Le paramètre events.
Le code de celui-ci, va permettre de masquer la courbe de la série dupliquée en même temps que la courbe de la série originale lorsque l'on cliquera sur l'Item de la légende de la série originale .
Sans cela, lorsque, dans la légende, l'on clique sur l'item de la série originale, les données de celle-ci sont masquées mais la courbe dupliquée, elle, reste visible.
- Dans un premier temps, l'on teste la visibilité de la série avec ce code :visibility = this.visible ? 'visible' : 'hidden';
- Ensuite, dans une boucle if - else, à l'aide de la commande chart.series[0].setVisible(false,true); l'on masque la série dupliquée ou chart.series[0].setVisible(true,true); l'on affiche la série dupliquée.
- chart.series[x] : x doit avoir le numéro de la série à afficher ou a masquer.
- setVisible(y,z);: y doit avoir la valeur false pour masquer et true pour afficher. z doit avoir la valeur true pour retracer le graphique lorsque l'on clique sur l'item de la série dans la légende.
Pour plus d'info, voir http://api.highcharts.com/highstock#Series.setVisible
Code : Tout sélectionner
{ // chart.serie[2] : duplication des données vitesses pour affichage getExtremes sur yAxis 3
name: 'Vent-2',
color: '#33CC66',
yAxis: 3,
type: 'spline',
showInLegend: false,
enableMouseTracking: false,
data: comArr(windspeed),
},
{ // chart.serie[3] Vitesse du vent
name: 'Vitesse du vent',
yAxis: 0,
type: 'areaspline',
color: '#33CC66',
fillColor: {
linearGradient: [0, 0, 0, 240],
stops: [
[0, 'rgba(128, 128, 128, .9)'],
[1, 'rgba(255, 255, 204, .7)']
]
},
events: {
legendItemClick: function () {
var chart = $('#container').highcharts(),
visibility = this.visible ? 'visible' : 'hidden';
if (visibility == "visible") {
chart.series[2].setVisible(false,true);
}
else {
chart.series[2].setVisible(true,true);
}
},
},
data: comArr(windspeed),
},
Remarquez également la valeur de chart.series[]. Elle a la valeur du numéro de la série duplique Vent-2.
Maintenant, nous allons voir le code qui est exécuté lorsque l'on clique sur le bouton.
Celui-ci doit être placé juste avant les }); de fermeture du code $(function () {var chart;
Le voici, les explications sont en dessous.
Code : Tout sélectionner
// the button getExtrèmes action
$('#button').click(function()
{
var Rafaleextremes = chart.yAxis[2].getExtremes(), Ventextremes = chart.yAxis[3].getExtremes()
$('#report').html(
'<span class="extreme_maxi" >'+ 'Vitesse maxi des rafales: '+ formatNombre(Rafaleextremes.dataMax,1) +' Km/h - ' +
'<span class="extreme_mini">'+'Vitesse mini des rafales: '+ formatNombre(Rafaleextremes.dataMin,1) +' Km/h ' + '<br>' +
'<span class="extreme_maxi" >'+ 'Vitesse maxi du vent: '+ formatNombre(Ventextremes.dataMax,1) +' Km/h - '+
'<span class="extreme_mini">'+'Vitesse mini du vent: '+ formatNombre(Ventextremes.dataMin,1) +' Km/h '
)
});
- On défini deux variables Rafaleextremes et Ventextremes dont on obtient les valeurs extrêmes affichée sur la courbe avec la fonction
- chart.yAxis[x].getExtremes(). La valeur de x doit être le numéro de l'yAxis dupliqué sur lequel est tracé la courbe dupliquée. Simple. Non.
- Ensuite, l'on affiche 2 <span> de classe extreme_maxi et extreme_mini (classe définie dans le style css)
- On met une légende Vitesse maxi des rafales et Vitesse mini des rafales
- Pour obtenir la valeur maxi, l'on se sert de la fonction Variable.dataMax
- Pour obtenir la valeur mini, l'on se sert de la fonction Variable.dataMin
- On met en forme la valeur des mini maxi obtenu à l'aide du fichier javascript formatNombre.js
La syntaxe de formatNombre est- formatNombre(
- la variable à mettre en forme Variable.dataMax
- suivie d'une virgule ,
- suivie d'un chiffre indiquant le nombre de chiffres après la virgule.
- fermé par un parenthèse ).
- On met enfin l'unité de mesure des données. +' Km/h '
pour afficher tout cela, dans le body de votre code html, après la div <div id="container" style="width: 1060px; height: 570px; margin: 0"></div><br> qui sert à l'affichage du graphique,
on créer un bouton
<button id="button">Afficher les extrêmes sur la plage selectionnée</button><br>
qui lorsqu'on cliquera dessus, affichera les valeurs minimales et maximales des données actuellement affichées sur la courbe dans une div dont l'id est report
<div id="report"></div>
Voila voili
That all folks
NB :pour avoir le code complet, faites un clic droit sur mon graphique puis Code source de la page.
Pascal