web-dev-qa-db-fra.com

Comment effacer la toile pour le redessiner

Après avoir expérimenté des opérations composites et dessiné des images sur la toile, j'essaie maintenant de supprimer les images et la composition. Comment puis-je faire cela?

J'ai besoin de nettoyer la toile pour redessiner d'autres images; cela peut durer un moment, donc je ne pense pas que dessiner un nouveau rectangle à chaque fois soit l'option la plus efficace.

916
richard
const context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);
1161
Pentium10

Utilisez: context.clearRect(0, 0, canvas.width, canvas.height);

C'est le moyen le plus rapide et le plus descriptif pour effacer l'intégralité de la toile.

Ne pas utiliser: canvas.width = canvas.width;

Réinitialiser canvas.width réinitialise tous les états de la toile (par exemple, transformations, largeur de trait, style de trait, etc.), il est très lent (comparé à clearRect), il ne fonctionne pas dans tous les navigateurs et ne décrit pas ce que vous êtes. en train d'essayer de faire.

Traiter avec des coordonnées transformées

Si vous avez modifié la matrice de transformation (par exemple, en utilisant scale, rotate ou translate), alors context.clearRect(0,0,canvas.width,canvas.height) n'effacera probablement pas l'intégralité de la partie visible du canevas.

La solution? Réinitialisez la matrice de transformation avant d'effacer le canevas:

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

Edit: Je viens de faire du profilage et (sous Chrome), il est environ 10% plus rapide que d'effacer un canevas de 300 x 150 (taille par défaut) sans réinitialiser la transformation. À mesure que la taille de votre toile augmente, cette différence diminue.

C'est déjà relativement peu important, mais dans la plupart des cas, vous en tirerez beaucoup plus que ce que vous en résolvez, et j'estime que cette différence de performances est sans importance.

100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear
699
Prestaul

Si vous tracez des lignes, assurez-vous de ne pas oublier:

context.beginPath();

Sinon, les lignes ne seront pas effacées.

212
trembl

