web-dev-qa-db-fra.com

La conversion du graphique de canevas Chart.js en image à l'aide de .toDataUrl () donne une image vide

J'utilise Chart.js. J'essaie de convertir le graphique en image en obtenant une chaîne de base 64. Le tutoriel ( http://www.chartjs.org/docs/ ) consacre une ligne entière au sujet:

L'élément canvas permet également de sauvegarder le contenu en base 64 chaîne, permettant d’enregistrer le graphique en tant qu’image.

Un élément canvas a la méthode toDataURL qui renvoie une chaîne en base64 de l'image. Cependant, lorsque je le fais, l'image qu'elle rend n'est qu'un rectangle transparent avec les dimensions du graphique et n'inclut pas le contenu du graphique. 

Voici un violon: http://jsfiddle.net/KSgV7/

Les "images" du violon sont ornées d'une bordure noire, ce qui vous permet de voir où elles sont censées se trouver, car elles ne semblent être qu'un gros bloc transparent.

Quelqu'un at-il converti avec succès un graphique Chart.js en une image?

22
chiliNUT

Le graphique semble être asynchrone et vous devrez probablement fournir un rappel lorsque l'animation est terminée, sinon le canevas sera vide.

var options = {
    bezierCurve : false,
    onAnimationComplete: done  /// calls function done() {} at end
};
24
user1693593

L’API Chart.JS a changé depuis sa publication et les exemples plus anciens ne semblaient pas fonctionner pour moi. 

HTML:

<body>
    <canvas id="canvas" height="450" width="600"></canvas>
    <img id="url" />
</body>

JS:

function done(){
  alert("haha");
  var url=myLine.toBase64Image();
  document.getElementById("url").src=url;
}

var options = {
  bezierCurve : false,
  animation: {
    onComplete: done
  }
};

var myLine = new 
   Chart(document.getElementById("canvas").getContext("2d"),
     {
        data:lineChartData,
        type:"line",
        options:options
      }
    );

http://jsfiddle.net/KSgV7/585/

10
ngalstyan

Vous devez plutôt utiliser la fonction toBase64Image() de l'API Chartjs et l'appeler une fois l'animation terminée. Donc:

var pieChart, URI;

var options = {
    animation : {
        onComplete : function(){    
            URI = pieChart.toBase64Image();
        }
    }
};

var content = {
    type: 'pie', //whatever, not relevant for this example
    data: {
        datasets: dataset //whatever, not relevant for this example
    },
    options: options        
};    

pieChart = new Chart(pieChart, content);

Exemple

Vous pouvez vérifier cet exemple et l'exécuter

var chart = new Chart(ctx, {
   type: 'bar',
   data: {
      labels: ['Standing costs', 'Running costs'], // responsible for how many bars are gonna show on the chart
      // create 12 datasets, since we have 12 items
      // data[0] = labels[0] (data for first bar - 'Standing costs') | data[1] = labels[1] (data for second bar - 'Running costs')
      // put 0, if there is no data for the particular bar
      datasets: [{
         label: 'Washing and cleaning',
         data: [0, 8],
         backgroundColor: '#22aa99'
      }, {
         label: 'Traffic tickets',
         data: [0, 2],
         backgroundColor: '#994499'
      }, {
         label: 'Tolls',
         data: [0, 1],
         backgroundColor: '#316395'
      }, {
         label: 'Parking',
         data: [5, 2],
         backgroundColor: '#b82e2e'
      }, {
         label: 'Car tax',
         data: [0, 1],
         backgroundColor: '#66aa00'
      }, {
         label: 'Repairs and improvements',
         data: [0, 2],
         backgroundColor: '#dd4477'
      }, {
         label: 'Maintenance',
         data: [6, 1],
         backgroundColor: '#0099c6'
      }, {
         label: 'Inspection',
         data: [0, 2],
         backgroundColor: '#990099'
      }, {
         label: 'Loan interest',
         data: [0, 3],
         backgroundColor: '#109618'
      }, {
         label: 'Depreciation of the vehicle',
         data: [0, 2],
         backgroundColor: '#109618'
      }, {
         label: 'Fuel',
         data: [0, 1],
         backgroundColor: '#dc3912'
      }, {
         label: 'Insurance and Breakdown cover',
         data: [4, 0],
         backgroundColor: '#3366cc'
      }]
   },
   options: {
      responsive: false,
      legend: {
         position: 'right' // place legend on the right side of chart
      },
      scales: {
         xAxes: [{
            stacked: true // this should be set to make the bars stacked
         }],
         yAxes: [{
            stacked: true // this also..
         }]
      },
      animation : {
         onComplete : done
      }      
   }
});

function done(){
    alert(chart.toBase64Image());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx" width="700"></canvas>

Vous pouvez accéder à afterRender hook en utilisant plugins.

Et ici sont tous les plugins api disponibles.

En fichier html:

<html>
  <canvas id="myChart"></canvas>
  <div id="imgWrap"></div>
</html>

En fichier js:

var chart = new Chart(ctx, {
  ...,
  plugins: [{
    afterRender: function () {
      // Do anything you want
      renderIntoImage()
    },
  }],
  ...,
});

const renderIntoImage = () => {
  const canvas = document.getElementById('myChart')
  const imgWrap = document.getElementById('imgWrap')
  var img = new Image();
  img.src = canvas.toDataURL()
  imgWrap.appendChild(img)
  canvas.style.display = 'none'
}
0
Lulala Chen