Version de Chart.js et activation du zoom

Bonjour à toutes et à tous,

Dans mon application de routeur photovoltaïque, je souhaite activer le zoom sur l'un des mes graphiques.

J'ai lu sur la toile qu'il faut ajouter un plug-in, mais que ce plug-in est fonction de la version de Chart.js que l'on a. Or, les seules indications que j'ai sont la ligne de chargement :

      <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

Après, pour utiliser le plug-in, j'ai vu qu'il faut faire :

> npm install chartjs-plugin-zoom

Étant sous Windows, comment je fais ... et question que je me pose, ce plug-in est-il attaché à un PC ou smartphone ou bien est-il lié à mon application comme Chart.js lui-même ?

Cordialement.

Pierre

Votre page web charge Chart.js via un CDN que vous ne contrôlez pas donc ce n’est pas la bonne méthode

Je pense que vous pouvez aussi charger le plugin depuis un CDN en ajoutant à votre page :

<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>

Vérifiez que c’est le bon lien (mais ça répond bien un fichier js qui semble correspondre)

Merci J-M-L pour ce lien.

En fait, en cherchant mieux, j'avais trouvé aussi à ce lien.

Je l'ai rajouté à mon application ainsi que celui relatif à Hammer.js. J'ai tout recompilé et relancé : pas de problème. Pour autant, je n'ai pas encore mis en œuvre le zoom ... à venir (pas avant vendredi).

Cordialement.

Pierre.

OK oui Hammer.js permet de gérer les gestes sur les appareils mobiles / à écran tactile

J'ai installé les fonctions zoom et pan. Autant la fonction zoom fonctionne à merveille, autant le fonction pan ne veut rien savoir, même en lui donnant les différents paramètres possible.

