相关文章推荐
暴走的电池  ·  python ...·  2 年前    · 

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more

I am using Chart.js ( http://www.chartjs.org/docs/ ) for charting.

I need to get the data from an Ajax request and the chart to be responsive.

In my HTML code I added a canvas as follows:

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

And in my javascript (JQuery) code I have:

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 }

PROBLEMS

  • The chart is not being resized on window resize.
  • Is there better code to do this? I think I am repeating to much code.
  • In Google the drawing is fast. In firefox sometimes it hangs for a while. Is anything wrong with my code?
  • Should the request be async or not?
  • You can make async AJAX calls no problem. It's just important that you setup the chart only after the success callback fires. Otherwise, you'll get issues with your canvas context not being defined. The first call to respondCanvas does the initial setup while the subsequent calls do the resizing.

    Here is what works for me:

    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();
    

    If you want to insert a small delay between calls, you can use a timeout:

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

    The delay will make your resizing more responsive in case you have a large dataset on your graph.

    You the real hero for saying setup the chart only after the success callback fires. Just spent an hour on this trying to use callbacks to fill the data....*SMH* – Petro Jun 30 '18 at 1:14
  • Indeed
  • Yes, I'll give you an example.
  • I dont see anything that might cause an issue. Except that window.resize might be firing rendering a new chart far more often then you want.
  • No. (I don't really know why, this is more coincidence.)
  • The 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"
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid …

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.