Как отменить действие ластика для HTML5 Canvas Drawing App
Я создал приложение для рисования HTML5, которое имеет основные функции, которые позволяют пользователю выбирать цвет для рисования, изменять размер (радиус) инструмента рисования, отменять, возвращать и полностью очищать холст.
Недавно я добавил инструмент Eraser, используя globalCompositionProperty (desitnation-out), чтобы стереть выделенные области холста. Эта часть работает нормально, но когда я иду, чтобы отменить удаление, весь холст очищается и функция повторения не работает. Когда я возобновляю рисование с помощью обычного инструмента рисования (с использованием исходного кода), отмена / повтор работает. Я включил код для нескольких функций, используемых в приложении. Я сохраняю снимок холста при каждом отключении инструмента рисования. Это добавляется в массив, который используется для отмены и восстановления холста.
Может кто-нибудь объяснить, что я могу здесь делать неправильно? Я не уверен, что понимаю, как свойство globalCompositeOperation влияет на сохраненный DataURI холста.
function storeSnapshot() {
cStep++;
if (cStep < cPushArray.length) { cPushArray.length = cStep; }
cPushArray.push(canvas.toDataURL());
}
var putPoint = function(e){
if(dragging){
context.lineTo(e.clientX - 174, e.clientY - 50);
context.stroke();
context.beginPath();
if(eraser == true){
context.globalCompositeOperation="destination-out";
}else{
context.globalCompositeOperation="source-over";
}
context.arc(e.clientX - 174, e.clientY - 50 , radius, 0, 2 * Math.PI);
context.fill();
context.beginPath();
context.moveTo(e.clientX - 174, e.clientY - 50);
}
}
ОБНОВЛЕНИЕ: После игры с этим некоторое время я попробовал кое-что, что решает мою проблему. Я не совсем уверен, правильно ли это делать, но я решил показать вам все, что сделал.
У меня есть функция отключения, которая срабатывает при наведении мыши. Вот функция раньше:
var disengage = function(){
dragging = false;
context.beginPath();
storeSnapshot();
}
Я добавил немного кода, и это позволяет пользователю использовать инструмент ластик и отменить / повторить действие. Я не совсем уверен, почему это работает, поэтому, если у кого-то есть понимание, я был бы очень признателен.
var disengage = function(){
dragging = false;
context.beginPath();
if(eraser == true)
{
context.globalCompositeOperation="source-over";
}
storeSnapshot();
}
1 ответ
У меня была та же проблема, что и у вас, и я так рад, что наткнулся на ваш вопрос / решение, потому что это был момент с лампочкой для меня. Как только я увидел ваше решение, в нем было полное понимание того, что происходит.
Чтобы понять, почему ваше решение работает, globalCompositeOperation
это свойство холста, которое в основном определяет, как материал, в данном случае штрих линии, помещается на холст. По умолчанию это источник, который просто помещает новый штрих линии поверх любых существующих штрихов. Как вы упомянули, при удалении используется пункт назначения, который сохраняет весь существующий контент там, где он не перекрывает новый штрих строки (следовательно, стирание). Для некоторых информативных диаграмм и объяснений я очень рекомендую документы MDN для globalCompositeOperation
: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
Поэтому, если вы перейдете в режим стирания (для вас eraser = true), удалите, а затем сразу попытаетесь отменить, globalCompositeOperation все равно будет установлен в пункт назначения-выход. Это означает, что когда ваша отмена пытается нарисовать сохраненное изображение на холсте, все исчезнет, потому что оно, по существу, все еще стирается (как говорит целевой приемник, оно забрасывает любой существующий контент, где оно перекрывается с новым контентом, который в этом дело всего холста пространства). Следовательно, вам нужно установить его обратно на источник, как в своем решении, чтобы восстановленное изображение действительно появилось на холсте. Надеюсь, это поможет!