NOTA : ces deux fonctions sont appliquées à un fichier comportant un jeu de 2880 données. Chaque jeu de données correspond à trois courbes. Le code correspondant est le suivant :

          options: {
            plugins: {
              zoom: {
                zoom: {
                  drag: { // En sélectionnant une zone autour de la valeur à zoommer
                    enabled: true,
                  },
                  wheel: { // Avec la molette de la souris
                    enabled: true,
                  },
                  pinch: { // En pincement avec deux doigts sur un écran tactile
                    enabled: true,
                  },
                  mode: 'x',
                },
                pan: { // même avec les différentes options, ça ne veut rien savoir
                  enabled: true,
                  mode: 'x',
                },
              },
            },

Une idée du problème ?

Cordialement.

Pierre.

Je crois que vous pouvez ajouter des événements pour vérifier si le pan est détecté, un truc comme cela

      pan: {
        enabled: true,
        mode: 'x',
        onPan: ({ chart }) => console.log('Debut Pan'),
        onPanComplete: ({ chart }) => console.log('Fin Pan'),
      }

Et regardez la console du navigateur

Pour être sûr que je verrai quelque chose, j'ai ajouté les mêmes messages dans la partie Zoom : Quand j'active le zoom, j'obtiens bien des messages dans la console.

Quand j'active le pan : aucun message ne s'affiche.

Dans la partie pan, il est dit que c'est la touche shift qui est activée par défaut. Si j'appuie sur cette touche en même temps que je drag la souris, c'est le zoom qui s'active.

NOTA : quand le zoom s'active, une zone grisée s'affiche sur la zone balayée avant que je relâche la souris pour que le zoom agisse.

Dans les options pan, j'ai déclaré la touche ctrl avec modifierKey: 'ctrl',. Dès lors, quand j'appuie sur cette touche et que je drag avec la souris, la zone grise n'apparaît plus. Quelque chose a donc bien été pris en compte. Pour autant, pas de pan ni de message dans la console.

Cordialement.

Pierre.

Tu as essayé de redéfinir la callback onPanStart, pour voir si elle est appelée ?

J'ai inclus :

                  onPan: ({ chart2 }) => console.log('Debut Pan'),
                  onPanStart: ({ chart2 }) => console.log('Lancement Pan'),
                  onPanComplete: ({ chart2 }) => console.log('Fin Pan'),

Ça ne donne rien. Mais peut-être n'est-ce pas la bonne syntaxe ?

Cordialement.

Pierre.

Tu pourrais redonner ton code globale

Quel code : le sketch, le HTML, le script ?

Cordialement.

Pierre.

toujours le HTML avec ce que tu as rajouté pour la gestion du plugin de zoom
Histoire que je teste sur la même chose que toi.

Voilà, voilà :

String pageHTML = R"rawliteral(
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>ESP32 Routeur photovoltaïque</title>
      <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.js"></script>
<!--      <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> -->
      <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
    </head>
    <body onload="init();">
      <h1 style="text-align: center;">ESP32 Routeur photovoltaïque</h1>
      <div style="text-align: center;">
        <button id="maj-DT">MaJ Date & Heure</button>
        <button onclick="updateChart(1);" class="button button-data">Forme Courant &amp; Tension</button> 
        <button onclick="updateChart(2);" class="button button-data">Historique Puissance</button>
        <a href="download-data"><button class="button button-data">Télécharger les données</button></a>
      </div>
      <div id = "txt1">
        <p>Date et Heure : <span id="DetH">0.00</span></p>
        <p>Puissance active (W) : <span id="PA">0.00</span></p>
      </div>
      <div id = "txt2">
        <p>Puissance max : <input type="number" id="pMaxMod" value="1000" min="0"> <button onclick="ajusterPmax()">Ajuster</button></p>
      </div>
      <canvas id="myChart1" width="800" height="300" style="display: none"></canvas>
      <canvas id="myChart2" width="800" height="300" style="display: none"></canvas>

      <script>
        let txt1 = document.getElementById("txt1");
        let txt2 = document.getElementById("txt2");

        const interval = 2000;
        let intervalId = -1;
        let pAjustee = 1000;  // Limite par défaut du nombre de points affichés

        function init() {
          txt1.style.display = "none";
          txt2.style.display = "none";
        }

        function ajusterPmax() {
          const newPmax = document.getElementById('pMaxMod').value;
          const parsedPmax = parseInt(newPmax, 10);  // On force la base 10 pour la conversion
          if (!isNaN(parsedPmax) && parsedPmax > 0) {
            pAjustee = parsedPmax;
            chart2.options.scales.y0.max = pAjustee;
            chart2.update();
            fetch('/modifVal?val='+pAjustee);
          }
        }
      
        document.getElementById('maj-DT').addEventListener('click', function() {
          fetch('/maj-DT')
            .then(response => response.text())
            .then(data => {
              document.getElementById('DetH').textContent = data;
            });
        });

        const ctx1 = document.getElementById('myChart1').getContext('2d');
        const chart1 = new Chart(ctx1, {
          type: 'line',
          data: {
            labels: [],
            datasets: [{
              label: "Tension",
              yAxisID: 'y0',
              data: [],
              borderColor: 'rgb(75, 192, 192)',
              tension: 0.3 // Filtrage du signal ; doit être compris entre 0 (pas de filtrage) et 1 (filtrage max)
            },
            {
              label: "Courant",
              yAxisID: 'y1',
              data: [],
              borderColor: 'rgb(192, 192, 75)',
              tension: 0.3
            }]
          },
          options: {
            scales: {
              x: {
                display: true,
                title : {
                  display: true,
                  text: 'Echantillons',
                }
              },
              y0: {
                display: true,
                position: 'left',
                title : {
                  display: true,
                  text: 'Tension (V)',
                }
              },
              y1: {
                display: true,
                position: 'left',
                title : {
                  display: true,
                  text: 'Courant (A)',
                }
              }
            }
          }
        });

        const ctx2 = document.getElementById('myChart2').getContext('2d');
        const chart2 = new Chart(ctx2, {
          type: 'line',
          data: {
            labels: [],
            datasets: [{
              pointRadius: 0,
              label: "Historique Puissance",
              yAxisID: 'y0',
              data: [],
              borderColor: 'blue',
              tension: 0.3 // Filtrage du signal ; doit être compris entre 0 (pas de filtrage) et 1 (filtrage max)
            },
            {
              pointRadius: 0,
              label: "Historique Tension",
              yAxisID: 'y1',
              data: [],
              borderColor: 'green',
              tension: 0.3
            },
            {
              pointRadius: 0,
              label: "Historique Courant",
              yAxisID: 'y2',
              data: [],
              borderColor: 'red',
              tension: 0.3
            }]
          },
          options: {
            plugins: {
              zoom: {
                zoom: {
                  drag: { // En sélectionnant une zone autour de la valeur à zoommer
                    enabled: true,
                  },
                  wheel: { // Avec la molette de la souris
                    enabled: true,
                  },
                  pinch: { // En pincement avec deux doigts sur un écran tactile
                    enabled: true,
                  },
                  mode: 'x',
                  onZoom: ({ chart2 }) => console.log('Debut Zoom'),
                  onZoomComplete: ({ chart2 }) => console.log('Fin Zoom'),
                },
                pan: {
                  enabled: true,
                  mode: 'x',
                  modifierKey: 'ctrl',
                  onPan: ({ chart2 }) => console.log('Debut Pan'),
                  onPanStart: ({ chart2 }) => console.log('Lancement Pan'),
                  onPanComplete: ({ chart2 }) => console.log('Fin Pan'),
                },
              },
            },
            scales: {
              x: {
                display: true,
                title : {
                  display: true,
                  text: 'Date et heure',
                }
              },
              y0: {
                min : 0,
                max : pAjustee,
                display: true,
                position: 'right',
                title : {
                  display: true,
                  text: 'Puissance (W)',
                }
              },
              y1: {
                min : 0,
                max : 300,
                display: true,
                position: 'left',
                title : {
                  display: true,
                  text: 'Tension (V)',
                }
              },
              y2: {
                min : 0,
                max : 20,
                display: true,
                position: 'left',
                title : {
                  display: true,
                  text: 'Courant (A)',
                }
              }
            }
          }
        });

        function updateChart(type) {
          if (type == 1) {

            fetch('/maj-DT')
              .then(response => response.text())
              .then(data => {
                document.getElementById('DetH').textContent = data;
              });

            fetch('/pActive')
              .then(response => response.text())
              .then(data => {
                document.getElementById('PA').textContent = data;
              });

            if (intervalId == -1) {
              intervalId = setInterval(updateChart, interval, 1);
            }
            fetch('/formeUI')
            .then(response => response.text())
            .then(data => {
              const rows = data.split('\n');
              const labels = [];
              const values0 = [];
              const values1 = [];
              let indx = 0;
              rows.forEach(row => {
                const [value0, value1] = row.split(',');
                labels.push(indx++);
                values0.push(parseFloat(value0));
                values1.push(parseFloat(value1));
              });             
              chart1.data.labels = labels;
              chart1.data.datasets[0].data = values0;
              chart1.data.datasets[1].data = values1;
              chart1.update();
            });
            txt1.style.display = 'block';
            txt2.style.display = 'none';
            document.getElementById('myChart1').style.display = 'block';
            document.getElementById('myChart2').style.display = 'none';
          } else {
            if (intervalId != -1) {
              clearInterval(intervalId);
            }
            intervalId = -1;
            fetch('/histoUIP')
//            fetch('/histo')
            .then(response => response.text())
            .then(data => {
              const rows = data.split('\n');
              const labels = [];
              const values0 = [];
              const values1 = [];
              const values2 = [];
              let indx = 0;
              rows.forEach(row => {
                const [label, value0, value1, value2] = row.split(',');
//              const [value0, value1, value2] = row.split(',');
              labels.push(label);
//              labels.push(indx++);
                values0.push(parseFloat(value0));
                values1.push(parseFloat(value1));
                values2.push(parseFloat(value2));
              });   
              chart2.resetZoom();          
              chart2.data.labels = labels;
              chart2.data.datasets[0].data = values0;
              chart2.data.datasets[1].data = values1;
              chart2.data.datasets[2].data = values2;
              chart2.update();
            });
            txt1.style.display = 'none';
            txt2.style.display = 'block';
            document.getElementById('myChart1').style.display = 'none';
            document.getElementById('myChart2').style.display = 'block';
          }
        }

      </script>
    </body>
    </html>
  )rawliteral";

Si vous mettez juste chart je pense que ça représente dynamiquement le graphique en cours d'utilisation dans le contexte d'un événement (zoom ou pan) mais ça devrait aussi fonctionner avec la variable de votre chart

Effectivement, j'ai changé chart2 en chart puis en brouette, ça n'a rien changé aux résultats : la console voir toujours les évènements zoom et ne voit jamais ceux de pan.

Cordialement.

<Pierre.

Je n’ai pas accès à mes jouets pour tester en ce moment…

Essayez de charger hammer.js avant chart.js

Je pensais avoir déjà essayé cette solution. Il faut croire que non ou pas de la bonne manière car, effectivement, plaçant hammer.js avant chart.js, le pan fonctionne.

      <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>

Merci beaucoup.

Pierre.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.