html5 - phần tử canvas - Nhiều lớp


176

Nếu không có bất kỳ thư viện mở rộng nào, có thể có nhiều lớp trong cùng một thành phần canvas không?

Vì vậy, nếu tôi thực hiện ClearRect trên lớp trên cùng, nó sẽ không xóa lớp dưới cùng?

Cảm ơn.


bạn có thể muốn xem radikalfx.com/2009/10/16/canvas-collage . anh ta sử dụng một loại kỹ thuật "lớp".
Matthew

2
kiểm tra xem .. html5.litten.com/USE-mult Môn-html5-canvases-as-layers này sẽ giúp bạn giải quyết vấn đề của mình theo cách thích hợp
Dakshika

@Dakshika Cảm ơn bạn vì liên kết đó, nó đã giải thích một vấn đề tôi đã sử dụng canvas vài năm trước mà một thư viện đã chăm sóc cho tôi.
Fering

Câu trả lời:


267

Tuy nhiên, không, bạn có thể xếp nhiều <canvas>yếu tố lên nhau và hoàn thành một cái gì đó tương tự.

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

Vẽ lớp đầu tiên của bạn trên layer1khung vẽ và lớp thứ hai trên layer2khung vẽ. Sau đó, khi bạn clearRectở lớp trên cùng, bất cứ thứ gì ở khung dưới sẽ hiển thị qua.


Có cách nào để ẩn / bỏ ẩn một lớp .. để tôi có thể ẩn layer1 và hiển thị layer2 và làm ngược lại khi được yêu cầu .. ??
Zaraki

4
Bạn có thể ẩn nó bằng CSS - tức là display: none;. Hoặc chỉ cần xóa khung vẽ, nếu nó không quá đắt để vẽ lại nó khi lớp sẽ được hiển thị.
jimr

Các giá trị được gán cho 'trái' và 'trên cùng' cần phải là '0px', không phải '0'.
Bryan Green

6
@BryanGreen Không đúng. "Tuy nhiên, với độ dài bằng không, định danh đơn vị là tùy chọn (nghĩa là có thể được biểu diễn bằng cú pháp dưới dạng <number> 0)." w3.org/TR/css3-values/#lengths
xehpuk

Tôi có thể kiểm soát loại thành phần cho nhiều canvas không?
ziyuang

40

Liên quan đến điều này:

Nếu bạn có một cái gì đó trên khung vẽ của mình và bạn muốn vẽ một cái gì đó ở mặt sau của nó - bạn có thể làm điều đó bằng cách thay đổi cài đặt bối cảnh.globalCompổngOperation thành 'Destination-over' - và sau đó đưa nó trở lại 'source-over' khi bạn ' làm lại

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


vâng, điều đó là tốt nhưng trong trường hợp xóa, như được hỏi trong câu hỏi. điều này sẽ xóa cả hai lớp song song. mà lại không đúng
Pardeep Jain

27

Bạn có thể tạo nhiều canvasyếu tố mà không cần thêm chúng vào tài liệu. Đây sẽ là các lớp của bạn :

Sau đó, làm bất cứ điều gì bạn muốn với họ và cuối cùng chỉ cần hiển thị nội dung của họ theo đúng thứ tự tại khung hình đích sử dụng drawImagetrên context.

Thí dụ:

