html5 - елемент полотна - Кілька шарів


176

Чи можливо без бібліотеки розширень мати кілька шарів в одному елементі полотна?

Тож якщо я виконаю clearRect на верхньому шарі, він не видалить нижній?

Дякую.


ви можете поглянути на radikalfx.com/2009/10/16/canvas-collage . він використовує своєрідну техніку "шарів".
Метью

2
перевірте це .. html5.litten.com/using-multiple-html5-canvases-as-layers це допоможе вам вирішити свою проблему належним чином
Dakshika

@Dakshika Дякую за те посилання, це пояснило проблему, якою я користувався полотном кілька років тому, що про мене піклувалася бібліотека.
Fering

Відповіді:


267

Ні, однак, ви можете накласти кілька <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на верхньому шарі, все, що є на нижньому полотні, буде показано наскрізь.


чи існує спосіб приховування / приховування шару .. такий, що я можу приховати шар1 та показати слой2 та зробити навпаки, коли потрібно .. ??
Заракі

4
Ви можете приховати це за допомогою CSS - тобто display: none;. Або просто очистити полотно, якщо це не надто дорого, щоб перемалювати його знову, коли шар повинен бути показаний.
jimr

Значення, присвоєні 'зліва' та 'top', мають бути "0px", а не "0".
Брайан Грін

6
@BryanGreen Неправда. "Однак для нульових довжин ідентифікатор одиниці є необов'язковим (тобто може бути синтаксично представлений як <число> 0)." w3.org/TR/css3-values/#lengths
xehpuk

Чи можна контролювати тип композиції для кількох полотен?
ziyuang

40

Пов’язане з цим:

Якщо у вас є щось на полотні, і ви хочете намалювати щось на задній панелі - ви можете це зробити, змінивши налаштування контексту.globalCompositeOperation на «призначення-над», а потім повернути його на «джерело-над», коли ви » зроблено.

   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" />


так, це добре, але у випадку стирання, про що йдеться в запитанні. це видалить обидва шари паралельно. що знову не правильно.
Pardeep Jain

27

Можна створити кілька canvasелементів, не додаючи їх до документа. Це будуть ваші шари :

Тоді робити все , що ви хочете з ними і в кінці кінців просто роблять їх утримання в належному порядку на цільовому полотні , використовуючи drawImageна 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


4
@SCLeo Ви сказали, що "Вбивця продуктивності. Приблизно ~ в 10 разів повільніше" абсолютно неправильно. Залежно від випадків використання, використовуючи одне полотно DOM, а рендерувати екранні полотна швидше, ніж укладання полотна в DOM. Поширена помилка - тестування дзвінків на основі тестування, дзвінки з малюнком на полотні можуть бути приурочені, рендемінг DOM знаходиться поза контекстом Javascripts і не може бути приурочений. Результат полягає в тому, що полотно, розміщене у форматі DOM, не отримує композиційну візуалізацію (виконано DOM), включену в орієнтир ..
Blindman67

@ Blindman67 Я знаю, що ти маєш на увазі. Просто перевірте цей орієнтир: jsfiddle.net/9a9L8k7k/1 . Якщо ви неправильно розумієте, є три полотна, полотно 1 (ctx1) - справжнє полотно. Полотно 2 (ctx2) і полотно 3 (ctx) вимкнено. Зображення було раніше виведено на ctx3. У тесті 1 цього еталону я безпосередньо вивожу ctx3 на ctx1. У тесті 2 я перетворюю ctx3 на ctx2, а потім ctx2 на ctx1. Тест 2 в 30 разів повільніше, ніж тест 1 на моєму комп’ютері. Тому я кажу, що використання проміжного полотна набагато повільніше.
SCLeo

@ Blindman67 Витівка полотна поза екраном працює лише тоді, коли полотно поза екраном статичне. Використання динамічних полотен значно пошкодить продуктивність. (Знову ж таки, те, що я намагаюся сказати, - динамічне полотно поза екраном надзвичайно повільне, тому, мабуть, ця техніка (знущатися з шарів за допомогою декількох полотен поза екраном) не буде бажаною)
SCLeo

@ Blindman67 ВАЖЛИВО: Адреса еталону https://jsfiddle.net/9a9L8k7k/3 , я забуду зберегти після редагування, і переповнення стека не дозволяє мені більше змінювати попередній коментар ...
SCLeo

4
@ Blindman67 Вибачте, це моя помилка. Я перевірив і виявив, що використання полотна з декількома екранами працює дуже гладко. Я все ще не впевнений, чому цей показник показує, що використання полотна поза екраном відбувається настільки повільно.
SCLeo

6

У мене була ця сама проблема, я, хоча кілька елементів полотна з позицією: абсолют робить роботу, якщо ви хочете зберегти вихід у зображення, це не спрацює.

Тому я пішов вперед і зробив просту багатошарову "систему", щоб кодувати так, ніби кожен шар мав свій код, але все це перетворюється в один і той же елемент.

https://github.com/federicojacobi/layeredCanvas

Я маю намір додати додаткові можливості, але поки це зробить.

Ви можете виконувати кілька функцій і викликати їх, щоб "підробити" шари.


Цей ідеальний.
Надір

4

Ви також можете замовити 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();

Яким чином ці шари опиняться в DOM? Кожен із них доступний через CSS?
Гаравані

0

Я розумію, що Q не хоче використовувати бібліотеку, але я запропоную це для інших, які надходять із пошукових запитів Google. @EricRowell згадав про хороший плагін, але є також інший плагін, який ви можете спробувати, html2canvas .

У нашому випадку ми використовуємо шаруваті прозорі PNG з z-indexвіджетом "конструктор продуктів". Html2canvas блискуче працював над тим, щоб звести стек вниз, не підштовхуючи зображення, не використовуючи складності, обхідні шляхи та саме "невідповідальне" полотно. Ми не змогли зробити це плавно / здорово за допомогою ванільного полотна + JS.

Спочатку використовуйте z-indexабсолютні знаки, щоб генерувати шаруватий вміст у відносно розташованій обгортці. Потім передайте обгортку через html2canvas, щоб отримати відтворене полотно, яке ви можете залишити як є, або вивести у вигляді зображення, щоб клієнт міг зберегти його.


Якщо у вас є більш важкі зображення, це потребує певного часу, щоб перетворити HTML на полотно, нам довелося відійти від цього лише тому, що візуалізація зайняла тривалий час.
Vilius

@Vilius так, добре зателефонуйте на важкі / великі зображення. Ми намагалися приклеїти зображення до 300 Кб або менше, що не перевищує 4 шари, інакше клієнти, які страждають ресурсами, відчують опік при завантаженні остаточного складеного зображення. Цікаво, що ти перейшов у цей скорочений час?
dhaupin

Що ж, ми зробили велику помилку, використовуючи html елементи, щоб намалювати щось в першу чергу. Оскільки наш api повернув x, y, ширину та висоту, ми перейшли до jscanavs, щоб намалювати зображення замість використання html-елементів. Зауважте, у нас було кілька проблем із обертанням (початкові точки були трохи незручними та непередбачуваними) та нанесенням на нього зображень за допомогою конкретних розмірів, але все було вирішено в підсумку. Ми також виявили, що наша програма для обробки зображень витрачає багато ресурсів, тому ми теж віддалилися від цього.
Вілій

0

але шар 02 буде охоплювати всі малюнки в шарі 01. Я використовував це, щоб показати малюнок в обох шарах. використання (колір фону: прозорий;) у стилі.

    <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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.