Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Distorted canvas border In chrome and Firefox

I have this very simple canvas script, Fiddle here.

JS code:

$(function() {

  var canvas = $('<canvas></canvas>').attr({
    width: 200,
    height: 200
  }).appendTo('.circle').get(0);

  var context = canvas.getContext('2d');

  context.clearRect(0, 0, 100, 100);

  context.beginPath();
  context.arc(100, 100, (200 / 2.5), Math.PI * 2, 0, false);

  context.lineWidth = 10;

  context.strokeStyle = "#eeeeee";
  context.stroke();

  context.fillStyle = "#FF0033";
  context.fill();

  var curPerc = 0;

  function drawArc(current) {
    console.log(current + ' ' + curPerc);
    context.beginPath();
    context.arc(100, 100, (200 / 2.5), 0, ((Math.PI * 2) * current), false);
    context.strokeStyle = '#9BCB3C';
    context.stroke();
    //console.log(curPerc)
    if (curPerc < 75) {
      curPerc += 1;
      requestAnimationFrame(function() {
        drawArc(curPerc / 100);
      });
    };

  }

  drawArc();

});

Now the problem is the circle doesn't quite look perfect, the border is a bit distorted. I am on the latest version of Chrome (same situation in latest FF) and below is how it looks:

distorted border.

Is this a known issue and is there an easy fix to this?

like image 455
Alexander Solonik Avatar asked Mar 05 '26 09:03

Alexander Solonik


1 Answers

Your problem is that you are always drawing the same arcs over the last ones. The anti-aliasing artifacts are accumulating at each draw and become bigger and nastier.

The solution is to clearRect() your canvas at each call.

$(function() {

  var canvas = $('<canvas></canvas>').attr({
    width: 200,
    height: 200
  }).appendTo('.circle').get(0);

  var context = canvas.getContext('2d');

  // you wil then need to redraw the full circle at every frame too
  var drawFull = function() {
    context.clearRect(0, 0, 200, 200);

    context.beginPath();
    context.arc(100, 100, (200 / 2.5), Math.PI * 2, 0, false);

    context.lineWidth = 10;

    context.strokeStyle = "#eeeeee";
    context.stroke();

    context.fillStyle = "#FF0033";
    context.fill();
  };
  var curPerc = 0;

  function drawArc(current) {
    drawFull();
    context.beginPath();
    context.arc(100, 100, (200 / 2.5), 0, ((Math.PI * 2) * current), false);
    context.strokeStyle = '#9BCB3C';
    context.stroke();
    if (curPerc < 75) {
      curPerc += 1;
      requestAnimationFrame(function() {
        drawArc(curPerc / 100);
      });
    };

  }

  drawArc();

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="circle">


</div>

With this drawing, you could also try to upscale your canvas' width/height attributes and downscale it after with css :

$(function() {

   var canvas = $('<canvas></canvas>').attr({
    width: 400,
    height: 400
  }).css({width:200,height:200}).appendTo('.circle').get(0);

  var context = canvas.getContext('2d');
  // we need to change the context's scale
  context.scale(2,2);

  var drawFull = function() {
    context.clearRect(0, 0, 200, 200);

    context.beginPath();
    context.arc(100, 100, (200 / 2.5), Math.PI * 2, 0, false);

    context.lineWidth = 10;

    context.strokeStyle = "#eeeeee";
    context.stroke();

    context.fillStyle = "#FF0033";
    context.fill();
  };
  var curPerc = 0;

  function drawArc(current) {
    drawFull();
    context.beginPath();
    context.arc(100, 100, (200 / 2.5), 0, ((Math.PI * 2) * current), false);
    context.strokeStyle = '#9BCB3C';
    context.stroke();
    if (curPerc < 75) {
      curPerc += 1;
      requestAnimationFrame(function() {
        drawArc(curPerc / 100);
      });
    };

  }

  drawArc();

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="circle">


</div>
like image 83
Kaiido Avatar answered Mar 06 '26 22:03

Kaiido