title: HTML5 canvas blinks while refreshing
body: <p>I need to refresh an HTML5 canvas every two or three seconds.</p>
  
  <pre><code>setInterval(writeCanvas, 2000);
  </code></pre>
  
  <p>This canvas is filled with points and lines. Each abscissa and ordinate is stored in an XML file. So before updating the canvas I do an async request to the file on the server.</p>
  
  <p>The problem is that the canvas blinks. I guess it disappears while the async request is running.</p>
  
  <p>How could I get around this issue?</p>
  
  <p>Here is the code of writeCanvas:</p>
  
  <pre><code>function drawLines(ctx, back, front, width, xArray, yArray) {
      ctx.strokeStyle = back;
      ctx.fillStyle = front;
      ctx.lineWidth = width;
      ctx.beginPath();
      ctx.moveTo(xArray[0], yArray[0]);
      for (var i=1; i&lt;xArray.length; i++) {
          ctx.lineTo(xArray[i],yArray[i]);
      }
      ctx.fill();
      ctx.stroke();
      ctx.closePath();
  }
  
  function drawPoint(ctx, back, front, x, y, radius, startAngle, endAngle) {
      ctx.strokeStyle = back;
      ctx.fillStyle = front;
      ctx.beginPath();
      ctx.arc(x,y,radius,startAngle,endAngle,endAngle);
      ctx.fill();
      ctx.stroke();
      ctx.closePath();
  }
  
  function writeLabel(ctx, color, font, x, y, text) {
      ctx.fillStyle = color;
      ctx.font = font;
      ctx.beginPath();
      if(x &lt; 0) {
          x = 0;
      }
      ctx.fillText(text, x, y);
      ctx.fill();
      ctx.closePath();
  }
  
  function writeCanvas()
  {
      var elem = document.getElementById('profileCanvas');
      if (!elem || !elem.getContext) {
          return;
      }
  
      var ctx = elem.getContext('2d');
      if (!ctx) {
          return;
      }
  
      // apply the final size to the canvas
      elem.setAttribute('width', canvasWidth);
      elem.setAttribute('height', canvasHeight);
  
      $.get('profileStatus.xml', function(xml) {
          if(xml) {
              var testPoints = new Array();
              $(xml).find('TP').each(function() {
                  var selected = $(this).find('SELECTED:first').text();
                  if(selected == "YES") {
                      var name = $(this).find('MODULE_NAME:first').text();
                      var state = $(this).find('STATE:first').text();
                      var tp = new ProfileTp(name, state, selected);
                      testPoints.push(tp);
                  }
              });
  
              $.get('profile.xml', function(data) {
                  if(data) {
                      profileWidth = parseFloat($(data).find('MAIN &gt; PROFILE &gt; DIM_W').first().text());
                      profileHeight = parseFloat($(data).find('MAIN &gt; PROFILE &gt; DIM_H').first().text());
  
                      var backgroundColor = '#ddd';
                      var color = '#323232';
                      ctx.translate(0,canvasHeight);
  
                      var xArray = new Array();
                      var yArray = new Array();
  
                      $(data).find('PROFILE &gt; POINT &gt; X').each(function(){
                          var x=parseFloat($(this).text());
                          xArray.push(x);
                      });
                      $(data).find('PROFILE &gt; POINT &gt; Y').each(function(){
                          var y=parseFloat($(this).text());
                          yArray.push(y);
                      });
                      drawLines(ctx, backgroundColor, color, 2, xArray, yArray);
  
                      var finalArray = new Array();
                      $(data).find('TESTPOINTS &gt; TP').each(function() {
                          var labelName = $(this).find('MODULE_NAME:first').text();
                          var tp = $.grep(testPoints, function(obj){ return obj.NAME == labelName; });
                          if(tp.length == 1) {
                              $(this).find('IHM').each(function(){
                                  tp[0].LABEL_X = parseFloat($(this).find('LABEL &gt; X:first').text());
                                  tp[0].LABEL_Y = parseFloat($(this).find('LABEL &gt; Y:first').text());
                                  tp[0].MARKER_X = parseFloat($(this).find('MARKER &gt; X:first').text());
                                  tp[0].MARKER_Y = parseFloat($(this).find('MARKER &gt;Y:first').text());
                              });
                              finalArray.push(tp[0]);
                          }
                      });
                      for(var i=0; i&lt;finalArray.length; i++) {
                          writeLabel(ctx, color, fontSize+"px Arial",(finalArray[i].MARKER_X+finalArray[i].LABEL_X),(finalArray[i].MARKER_Y+finalArray[i].LABEL_Y), finalArray[i].NAME);
                          drawPoint(ctx, backgroundColor, color, finalArray[i].MARKER_X, finalArray[i].MARKER_Y, 8, 0, 2*Math.PI);
                      }
                  } else {
                      console.error('No XML test points returned');
                  }
              });
          }
      });
  }
  </code></pre>
  
  <p>There are two XML files. One contains all the points, lines and labels. The second contains only the points and labels that have to be displayed.</p>