D'autres ont déjà fait un excellent travail en répondant à la question, mais si une simple méthode clear() sur l'objet contextuel vous serait utile (c'était pour moi), voici l'implémentation que j'utilise en fonction des réponses fournies:

CanvasRenderingContext2D.prototype.clear = 
  CanvasRenderingContext2D.prototype.clear || function (preserveTransform) {
    if (preserveTransform) {
      this.save();
      this.setTransform(1, 0, 0, 1, 0, 0);
    }

    this.clearRect(0, 0, this.canvas.width, this.canvas.height);

    if (preserveTransform) {
      this.restore();
    }           
};

Usage:

window.onload = function () {
  var canvas = document.getElementById('canvasId');
  var context = canvas.getContext('2d');

  // do some drawing
  context.clear();

  // do some more drawing
  context.setTransform(-1, 0, 0, 1, 200, 200);
  // do some drawing with the new transform
  context.clear(true);
  // draw more, still using the preserved transform
};
115
JonathanK
  • Chrome répond bien à: context.clearRect ( x , y , w , h ); comme suggéré par @ Pentium10, mais IE9 semble ignorer complètement cette instruction.
  • IE9 semble répondre à: canvas.width = canvas.width; mais il ne supprime pas les lignes, mais uniquement les formes, les images et autres objets, à moins que vous n'utilisiez également la solution de @John Allsopp consistant à modifier d'abord la largeur.

Donc, si vous avez une toile et un contexte créés comme ceci:

var canvas = document.getElementById('my-canvas');
var context = canvas.getContext('2d');

Vous pouvez utiliser une méthode comme celle-ci:

function clearCanvas(context, canvas) {
  context.clearRect(0, 0, canvas.width, canvas.height);
  var w = canvas.width;
  canvas.width = 1;
  canvas.width = w;
}
35
grenade

Utilisez la méthode clearRect en passant les coordonnées x, y, la hauteur et la largeur de la toile. ClearRect effacera toute la toile en tant que:

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
19
Vishwas

Nous sommes en 2018 et il n'y a toujours pas de méthode native pour effacer complètement le canevas à redessiner. clearRect()ne le fait pas efface complètement le canevas. Les dessins de type sans remplissage ne sont pas effacés (par exemple, rect())

1.Pour complètement effacer la toile, quelle que soit la façon dont vous dessinez:

context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.beginPath();

Avantages: conserve strokeStyle, fillStyle, etc. Pas de retard;

Inconvénients: inutile si vous utilisez déjà beginPath avant de dessiner quoi que ce soit

2.Utilisez le hack width/height:

context.canvas.width = context.canvas.width;

OR

context.canvas.height = context.canvas.height;

Avantages: fonctionne avec IE inconvénients: réinitialise strokeStyle, fillStyle au noir; Laggy;

Je me demandais pourquoi une solution native n'existe pas. En fait, clearRect() est considéré comme une solution à une seule ligne car la plupart des utilisateurs font beginPath() avant de tracer un nouveau chemin. Bien que beginPath ne soit utilisé que pour tracer des lignes et non un chemin fermé comme rect().

C'est la raison pour laquelle la réponse acceptée n'a pas résolu mon problème et j'ai fini par perdre des heures à essayer différentes méthodes de piratage. Vous maudire mozilla

18
sziraqui

il y a une tonne de bonnes réponses ici. Une autre remarque est qu'il est parfois amusant de ne nettoyer que partiellement la toile. c'est-à-dire que "fondu en fondu" l'image précédente au lieu de l'effacer entièrement. cela peut donner des effets de pistes de Nice.

c'est facile. en supposant que votre couleur de fond soit blanche:

// assuming background color = white and "eraseAlpha" is a value from 0 to 1.
myContext.fillStyle = "rgba(255, 255, 255, " + eraseAlpha + ")";
myContext.fillRect(0, 0, w, h);
14
orion elenzil

Un moyen rapide est de faire

canvas.width = canvas.width

Idk comment ça marche mais ça marche!

8
Jacob Morris

J'ai constaté que, dans tous les navigateurs que je teste, le moyen le plus rapide est de remplir de blanc, quelle que soit la couleur souhaitée. J'ai un très grand moniteur et en mode plein écran, le clearRect est terriblement lent, mais le fillRect est raisonnable.

context.fillStyle = "#ffffff";
context.fillRect(0,0,canvas.width, canvas.height);

L'inconvénient est que la toile n'est plus transparente.

4
John Page

Cela a fonctionné pour mon pieChart dans chart.js

<div class="pie_nut" id="pieChartContainer">
    <canvas id="pieChart" height="5" width="6"></canvas> 
</div>

$('#pieChartContainer').html(''); //remove canvas from container
$('#pieChartContainer').html('<canvas id="pieChart" height="5" width="6"></canvas>'); //add it back to the container
4
Sanal S

C'est ce que j'utilise, quelles que soient les limites et les transformations de la matrice:

function clearCanvas(canvas) {
  const ctx = canvas.getContext('2d');
  ctx.save();
  ctx.globalCompositeOperation = 'copy';
  ctx.strokeStyle = 'transparent';
  ctx.beginPath();
  ctx.lineTo(0, 0);
  ctx.stroke();
  ctx.restore();
}

Fondamentalement, il enregistre l'état actuel du contexte et dessine un pixel transparent avec copy comme globalCompositeOperation . Ensuite, restaure l'état de contexte précédent.

4
superruzafa
function clear(context, color)
{
    var tmp = context.fillStyle;
    context.fillStyle = color;
    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
    context.fillStyle = tmp;
}
4
Imagine Breaker

dans webkit, vous devez définir une largeur différente pour la largeur, puis vous pouvez rétablir la valeur initiale.

4
John Allsopp

Un moyen simple, mais pas très lisible, est d'écrire ceci:

var canvas = document.getElementId('canvas');

// after doing some rendering

canvas.width = canvas.width;  // clear the whole canvas
2
Chang

J'utilise toujours

cxt.fillStyle = "rgb(255, 255, 255)";
cxt.fillRect(0, 0, canvas.width, canvas.height);
1
GameMaster1928
Context.clearRect(starting width, starting height, ending width, ending height);

Exemple: context.clearRect(0, 0, canvas.width, canvas.height);

0
Gavin T

moyen le plus rapide:

canvas = document.getElementById("canvas");
c = canvas.getContext("2d");

//... some drawing here

i = c.createImageData(canvas.width, canvas.height);
c.putImageData(i, 0, 0); // clear context by putting empty image data
0
elser
context.clearRect(0,0,w,h)   

remplissez le rectangle donné avec les valeurs RGBA:
0 0 0 0: avec chrome
0 0 0 255: avec FF & Safari

Mais

context.clearRect(0,0,w,h);    
context.fillStyle = 'rgba(0,0,0,1)';  
context.fillRect(0,0,w,h);  

laisser le rectangle rempli de
0 0 0 255
peu importe le navigateur!

0

Si vous utilisez uniquement clearRect, si vous l'avez dans un formulaire pour soumettre votre dessin, vous obtiendrez un envoi à la place, ou peut-être pourrez-vous le nettoyer en premier, puis télécharger un dessin nul, vous devrez donc ajouter un preventDefault au début de la fonction:

   function clearCanvas(canvas,ctx) {
        event.preventDefault();
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }


<input type="button" value="Clear Sketchpad" id="clearbutton" onclick="clearCanvas(canvas,ctx);">

J'espère que ça aide quelqu'un.

0
JoelBonetR