web-dev-qa-db-fra.com

Dessinez un fichier Chart.js avec des données ajax et responsive. Quelques problèmes et questions

J'utilise Chart.js ( http://www.chartjs.org/docs/ ) pour la création de graphiques.

Je dois obtenir les données d'une demande Ajax et le graphique pour être réactif. 

Dans mon code HTML, j'ai ajouté un canevas comme suit:

<div>
  <canvas id="userscreated" class="plot" data-url="/stats/userscreated"></canvas>
</div>

Et dans mon code javascript (JQuery), j'ai:

var data2;

$.ajax({
  url: $('#userscreated').data('url'),
  async: true,
  dataType: 'json',
  type: "get",
}).done(function (data) {

    data2 = data;

    // Draw chart
    var context = $('#userscreated').get(0).getContext("2d");
    var wrapper = $('#userscreated').parent();
    var width = $('#userscreated').attr('width', $(wrapper).width());

    new Chart(context).Line(
    {
      labels: data.Dates,
      datasets: [
        { fillColor: #404040, data: data.Users }
      ]
    },
    { animation: false }
  );

});

// Redraw the chart with the same data
$(window).resize(function () {

  var context = $('#userscreated').get(0).getContext("2d");
  var wrapper = $('#userscreated').parent();
  var width = $('#userscreated').attr('width', $(wrapper).width());

  new Chart(context).Line(
    {
      labels: data2.Dates,
      datasets: [
        { fillColor: #404040, data: data2.Users }
      ]
    },
    { animation: false }
  );

});

PROBL&EGRAVE;MES

  1. Le graphique n'est pas redimensionné lors du redimensionnement de la fenêtre.
  2. Y a-t-il un meilleur code pour le faire? Je pense que je répète trop de code.
  3. Dans Google le dessin est rapide. Dans Firefox, il se bloque parfois pendant un certain temps… .. Quelque chose ne va pas avec mon code?
  4. La demande doit-elle être asynchrone ou non?
16
Miguel Moura

Vous pouvez effectuer des appels asynchrones AJAX sans problème. Il est simplement important que vous configuriez le graphique uniquement après le déclenchement du rappel. Sinon, vous aurez des problèmes avec le contexte de votre toile non défini. Le premier appel à respondCanvas effectue la configuration initiale, tandis que les appels suivants effectuent le redimensionnement.

Voici ce qui fonctionne pour moi:

var max = 0;
var steps = 10;
var chartData = {};

function respondCanvas() {
    var c = $('#summary');
    var ctx = c.get(0).getContext("2d");
    var container = c.parent();

    var $container = $(container);

    c.attr('width', $container.width()); //max width

    c.attr('height', $container.height()); //max height                   

    //Call a function to redraw other content (texts, images etc)
    var chart = new Chart(ctx).Line(chartData, {
        scaleOverride: true,
        scaleSteps: steps,
        scaleStepWidth: Math.ceil(max / steps),
        scaleStartValue: 0
    });
}

var GetChartData = function () {
    $.ajax({
        url: serviceUri,
        method: 'GET',
        dataType: 'json',
        success: function (d) {
           chartData = {
                labels: d.AxisLabels,
                datasets: [
                    {
                        fillColor: "rgba(220,220,220,0.5)",
                        strokeColor: "rgba(220,220,220,1)",
                        pointColor: "rgba(220,220,220,1)",
                        pointStrokeColor: "#fff",
                        data: d.DataSets[0]
                    }
                ]
            };

            max = Math.max.apply(Math, d.DataSets[0]);
            steps = 10;

            respondCanvas();
        }
    });
};

$(document).ready(function() {
    $(window).resize(respondCanvas);

    GetChartData();
});

Si vous souhaitez insérer un léger délai entre les appels, vous pouvez utiliser un délai d’expiration:

$(document).ready(function() {
    $(window).resize(setTimeout(respondCanvas, 500));

    GetChartData();
});

Le délai rendra votre redimensionnement plus réactif si vous avez un jeu de données volumineux sur votre graphique.

18
Cameron Tinker

vous pouvez définir cela dans chart.js

new Chart(context, {
  type:"line",
  labels: data.Dates,
  datasets: [
    { fillColor: #404040, data: data.Users }
  ]
  options: { responsive: false }
});
4
melon24
  1. Effectivement
  2. Oui, je vais vous donner un exemple.
  3. Je ne vois rien qui puisse causer un problème. Sauf que window.resize peut déclencher le rendu d'un nouveau graphique beaucoup plus souvent que vous le souhaitez.
  4. Non (je ne sais pas vraiment pourquoi, c'est plus une coïncidence.)

Le code:

window.getVisitCounts = ($canvas) ->
    url = Routes.visits_between_project_path($canvas.data('project-id'), {
        format: "json",
        start: $canvas.data('start'),
        end: $canvas.data('end')
    })


visits = []
days = []

 $.ajax
 url: url,
 async: false,
 dataType: "json",
 type: "GET",
 success: (data) - >
 for point in data.chart.data
 visits.Push(point.visits)
 days.Push(point.date)

 {
     days: days,
     visits: visits
 }

 window.createChartData = (raw) - > {
     labels: raw.days,
     datasets: [{
         fillColor: "rgba(151,187,205,0.5)",
         strokeColor: "rgba(151,187,205,1)",
         pointColor: "rgba(151,187,205,1)",
         pointStrokeColor: "#fff",
         data: raw.visits,
     }]
 }

 window.setupCanvas = ($canvas, data) - >
     newWidth = $canvas.parent().width()

 $canvas.prop
 width: newWidth
 height: 400

 options = {
     scaleOverride: true,
     scaleSteps: 10,
     scaleStepWidth: Math.ceil(Math.max.apply(Math, data.datasets[0].data) / 10),
     scaleStartValue: 0
 }

 ctx = $canvas.get(0).getContext("2d")
 new Chart(ctx).Line(data, options)

 $ - > @canvas = $("#analytics-canvas")
 if@ canvas.length != 0@ visits = window.createChartData(window.getVisitCounts(@canvas))
 window.setupCanvas(@canvas, @visits)

 $(window).on('resizeEnd', - >
     setupCanvas(document.canvas, document.visits)
 )

 $(window).resize - >
 if (@resizeTO)
     clearTimeout(@resizeTO)

 @resizeTO = setTimeout(- >
     $(this).trigger "resizeEnd"
     500
 )
0
Senjai