/* 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);

Và đây là một số codepen: https://codepen.io/anon/pen/mQWMMW


4
@SCLeo bạn nói "Kẻ giết người hiệu suất. Chậm hơn khoảng 10 lần" là hoàn toàn sai. Tùy thuộc vào các trường hợp sử dụng bằng cách sử dụng một khung vải DOM duy nhất và hiển thị các khung vẽ ngoài màn hình để nhanh hơn so với xếp chồng vải trong DOM. Lỗi phổ biến là các cuộc gọi kết xuất điểm chuẩn, các cuộc gọi vẽ canvas có thể được định thời gian, kết xuất DOM nằm ngoài ngữ cảnh Javascripts và không thể được định thời gian. Kết quả là khung vẽ được xếp chồng DOM không nhận được kết xuất tổng hợp (được thực hiện bởi DOM) được bao gồm trong điểm chuẩn ..
Blindman67

@ Blindman67 Tôi hiểu ý của bạn. Chỉ cần kiểm tra điểm chuẩn này: jsfiddle.net/9a9L8k7k/1 . Trong trường hợp bạn hiểu nhầm, có ba canvas, canvas 1 (ctx1) là một canvas thực sự. Canvas 2 (ctx2) và canvas 3 (ctx) tắt màn hình. Hình ảnh đã được kết xuất trước đó trên ctx3. Trong thử nghiệm 1 của điểm chuẩn này, tôi trực tiếp kết xuất ctx3 lên ctx1. Trong thử nghiệm 2, tôi kết xuất ctx3 lên ctx2 và sau đó ctx2 thành ctx1. Kiểm tra 2 chậm hơn 30 lần so với kiểm tra 1 trên máy tính của tôi. Đó là lý do tại sao tôi nói sử dụng một canvas trung gian chậm hơn nhiều.
SCLeo

@ Blindman67 Thủ thuật canvas ngoài màn hình chỉ hoạt động khi canvas ngoài màn hình tĩnh. Sử dụng canvas động sẽ làm hỏng rất nhiều hiệu suất. (Một lần nữa, điều tôi đang cố gắng nói là canvas ngoài màn hình động cực kỳ chậm nên có lẽ kỹ thuật này (giả các lớp bằng nhiều canvas ngoài màn hình) sẽ không được mong muốn)
SCLeo

@ Blindman67 QUAN TRỌNG: Địa chỉ của điểm chuẩn là https://jsfiddle.net/9a9L8k7k/3 , tôi quên lưu sau khi chỉnh sửa và Stack Overflow không cho phép tôi thay đổi nhận xét trước đó nữa ...
SCLeo

4
@ Blindman67 Tôi xin lỗi, đó là sai lầm của tôi. Tôi đã thử nghiệm và thấy rằng sử dụng nhiều màn hình tắt màn hình sẽ chạy rất trơn tru. Tôi vẫn không chắc tại sao điểm chuẩn đó cho thấy rằng sử dụng tắt màn hình là chậm.
SCLeo

6

Tôi cũng gặp vấn đề tương tự, trong khi nhiều yếu tố canvas có vị trí: công việc tuyệt đối, nếu bạn muốn lưu kết quả đầu ra vào hình ảnh, điều đó sẽ không hiệu quả.

Vì vậy, tôi đã tiếp tục và thực hiện một "hệ thống" phân lớp đơn giản để mã hóa như thể mỗi lớp có mã riêng, nhưng tất cả được kết xuất thành cùng một phần tử.

https://github.com/federicojacobi/layeredCanvas

Tôi dự định thêm các khả năng bổ sung, nhưng bây giờ nó sẽ làm được.

Bạn có thể thực hiện nhiều chức năng và gọi chúng để các lớp "giả".


Điều này là hoàn hảo.
Nadir

4

Bạn cũng có thể kiểm tra http://www.concittlejs.com , một khung vải Html5 hiện đại, gọn nhẹ, cho phép phát hiện, đánh lớp và nhiều thứ ngoại vi khác. Bạn có thể làm những việc như thế này:

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();

Bằng cách nào các lớp đó sẽ kết thúc trong DOM? Mỗi người có thể truy cập qua CSS?
Garavani

0

Tôi hiểu rằng Q không muốn sử dụng thư viện, nhưng tôi sẽ cung cấp dịch vụ này cho những người khác đến từ các tìm kiếm của Google. @EricRowell đã đề cập đến một plugin tốt, nhưng, cũng có một plugin khác bạn có thể thử, html2canvas .

Trong trường hợp của chúng tôi, chúng tôi đang sử dụng các PNG trong suốt được xếp lớp với z-indextư cách là tiện ích "trình tạo sản phẩm". Html2canvas đã làm việc tuyệt vời để đun sôi ngăn xếp xuống mà không đẩy hình ảnh, cũng không sử dụng độ phức tạp, cách giải quyết và bản thân khung vẽ "không phản hồi". Chúng tôi không thể thực hiện điều này một cách trơn tru / lành mạnh với khung vẽ vanilla + JS.

Đầu tiên sử dụng z-indextrên div tuyệt đối để tạo nội dung lớp trong một trình bao bọc được định vị tương đối. Sau đó, đưa trình bao bọc qua html2canvas để có được một khung vẽ được hiển thị, mà bạn có thể để nguyên trạng hoặc xuất ra dưới dạng hình ảnh để khách hàng có thể lưu nó.


Nếu bạn có hình ảnh nặng hơn, việc này sẽ mất một chút thời gian để chuyển đổi HTML sang canvas, chúng tôi đã phải tránh xa điều này chỉ vì việc kết xuất mất nhiều thời gian.
Vilius

@Vilius yeah gọi tốt trên hình ảnh nặng / lớn. Chúng tôi đã cố gắng bám vào hình ảnh 300K hoặc ít hơn với không quá 4 lớp, các khách hàng bị ảnh hưởng tài nguyên khác sẽ cảm thấy bỏng rát khi tải xuống hình ảnh phân trộn cuối cùng. Tò mò, bạn đã làm gì để giảm thời gian?
dhaupin

Vâng, chúng tôi đã phạm một sai lầm lớn bằng cách sử dụng các yếu tố html để vẽ một cái gì đó ở vị trí đầu tiên. Vì api của chúng tôi trả về x, y, chiều rộng và chiều cao, chúng tôi đã chuyển sang jscanavs để vẽ hình ảnh thay vì sử dụng các phần tử html. Xin lưu ý rằng chúng tôi đã có một số vấn đề với xoay vòng (điểm bắt đầu hơi khó xử và không thể đoán trước) và áp dụng hình ảnh cho nó bằng các kích thước cụ thể nhưng cuối cùng tất cả đã được giải quyết. Chúng tôi cũng nhận thấy rằng ứng dụng xử lý hình ảnh của chúng tôi đã làm cạn kiệt rất nhiều tài nguyên, vì vậy chúng tôi cũng đã chuyển đi từ đó.
Vilius

0

nhưng lớp 02, sẽ bao gồm tất cả các bản vẽ trong lớp 01. Tôi đã sử dụng nó để hiển thị bản vẽ trong cả hai lớp. sử dụng (màu nền: trong suốt;) trong phong cách.

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.