Как очистить холст для перерисовки

840

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

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

Теги:
canvas
composite
html5-canvas

21 ответ

1045
Лучший ответ
const context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);
  • 0
    @bplus, у меня работает ...
  • 1
    Настройка ширины у меня работает в Chrome 9.0.597.107, но не в Safari 5.0.3 (Windows)
Показать ещё 17 комментариев
645

Использование: 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), скорее всего, не очистит всю видимую часть холста.

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

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

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

100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear
  • 3
    Чисто(); работает ......
  • 4
    @YumYumYum: clear () - стандартная функция? Кажется, нет.
Показать ещё 14 комментариев
191

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

context.beginPath();

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

  • 24
    Это напоминание только что спасло меня от головной боли. Спасибо!
  • 8
    Я знаю, что это было здесь некоторое время, и, наверное, глупо комментировать после всего этого времени, но это беспокоило меня в течение года ... beginPath когда вы начинаете новый путь , не думайте, что только потому, что Вы очищаете холст, который хотите очистить и существующий путь! Это было бы ужасной практикой и обратным взглядом на рисование.
Показать ещё 5 комментариев
105

Другие уже сделали отличную работу, отвечая на вопрос, но если бы простой метод 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
};
  • 5
    Это отличная реализация. Я полностью поддерживаю улучшение собственных прототипов, но вы можете убедиться, что «clear» не определено перед его назначением - я все еще надеюсь на нативную реализацию когда-нибудь. :) Знаете ли вы, насколько широко браузеры поддерживают CanvasRenderingContext2D и оставляют его «доступным для записи»?
  • 0
    Спасибо за отзыв @Prestaul - также ни один браузер не должен мешать вам расширять объекты javascript таким образом.
Показать ещё 2 комментария
33
  • 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;
}
  • 12
    Обратите внимание, что метод можно упростить, передав только контекст и используя context.clearRect(0,0,context.canvas.width,context.canvas.height) .
  • 5
    IE 9 должен абсолютно отвечать на вызов clearRect ... (См .: msdn.microsoft.com/en-us/library/ff975407(v=vs.85).aspx ). Медленно, как изменение canvas.width, единственный способ Вы можете сделать медленнее, изменив его дважды и вызвав clearRect.
Показать ещё 3 комментария
19

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

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
  • 0
    Вы можете просто вставить это в метод и вызывать его каждый раз, когда хотите обновить экран, правильно.
  • 0
    да user3376708, это очистит содержимое холста
Показать ещё 2 комментария
13

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

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

// 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);
  • 0
    Я знаю, что это возможно, и у меня нет проблем с вашим ответом, мне просто интересно, если у вас есть 2 объекта, которые движутся, и вы хотите отследить только один из них, как бы вы это сделали?
  • 0
    это намного сложнее. в этом случае вы должны создать закадровый холст, и каждый кадр рисует объекты, которые вы хотите отследить на этом холсте, используя метод частичного стирания, описанный здесь, а также каждый кадр очищает основной холст на 100%, рисует нетранслируемый объекты, а затем скомпоновать закадровый холст на основной, используя drawImage (). Вам также необходимо установить для globalCompositeOperation что-то подходящее для изображений. например, «умножение» будет хорошо работать для темных объектов на светлом фоне.
9

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

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

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

Плюсы: сохраняет штрих-стиль, fillStyle и т. Д.; Нет лагов;

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

2. Используя хак ширины/высоты:

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

ИЛИ ЖЕ

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

Плюсы: Работает с IE. Минусы: Сбрасывает strokeStyle, fillStyle в черный; лаг;

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

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

  • 0
    Мой плохой, должно быть clearRect (). Я очень привык писать функцию-оболочку с именем clearCanvas, поэтому допустил эту ошибку
  • 0
    голосование снято :-)
5

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

canvas.width = canvas.width

ИДК, как это работает, но это делает!

  • 0
    Вот это да. Это действительно работает, как вы когда-нибудь нашли это?
  • 0
    @zipit Быстрый трюк, который я обнаружил на medium.com после того, как обычная очистка не рендерилась :)
4

Это сработало для моего pieChart в 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
function clear(context, color)
{
    var tmp = context.fillStyle;
    context.fillStyle = color;
    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
    context.fillStyle = tmp;
}
  • 0
    Это медленнее, чем clearRect (0,0, canvas.width, canvas.height)
4

Я обнаружил, что во всех браузерах, которые я тестирую, самым быстрым способом является на самом деле fillRect с белым или любым желаемым цветом. У меня очень большой монитор, и в полноэкранном режиме clearRect мучительно медленный, но fillRect разумен.

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

Недостаток в том, что холст уже не прозрачен.

4

в webkit вам нужно установить ширину на другое значение, после чего вы можете вернуть ее к исходному значению

  • 1
    По состоянию на 2018 год webkit работает так же, как и другие.
3

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

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. Затем восстанавливает предыдущее состояние контекста.

  • 1
    Да! Мне нравится, как это сохраняет холст тоже.
2

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

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

// after doing some rendering

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

Самый быстрый способ:

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
  • 11
    вау ... в каком браузере? В моем (Chrome 22 и Firefox 14 на OS X) ваш метод, безусловно, самый медленный вариант. jsperf.com/canvas-clear-speed/9
  • 1
    > 5 лет в будущем, это все еще самый медленный метод, очень большой, в 700 раз медленнее, чем clearRect .
0

Я всегда использую

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

Пример: context.clearRect(0, 0, canvas.width, canvas.height);

0

Если вы используете clearRect только, если у вас есть в форме, чтобы отправить свой рисунок, вы получите отправку, а затем очистку, или, возможно, ее можно сначала очистить, а затем загрузить рисунок пустоты, так что вам понадобится для добавления функции preventDefault в начале функции:

   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);">

Надеюсь, что это поможет кому-то.

0
context.clearRect(0,0,w,h)   

заполнить данный прямоугольник значениями RGBA:
0 0 0 0: с Chrome
0 0 0 255: с FF и Safari

Но

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

пусть прямоугольник заполнен с помощью 0 0 0 255
независимо от браузера!

-1

Все это отличные примеры того, как вы очищаете стандартный холст, но если вы используете paperjs, то это будет работать:

Определите глобальную переменную в JavaScript:

var clearCanvas = false;

Из вашего PaperScript определите:

function onFrame(event){
    if(clearCanvas && project.activeLayer.hasChildren()){
        project.activeLayer.removeChildren();
        clearCanvas = false;
    }
}

Теперь, когда вы устанавливаете clearCanvas в true, он очищает все элементы с экрана.

  • 7
    -1 Для рекомендации глобальных переменных ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню