score:0

  1. indeed
  2. yes, i'll give you an example.
  3. 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.
  4. 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"
     500
 )

score:2

for those reading this in 2021:

update for chart.js v3.x.x

following updated answer for v3.x.x (which is not backwards compatible with v2.x.x)

first, answers to the 4 initial questions:

  1. the chart is not being resized on window resize.
  2. is there better code to do this? i think i am repeating to much code.
  3. in google the drawing is fast. in firefox sometimes it hangs for a while. is anything wrong with my code?
  4. should the request be async or not?
  1. with current version, it should resize automatically, try it yourself running the snippet below and resizing the browser window.

  2. the trick was to assign your chart to a variable const mylinechart = and then call simply mylinechart.update() when needed. be aware to assign programmatically the labels and datasets again before calling mylinechart.update(), otherwise data changes would not reflect in chart.

  3. should be fine now in firefox according to my testings.

  4. oh yes, absolutely async (either ajax or http-request with callback or promises).

// once the success function of your $.ajax request fires,
// put following code within your success-function

// for now, let's assume sample data
let data2 = {
  "dates" : [
    "2021-08-02",
    "2021-08-03",
    "2021-08-04",
    "2021-08-05",
    "2021-08-06"
  ],
  "users": [
    6,
    4,
    3,
    8,
    2
  ]
};

// draw chart
const ctx = document.queryselector('canvas').getcontext('2d');

const mylinechart = new chart(ctx, {
  type: 'line',
  data: {
    labels: data2.dates,
    datasets: [{
      label: 'users created',
      data: data2.users,
      bordercolor: 'green',
      backgroundcolor: '#404040',
      fill: true,
      animations: false // <-- now plural, instead of "animation" before
    }]
  }
});

// redraw the chart with an added record
function updatedata(event) {
  event.target.disabled = true;

  data2 = {
    "dates" : [
      "2021-08-02",
      "2021-08-03",
      "2021-08-04",
      "2021-08-05",
      "2021-08-06",
      "2021-08-07"
    ],
    "users": [
      6,
      4,
      3,
      8,
      2,
      12
    ]
  };

  // assign programmatically the datasets again, otherwise data changes won't show
  mylinechart.data.labels = data2.dates;
  mylinechart.data.datasets[0].data = data2.users;

  mylinechart.update();
};
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- gets you the latest version of chart.js, now at v3.5.0 -->

<button onclick="updatedata(event)">add data</button>

<canvas width="320" height="240"></canvas>

score:5

you can set that in chart.js

new chart(context, {
  type:"line",
  labels: data.dates,
  datasets: [
    { fillcolor: #404040, data: data.users }
  ]
  options: { responsive: false }
});

score:22

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.


Related Query