Как очистить холст для перерисовки - PullRequest
900 голосов
/ 26 января 2010

После экспериментов с составными операциями и рисования изображений на холсте, я сейчас пытаюсь удалить изображения и композитинг. Как мне это сделать?

Мне нужно очистить холст для перерисовки других изображений; это может продолжаться некоторое время, поэтому я не думаю, что каждый раз рисование нового прямоугольника будет наиболее эффективным вариантом.

Ответы [ 21 ]

1129 голосов
/ 26 января 2010
const context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);
695 голосов
/ 17 июля 2011

Использование: context.clearRect(0, 0, canvas.width, canvas.height);

Это самый быстрый и описательный способ очистки всего холста.

Не использовать: canvas.width = canvas.width;

Сброс canvas.width сбрасывает все состояние холста (например, трансформации, lineWidth, strokeStyle и т. Д.), Он очень медленный (по сравнению с clearRect), работает не во всех браузерах и не описывает, что на самом деле пытаются сделать.

Работа с преобразованными координатами

Если вы изменили матрицу преобразования (например, используя scale, rotate или translate), то context.clearRect(0,0,canvas.width,canvas.height), вероятно, не очистит всю видимую часть холста.

Решение? Сброс матрицы преобразования до очистки холста:

// 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: Я только что выполнил некоторое профилирование и (в Chrome) очистка холста 300x150 (размер по умолчанию) примерно на 10% быстрее без сброса преобразования. По мере увеличения размера вашего холста эта разница уменьшается.

Это уже относительно несущественно, но в большинстве случаев вы будете рисовать значительно больше, чем очищаете, и я считаю, что эта разница в производительности не имеет значения.

100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear
211 голосов
/ 13 января 2011

Если вы рисуете линии, убедитесь, что вы не забыли:

context.beginPath();

В противном случае строки не будут очищены.

115 голосов
/ 15 марта 2012

Другие уже проделали отличную работу, отвечая на вопрос, но если простой (clear()) метод для объекта контекста был бы полезен для вас (это было для меня), то это реализация, которую я использую, основываясь на ответах здесь:

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

Использование:

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
};
35 голосов
/ 03 ноября 2010
  • Chrome хорошо реагирует на: context.clearRect ( x , y , w , h );, как предлагает @ Pentium10, но IE9, похоже, полностью игнорирует эту инструкцию.
  • IE9, кажется, отвечает: canvas.width = canvas.width;, но он не очищает линии, только фигуры, рисунки и другие объекты, если вы не используете решение @John Allsopp для первого изменения ширины.

Итак, если у вас есть холст и контекст, созданный так:

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

Вы можете использовать метод, подобный этому:

function clearCanvas(context, canvas) {
  context.clearRect(0, 0, canvas.width, canvas.height);
  var w = canvas.width;
  canvas.width = 1;
  canvas.width = w;
}
19 голосов
/ 13 ноября 2013

Используйте метод clearRect, передавая координаты x, y, а также высоту и ширину холста. ClearRect очистит весь холст как:

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
17 голосов
/ 08 мая 2018

Это 2018 год, и до сих пор нет собственного способа полностью очистить холст для перерисовки. clearRect() не полностью очищает холст. Чертежи незаполненного типа не очищаются (например, rect())

1.T полностью прозрачный холст, независимо от того, как вы рисуете:

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

Плюсы: Сохраняет штрих-стиль, заливку и т. Д .; Без задержки;

Минусы: не нужно, если вы уже используете beginPath перед рисованием чего-либо

2.Использование взлома ширина / высота:

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

OR

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

Плюсы: работает с IE Минусы: Сбрасывает штрих-стиль, fillStyle в черный; Лаг;

Мне было интересно, почему не существует нативного решения. На самом деле, clearRect() рассматривается как однострочное решение, потому что большинство пользователей делают beginPath() перед тем, как рисовать новый путь. Хотя beginPath следует использовать только при рисовании линий, а не при закрытом пути, например rect().

Это причина, по которой принятый ответ не решил мою проблему, и я потратил часы, пытаясь использовать различные способы взлома. Проклинаю тебя мозилла

14 голосов
/ 04 мая 2012

здесь есть множество хороших ответов. Еще одно замечание: иногда бывает весело только частично очистить холст. то есть «затухает» предыдущее изображение, а не стирает его полностью. это может дать хорошие следы эффектов.

это легко. Предположим, ваш цвет фона белый:

// 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);
8 голосов
/ 08 мая 2018

Быстрый способ сделать

canvas.width = canvas.width

Я знаю, как это работает, но работает!

4 голосов
/ 28 мая 2018

Это то, что я использую, независимо от границ и матричных преобразований:

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

По сути, он сохраняет текущее состояние контекста и рисует прозрачный пиксель с copy как globalCompositeOperation. Затем восстанавливает предыдущее состояние контекста.

...