Как очистить холст для перерисовки
После экспериментов с составными операциями и рисования изображений на холсте, я сейчас пытаюсь удалить изображения и композитинг. Как мне это сделать?
Мне нужно очистить холст для перерисовки других изображений; это может продолжаться какое-то время, поэтому я не думаю, что рисование нового прямоугольника каждый раз будет наиболее эффективным вариантом.
26 ответов
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
Использование: context.clearRect(0, 0, canvas.width, canvas.height);
Это самый быстрый и описательный способ очистки всего холста.
Не использовать: canvas.width = canvas.width;
Сброс canvas.width
сбрасывает все состояния холста (например, transformation, 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();
Редактировать: я только что провел некоторое профилирование и (в Chrome) примерно на 10% быстрее очистить холст 300x150 (размер по умолчанию) без сброса преобразования. По мере увеличения размера вашего холста эта разница уменьшается.
Это уже относительно незначительно, но в большинстве случаев вы будете рисовать значительно больше, чем очищаете, и я считаю, что эта разница в производительности не имеет значения.
100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear
Если вы рисуете линии, убедитесь, что вы не забыли:
context.beginPath();
В противном случае линии не будут очищены.
Другие уже сделали отличную работу, отвечая на вопрос, но если простой 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
};
Это 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().
Это причина, по которой принятый ответ не решил мою проблему, и я потратил часы, пытаясь использовать различные способы взлома. Проклинаю тебя мозилла
- 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;
}
Используйте метод clearRect, передавая координаты x,y, а также высоту и ширину холста. ClearRect очистит весь холст как:
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
Быстрый способ сделать
canvas.width = canvas.width
ИДК, как это работает, но это делает!
Здесь есть множество хороших ответов. Еще одно замечание: иногда забавно очищать холст лишь частично. то есть "затухает" предыдущее изображение, а не стирает его полностью. это может дать хорошие следы эффектов.
это просто. Предположим, ваш цвет фона белый:
// 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);
Я всегда использую
cxt.fillStyle = "rgb(255, 255, 255)";
cxt.fillRect(0, 0, canvas.width, canvas.height);
Это то, что я использую, независимо от границ и матричных преобразований:
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
, Затем восстанавливает предыдущее состояние контекста.
Это сработало для моего 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
Я обнаружил, что во всех браузерах, которые я тестирую, самый быстрый способ - это заполнить Rect белым или любым другим цветом, который вы хотите. У меня очень большой монитор, и в полноэкранном режиме clearRect мучительно медленен, но fillRect оправдан.
context.fillStyle = "#ffffff";
context.fillRect(0,0,canvas.width, canvas.height);
Недостатком является то, что холст больше не является прозрачным.
Теперь есть.reset()
метод, который не только очистит буфер холста, но и полностью сбросит все свойства контекста (стили и т. д.), сбросит его матрицу преобразования, очистит его текущий подпуть, очистит его стек состояний (тот, который контролируетсяsave()
иrestore()
) и удалите все области отсечения.
context.reset();
// now 'context' is clear as new
По сути, он имеет те же эффекты, что и , за исключением того, что он более идиоматичен.
Однако кажется, что в текущей реализации Chromium это так же медленно, какcanvas.width += 0
, он также генерирует новый буфер вместо того, чтобы просто очищать предыдущий (что приводит к большему количеству мусора в памяти). Еще одно предостережение заключается в том, что в настоящее время он поддерживается только в браузерах Chromium. Хотя для полифилла вы можете пойти по пути Chrome
if (!CanvasRenderingContext2D.prototype.reset) {
CanvasRenderingContext2D.prototype.reset = function() {
this.canvas.width += 0;
};
}
if (!OffscreenCanvasRenderingContext2D.prototype.reset) {
OffscreenCanvasRenderingContext2D.prototype.reset = function() {
this.canvas.width += 0;
};
}
private clearCanvas() {
const canvas: HTMLCanvasElement = this.ctx.canvas
this.ctx.save()
this.ctx.setTransform(1, 0, 0, 1, 0, 0)
this.ctx.clearRect(0, 0, canvas.width, canvas.height)
this.ctx.restore()
}
function clear(context, color)
{
var tmp = context.fillStyle;
context.fillStyle = color;
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
context.fillStyle = tmp;
}
В webkit вам нужно установить ширину на другое значение, затем вы можете вернуть его к первоначальному значению
Простой, но не очень читаемый способ - написать так:
var canvas = document.getElementId('canvas');
// after doing some rendering
canvas.width = canvas.width; // clear the whole canvas
Самый быстрый способ:
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
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
независимо от браузера!
Context.clearRect(starting width, starting height, ending width, ending height);
Пример: context.clearRect(0, 0, canvas.width, canvas.height);
Я всегда использую это
ctx.clearRect(0, 0, canvas.width, canvas.height)
window.requestAnimationFrame(functionToBeCalled)
НОТА
сочетание clearRect и requestAnimationFrame позволяет получить более плавную анимацию, если это то, что вы собираетесь
Это холст для рисования от руки с кнопкой очистки холста.
Посмотрите этот живой пример холста, на котором вы можете рисовать, а также, при необходимости, очистить его для перерисовки.
clearRect()
используется для удаления существующего холста и
fillRect()
используется для повторного рисования исходного холста, который был чистым и на нем не было рисунков.
Если вы используете только clearRect, если у вас это есть в форме для отправки чертежа, вы получите отправку вместо очистки, или, возможно, сначала ее можно очистить, а затем загрузить недействительный чертеж, поэтому вам нужно будет добавить protectDefault в начале функции:
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);">
Надеюсь, это поможет кому-то.
Все это отличные примеры того, как вы очищаете стандартный холст, но если вы используете paperjs, то это будет работать:
Определите глобальную переменную в JavaScript:
var clearCanvas = false;
Из вашего PaperScript определите:
function onFrame(event){
if(clearCanvas && project.activeLayer.hasChildren()){
project.activeLayer.removeChildren();
clearCanvas = false;
}
}
Теперь, где бы вы ни установили clearCanvas в true, он удалит все элементы с экрана.