Как правильно полностью очистить холст HTML5 после операции globalComposite? - PullRequest
0 голосов
/ 17 мая 2019

Я знаю этот вопрос может быть связан , но, используя там решения, я не могу полностью очистить свой холст.
После того, как я установил globalCompositeOperation своего контекста, мой холст все еще имел некоторый слой после вызова clearRect().

Решение canvas.width = canvas.width подойдет, но там говорит, что оно поддерживается не во всех браузерах, а также является плохой практикой.

Как правильно очистить холст после операции globalComposite?

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const img = new Image();
const reader = new FileReader();
const filterRed = document.getElementById("red");
const addText = document.getElementById("addText");
const upload = document.getElementById("upload");

upload.addEventListener("change", function(evnt) {
  const file = evnt.target.files[0];
  reader.onload = function(e) {
    img.src = e.target.result;
    img.onload = function() {
      ctx.drawImage(img, 0, 0, canvas.clientWidth, canvas.height);
    };
  };
  reader.readAsDataURL(file);
});

filterRed.addEventListener("click", function(e) {
  // redraw image again to prevent double clicking
  // behave not normaly
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "red";
  ctx.filter = "contrast(0.6) brightness(100%)";
  ctx.globalCompositeOperation = "multiply";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
});

addText.addEventListener("click", function(e) {
  // redraw all things again
  // but here not behave normaly
  canvas.toBlob(function(blob) {
    img.src = URL.createObjectURL(blob);
    img.onload = function() {
      // using canvas.width = canvas.width solve the problem
      // but it is not the right way
      canvas.width = canvas.width;
      ctx.drawImage(img, 0, 0, canvas.width, canvas.width);
      ctx.font = "50px serif";
      ctx.fillStyle = "#00ff00";
      ctx.fillText("Hello world", 50, 90);
    };
  });
});
<p>
  Upload Image First
</p>
<label for="upload">Click to select file</label>
<input type="file" accept="image/*|video/*" id="upload" hidden>


<canvas id="canvas"></canvas>
<button id="red">
  red
</button>
<button id="addText">
  redraw with text
</button>

Здесь репродукция коды и коробка

На изображении не должно быть белого слоя, текст должен быть белым, а не изображение.

1 Ответ

1 голос
/ 17 мая 2019

Вы должны повторно инициализировать свой контекст globalCompositeOperation до значения по умолчанию: source-over.

Обратите внимание, что вам также может понадобиться сбросить матрицу преобразования контекста на ее значение по умолчанию, это можно сделать с помощью *Метод 1005 * и единичная матрица 1, 0, 0, 1, 0, 0.

Единственное, что теперь может помешать правильной работе нашего clearRect, - это активное правило отсечения.Поэтому, когда вы используете clip(), убедитесь, что вы всегда вызывали ctx.save() до, а затем - ctx.restore() после, чтобы отключить область отсечения (или вообще не использовать clip).

const ctx = canvas.getContext('2d');
draw_btn.onclick = drawStuffs;
simpleclear_btn.onclick = brokenClear;
better_btn.onclick = betterClear;

drawStuffs();

function drawStuffs() {
  ctx.fillStyle = 'rgba(0,34,123, .75)';
  ctx.fillRect(0,0,45,45);
  ctx.globalCompositeOperation = 'source-atop';
  ctx.fillStyle = "red";
  ctx.translate(25, 25);
  ctx.fillRect(0,0,45,45);
}

function brokenClear() {
  ctx.clearRect(0,0,canvas.width,canvas.height);
}
function betterClear() {
 ctx.globalCompositeOperation = 'source-over';
 ctx.setTransform(1,0,0,1,0,0);
 ctx.clearRect(0,0,canvas.width,canvas.height);
}
<button id="draw_btn">draw stuff</button>
<button id="simpleclear_btn">simple clear (broken)</button>
<button id="better_btn">better clear</button>


<canvas id="canvas"></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...