javascript - Cómo limpiar el lienzo para volver a dibujar
Después de experimentar con operaciones compuestas y dibujar imágenes en el lienzo, ahora estoy intentando eliminar imágenes y la composición. ¿Cómo hago esto?
Necesito limpiar el lienzo para volver a dibujar otras imágenes; esto puede continuar por un tiempo, así que no creo que dibujar un nuevo rectángulo cada vez sea la opción más eficiente.
Respuesta #1
Dado que canvas es un elemento canvas o un objeto OffscreenCanvas, usa clearRect:
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
Respuesta #2
Uso: context.clearRect(0, 0, canvas.width, canvas.height);
Esta es la manera más rápida y descriptiva de limpiar todo el lienzo.
No utilices: canvas.width=canvas.width;
Restablecer canvas.width restablece todo el estado del lienzo (por ejemplo, transformaciones, lineWidth, strokeStyle, etc.), es muy lento (en comparación con clearRect), no funciona en todos los navegadores y no describe lo que realmente estás intentando hacer.
Tratando con coordenadas transformadas
Si has modificado la matriz de transformación (por ejemplo, usando scale, rotate o translate), entonces context.clearRect(0,0,canvas.width,canvas.height) probablemente no borrará toda la porción visible del lienzo.
¿La solución? Restablecer la matriz de transformación antes de limpiar 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();
Editar: Acabo de hacer algunos perfiles y (en Chrome) es aproximadamente un 10% más rápido limpiar un lienzo de 300x150 (tamaño predeterminado) sin reiniciar la transformación. A medida que aumenta el tamaño de tu lienzo, esta diferencia disminuye.
Eso ya es relativamente insignificante, pero en la mayoría de los casos estarás extrayendo considerablemente más de lo que estás limpiando y creo que esta diferencia de rendimiento será irrelevante.
100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear
Respuesta #3
Si estás dibujando líneas, asegúrate de no olvidar:
context.beginPath();
De lo contrario, las líneas no se borrarán.
Respuesta #4
Otros ya han hecho un excelente trabajo respondiendo la pregunta, pero si un simple método clear() en el objeto contexto te sería útil (a mí lo fue), esta es la implementación que uso basada en las respuestas aquí:
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();
}
};
Uso :
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
};
Respuesta #5
Estamos en 2018 y todavía no existe un método nativo para limpiar completamente el lienzo para volver a dibujar. clearRect() no limpia completamente el lienzo. Los dibujos que no son de relleno no se eliminan (por ejemplo, rect())
1. Para borrar completamente el lienzo sin importar cómo dibujes:
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.beginPath();
Pros: Conserva strokeStyle, fillStyle, etc.; Sin retraso;
Contras: Innecesario si ya está utilizando beginPath antes de dibujar cualquier cosa
2. Usando el truco de ancho/alto:
context.canvas.width = context.canvas.width;
O
context.canvas.height = context.canvas.height;
Pros: Funciona con IE Contras: Restablece strokeStyle y fillStyle a negro; Lento;
Me preguntaba por qué no existe una solución nativa. De hecho, clearRect() se considera la solución de una sola línea porque la mayoría de los usuarios hacen beginPath() antes de dibujar cualquier camino nuevo. Aunque beginPath solo debe usarse al dibujar líneas y no un camino cerrado como rect().
Esta es la razón por la cual la respuesta aceptada no resolvió mi problema y terminé perdiendo horas probando diferentes trucos. Maldita seas, Mozilla
Respuesta #6
- Chrome responde bien a:
context.clearRect ( x , y , w , h );como sugiere @Pentium10 pero IE9 parece ignorar completamente esta instrucción. - IE9 parece responder a:
canvas.width=canvas.width;pero no borra líneas, solo formas, imágenes y otros objetos a menos que también uses la solución de @John Allsopp de primero cambiar el ancho.
Entonces, si tienes un lienzo y un contexto creados así:
var canvas = document.getElementById('my-canvas');
var context = canvas.getContext('2d');
Puedes usar un método como este:
function clearCanvas(context, canvas) {
context.clearRect(0, 0, canvas.width, canvas.height);
var w = canvas.width;
canvas.width = 1;
canvas.width = w;
}
Respuesta #7
Usa el método clearRect pasando las coordenadas x, y y la altura y anchura del lienzo. ClearRect borrará todo el lienzo como:
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
Respuesta #8
Una forma rápida es hacer
canvas.width = canvas.width
¡No sé cómo funciona, pero funciona!
Respuesta #9
hay un montón de buenas respuestas aquí. una nota adicional es que a veces es divertido limpiar solo parcialmente el lienzo. es decir, "desvanecer" la imagen anterior en lugar de borrarla por completo. esto puede dar efectos de rastro agradables.
es fácil. suponiendo que el color de fondo sea blanco:
// 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);
Respuesta #10
Esto es lo que uso, sin importar los límites y las transformaciones de matriz:
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();
}
Básicamente, guarda el estado actual del contexto y dibuja un píxel transparente con copy como globalCompositeOperation. Luego, restaura el estado previo del contexto.
Respuesta #11
Siempre uso
ctx.fillStyle = "rgb(255, 255, 255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
Para un color personalizado, y
ctx.clearRect(0, 0, canvas.width, canvas.height);
Para hacer el lienzo transparente al limpiar
