#javascript #html #html5-canvas
#javascript #HTML #html5-canvas
Вопрос:
У меня есть следующий код:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = new Image(60, 45); // Using optional size for image
image.onload = drawImageActualSize; // Draw when image has loaded
// Load an image of intrinsic size 300x227 in CSS pixels
image.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
function drawImageActualSize() {
// Use the intrinsic size of image in CSS pixels for the canvas element
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
// Will draw the image as 300x227, ignoring the custom size of 60x45
// given in the constructor
ctx.drawImage(this, 0, 0);
// To use the custom size we'll have to specify the scale parameters
// using the element's width and height properties - lets draw one
// on top in the corner:
ctx.drawImage(this, 0, 0, this.width, this.height);
ctx.save();
ctx.fillStyle = 'green';
ctx.fillRect(10, 10, 150, 100);
ctx.restore();
ctx.clearRect(10, 10, 150, 100);
}
<canvas id="canvas" width=300 height=200></canvas>
Здесь метод ctx.clearRect (10, 10, 150, 100) удаляет зеленую часть, а также изображение и показывает белый холст.
Я хочу удалить только зеленую часть и восстановить предыдущее изображение.
Как я могу этого добиться?
Ответ №1:
Перерисовать
Стандартный способ добавления и удаления динамического содержимого — повторно отображать холст каждый раз, когда происходит изменение. Вот как это делают HTML-игры canvas, работающие со скоростью 60 кадров в секунду, и в них может меняться 100 элементов за кадр.
Существуют другие методы, которые требуют создания копии того, что находится под прямоугольником каждый раз, когда он рисуется, а затем рисования копии поверх прямоугольника, когда вы хотите его удалить.
Это сложно и требует по крайней мере одного дополнительного холста для каждого отрисовываемого динамического объекта и, таким образом, занимает много памяти. Или используйте getImageData
и putImageData, которые также загружают память, работают очень медленно, приведут к большому количеству действий GC и недоступны для незащищенного содержимого (изображения в разных доменах или из локального хранилища файлов).
Перерисовка — безусловно, самый простой способ. Вы бы рассматривали другие методы, только если для рендеринга всего содержимого (для не анимированного содержимого) потребовалось более нескольких 100 мс
Пример
В примере переменная rectOn
, если true, добавляет зеленый прямоугольник на холст (рисует как изображение, так и прямоугольник). Если не верно, то прямоугольник удаляется (рисуется только изображение).
Функция draw
отображает холст в соответствии с состоянием переменной rectOn
Нажмите кнопку, чтобы добавить / удалить прямоугольник.
const ctx = canvas.getContext('2d');
var rectOn = false;
const image = new Image();
image.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
image.addEventListener("load", ready, {once:true});
function ready() {
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
loading.classList.add("hide");
addRemove.classList.remove("hide");
addRemove.addEventListener("click", toggle);
draw();
}
function draw() {
ctx.drawImage(image, 0, 0);
if (rectOn) {
ctx.fillStyle = "#0F0";
ctx.fillRect(10, 50, 150, 100);
}
}
function toggle() {
rectOn = !rectOn;
addRemove.textContent = (rectOn ? "Remove": "Add" ) " rect";
draw();
}
button { cursor: pointer; width: 120px }
.hide {display:none}
canvas { position: absolute; top: 0px; left: 0px; z-index:-1; }
<span id="loading">Loading image</span><button id="addRemove" class="hide">Add green rect</button><br>
<canvas id="canvas"></canvas>