He tenido dificultades para producir formas nítidas en mi lienzo, he estado sacando código para tratar de depurarlo y parece que una de las causas es el hecho de que se está volviendo a dibujar. A continuación se muestra el código sin bucle:

var context = $('canvas')[0].getContext('2d');

function draw() {
  context.clearRect(0, 0, context.width, context.height);
  context.beginPath();
  context.arc(100, 100, 50, 0, 2 * Math.PI, false);
  context.fillStyle = 'red';
  context.fill();
  context.lineWidth = 4;
  context.strokeStyle = 'darkred';
  context.stroke();
}
draw();
<canvas width=200 height=200></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

Y aquí está lo mismo otra vez con el bucle:

var context = $('canvas')[0].getContext('2d');

function draw() {
  requestAnimationFrame(draw);
  context.clearRect(0, 0, context.width, context.height);
  context.beginPath();
  context.arc(100, 100, 50, 0, 2 * Math.PI, false);
  context.fillStyle = 'red';
  context.fill();
  context.lineWidth = 4;
  context.strokeStyle = 'darkred';
  context.stroke();
}

function init() {
  if (typeof game_loop != "undefined") clearInterval(game_loop);
  var game_loop = setInterval(draw, 30);
}
init();
<canvas width=200 height=200></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

Para aquellos que no ven lo que hago en Chrome, aquí hay una imagen: Círculo con suavizado y círculo sin

Parece que incluso poner la línea requestAnimationFrame(draw); en el primer ejemplo causa el mismo problema.

¿Qué estoy haciendo mal aquí?

1
jaunt 1 nov. 2017 a las 03:30

3 respuestas

La mejor respuesta

El problema es que no puede acceder a context.width y context.height. Por lo tanto, esto hará que el método clearRect falle y los círculos se dibujen sobre otro. Use canvas.width y canvas.height.

var canvas = $('canvas')[0]
var context = canvas.getContext('2d');
var game_loop

function draw() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.beginPath();
  context.arc(100, 100, 50, 0, 2 * Math.PI, false);
  context.fillStyle = 'red';
  context.fill();
  context.lineWidth = 4;
  context.strokeStyle = 'darkred';
  context.stroke();
}

function init() {
  if (typeof game_loop != "undefined") clearInterval(game_loop);
  game_loop = setInterval(requestAnimationFrame.bind(null, draw), 30) // use requestAnimationFrame but limit to 30ms interval - from @JoshuaK
}
init();
<canvas width=200 height=200></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

También usaste ambos, un intervalo y el requestAnimationFrame. Lo que causará retrasos masivos. Use intervalos para anmation solo cuando no tenga otra opción. También podría usar este polyfill:

window.requestAnimFrame = function(){
    return (
        window.requestAnimationFrame       || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame    || 
        window.oRequestAnimationFrame      || 
        window.msRequestAnimationFrame     || 
        function(func){
            window.setTimeout(func, 30);
        }
    );
}()
4
Manuel Otto 1 nov. 2017 a las 01:34

CanvasRenderingContext2D (el tipo de {{X1 }}) no tiene los atributos width y height, pero mantiene una referencia a canvas al que pertenece.

Y, por supuesto, eso tiene width / height, por lo que el cambio mínimo en su código podría ser:

context.clearRect(0, 0, context.canvas.width, context.canvas.height);
1
tevemadar 1 nov. 2017 a las 11:19

Si cambió la matriz de transformación (por ejemplo, usando escala, rotación o traslación), context.clearRect (0,0, canvas.width, canvas.height) probablemente no eliminará toda la parte visible Canvas

¿La solución? Restablezca la matriz de transformación antes de borrar el lienzo:

// Store the current transformation matrix
context.save();

// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);

// Restore the transform
context.restore();
1
Amine KOUIS 1 nov. 2017 a las 01:08