Без какой-либо библиотеки расширений возможно ли иметь несколько слоев в одном элементе canvas?
Так что, если я сделаю clearRect на верхнем слое, он не сотрет нижний?
Спасибо.
Без какой-либо библиотеки расширений возможно ли иметь несколько слоев в одном элементе canvas?
Так что, если я сделаю clearRect на верхнем слое, он не сотрет нижний?
Спасибо.
Ответы:
Нет, однако, вы можете наложить несколько <canvas>
элементов друг на друга и сделать что-то похожее.
<div style="position: relative;">
<canvas id="layer1" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="layer2" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>
Нарисуйте свой первый слой на layer1
холсте, а второй слой на layer2
холсте. Затем, когда вы clearRect
на верхнем слое, все, что находится на нижнем холсте, будет просвечивать.
display: none;
. Или просто очистите холст, если не слишком дорого перерисовать его снова, когда слой должен быть показан.
С этим связано:
Если у вас есть что-то на холсте, и вы хотите нарисовать что-то позади него - вы можете сделать это, изменив параметр context.globalCompositeOperation на 'destination-over' - и затем вернуть его в 'source-over', когда вы ' сделано.
var context = document.getElementById('cvs').getContext('2d');
// Draw a red square
context.fillStyle = 'red';
context.fillRect(50,50,100,100);
// Change the globalCompositeOperation to destination-over so that anything
// that is drawn on to the canvas from this point on is drawn at the back
// of what's already on the canvas
context.globalCompositeOperation = 'destination-over';
// Draw a big yellow rectangle
context.fillStyle = 'yellow';
context.fillRect(0,0,600,250);
// Now return the globalCompositeOperation to source-over and draw a
// blue rectangle
context.globalCompositeOperation = 'source-over';
// Draw a blue rectangle
context.fillStyle = 'blue';
context.fillRect(75,75,100,100);
<canvas id="cvs" />
Вы можете создать несколько canvas
элементов, не добавляя их в документ. Это будут ваши слои :
Затем делайте с ними все, что хотите, и в конце просто визуализируйте их содержимое в правильном порядке на целевом холсте, используя drawImage
on context
.
Пример:
/* using canvas from DOM */
var domCanvas = document.getElementById('some-canvas');
var domContext = domCanvas.getContext('2d');
domContext.fillRect(50,50,150,50);
/* virtual canvase 1 - not appended to the DOM */
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue';
ctx.fillRect(50,50,150,150);
/* virtual canvase 2 - not appended to the DOM */
var canvas2 = document.createElement('canvas')
var ctx2 = canvas2.getContext('2d');
ctx2.fillStyle = 'yellow';
ctx2.fillRect(50,50,100,50)
/* render virtual canvases on DOM canvas */
domContext.drawImage(canvas, 0, 0, 200, 200);
domContext.drawImage(canvas2, 0, 0, 200, 200);
И вот некоторые кодовые ручки: https://codepen.io/anon/pen/mQWMMW
У меня тоже была такая же проблема, я в то время как несколько элементов canvas с position: absolute делает работу, если вы хотите сохранить вывод в изображение, это не сработает.
Поэтому я пошел дальше и создал простую многоуровневую «систему» для кодирования, как если бы каждый слой имел свой собственный код, но все это отображается в одном элементе.
https://github.com/federicojacobi/layeredCanvas
Я намерен добавить дополнительные возможности, но пока это будет сделано.
Вы можете выполнять несколько функций и вызывать их, чтобы «подделать» слои.
Вы также можете зайти на http://www.concretejs.com, которая представляет собой современный, легкий, Html5-фреймворк для холста, который позволяет обнаруживать попадания, слои и многое другое. Вы можете делать такие вещи:
var wrapper = new Concrete.Wrapper({
width: 500,
height: 300,
container: el
});
var layer1 = new Concrete.Layer();
var layer2 = new Concrete.Layer();
wrapper.add(layer1).add(layer2);
// draw stuff
layer1.sceneCanvas.context.fillStyle = 'red';
layer1.sceneCanvas.context.fillRect(0, 0, 100, 100);
// reorder layers
layer1.moveUp();
// destroy a layer
layer1.destroy();
Я понимаю, что Q не хочет использовать библиотеку, но я предложу это для других, поступающих из поисков Google. @EricRowell упомянул хороший плагин, но есть и другой плагин, который вы можете попробовать, html2canvas .
В нашем случае мы используем многоуровневые прозрачные PNG с z-index
виджетом «Построитель продукта». Html2canvas блестяще работал для того, чтобы свести стек, не выдвигая изображения, не используя сложности, обходные пути и сам «неотвечающий» холст. Мы не смогли сделать это гладко / вменяемым с vanilla canvas + JS.
Сначала используйте z-index
абсолютные элементы div для создания многоуровневого содержимого в относительной позиционированной оболочке. Затем направьте оболочку через html2canvas, чтобы получить визуализированный холст, который вы можете оставить как есть, или вывести как изображение, чтобы клиент мог его сохранить.
но слой 02 будет охватывать все рисунки в слое 01. Я использовал это, чтобы показать рисунок в обоих слоях. использовать (background-color: прозрачный;) в стиле.
<div style="position: relative;">
<canvas id="lay01" width="500" height="500" style="position: absolute; left: 0; top: 0; z-index: 0; background-color: transparent;">
</canvas>
<canvas id="lay02" width="500" height="500" style="position: absolute; left: 0; top: 0; z-index: 1; background-color: transparent;">
</canvas>
</div>