Narysuj pierwszą warstwę na layer1płótnie, a drugą na layer2płótnie. Następnie, gdy jesteś clearRectna górnej warstwie, prześwituje wszystko, co znajduje się na niższym płótnie.
czy istnieje sposób na ukrycie / pokazanie warstwy .. tak, że mogę ukryć warstwę 1 i pokazać warstwę 2 i zrobić odwrotnie, gdy jest to wymagane .. ??
Zaraki
4
Można to ukryć za pomocą CSS - tj display: none;. Lub po prostu wyczyść płótno, jeśli ponowne narysowanie go ponownie, gdy warstwa powinna zostać wyświetlona, nie jest zbyt kosztowne.
Jimr
Wartości przypisane do „left” i „top” muszą mieć wartość „0px”, a nie „0”.
Bryan Green
6
@BryanGreen Nie prawda. „Jednak dla zerowych długości identyfikator jednostki jest opcjonalny (tj. Może być składniowo reprezentowany jako <numer> 0)”. w3.org/TR/css3-values/#lengths
xehpuk
Czy mogę kontrolować typ kompozycji dla wielu kanw?
ziyuang
40
Powiązane z tym:
Jeśli masz coś na płótnie i chcesz narysować coś z tyłu - możesz to zrobić, zmieniając ustawienie context.globalCompositeOperation na „destination-over” - a następnie przywróć je do „source-over”, kiedy to zrobisz gotowe.
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);
tak, to jest w porządku, ale w przypadku skasowania, jak zadano w pytaniu. spowoduje to równoległe wymazanie obu warstw. co znowu nie jest poprawne.
Pardeep Jain
27
Możesz tworzyć wiele canvaselementów bez dołączania ich do dokumentu. To będą twoje warstwy :
Następnie rób z nimi, co chcesz, a na koniec po prostu renderuj ich zawartość w odpowiedniej kolejności na docelowym płótnie, używając drawImageon context.
Przykład:
/* 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);
@SCLeo powiedziałeś, że „zabójca wydajności. Około ~ 10 razy wolniej” jest całkowicie błędny. W zależności od przypadków użycia użycie pojedynczego płótna DOM i renderowanie do niego kanw poza ekranem jest szybsze niż układanie kanw w DOM. Częstym błędem jest testowanie wywołań renderowania, wywołania rysowania kanwy mogą być synchronizowane w czasie, renderowanie DOM jest poza kontekstem JavaScript i nie można ich ustawić w czasie. W rezultacie płótno ułożone w stos be DOM nie otrzymuje renderowania kompozycji (wykonanego przez DOM) zawartego w
teście
@ Blindman67 Wiem, co masz na myśli. Po prostu sprawdź ten test porównawczy: jsfiddle.net/9a9L8k7k/1 . Jeśli źle zrozumiesz, są trzy płótna, płótno 1 (ctx1) to prawdziwe płótno. Canvas 2 (ctx2) i canvas 3 (ctx) są poza ekranem. Obraz został wcześniej wyrenderowany na ctx3. W teście 1 tego testu porównawczego renderuję bezpośrednio ctx3 na ctx1. W teście 2 renderuję ctx3 na ctx2, a następnie ctx2 na ctx1. Test 2 jest 30 razy wolniejszy niż test 1 na moim komputerze. Dlatego mówię, że używanie pośredniego płótna jest znacznie wolniejsze.
SCLeo
@ Blindman67 Sztuczka z płótnem poza ekranem działa tylko wtedy, gdy płótno poza ekranem jest statyczne. Używanie dynamicznych płócien znacznie obniży wydajność. (Ponownie, próbuję powiedzieć, że dynamiczne płótno poza ekranem jest wyjątkowo wolne, więc przypuszczalnie ta technika (pozorowanie warstw przez wiele
obszarów
@ Blindman67 WAŻNE: Adres benchmarku to https://jsfiddle.net/9a9L8k7k/3 , zapomniałem zapisać po edycji, a przepełnienie stosu nie pozwala mi już zmienić poprzedniego komentarza ...
SCLeo
4
@ Blindman67 Przepraszam, to mój błąd. Przetestowałem i stwierdziłem, że korzystanie z wielu kanw poza ekranem działa bardzo płynnie. Nadal nie jestem pewien, dlaczego ten test porównawczy pokazuje, że używanie płótna poza ekranem jest tak wolne.
SCLeo
6
Miałem też ten sam problem, podczas gdy wiele elementów płótna z pozycją: absolutne spełnia swoje zadanie, jeśli chcesz zapisać wynik do obrazu, to nie zadziała.
Więc poszedłem do przodu i zrobiłem prosty "system" warstwowania, aby zakodować tak, jakby każda warstwa miała swój własny kod, ale wszystko jest renderowane w tym samym elemencie.
Możesz również sprawdzić http://www.concretejs.com, który jest nowoczesnym, lekkim frameworkiem HTML5, który umożliwia wykrywanie trafień, nakładanie warstw i wiele innych peryferyjnych rzeczy. Możesz robić takie rzeczy:
var wrapper =newConcrete.Wrapper({
width:500,
height:300,
container: el
});var layer1 =newConcrete.Layer();var layer2 =newConcrete.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();
W jaki sposób te warstwy trafią do DOM? Każdy dostępny przez CSS?
Garavani
0
Rozumiem, że Q nie chce korzystać z biblioteki, ale zaoferuję to innym osobom pochodzącym z wyszukiwań Google. @EricRowell wspomniał o dobrej wtyczce, ale jest też inna wtyczka, którą możesz wypróbować, html2canvas .
W naszym przypadku używamy warstwowych przezroczystych plików PNG z z-indexwidżetem „konstruktora produktu”. Html2canvas działał znakomicie, aby ugotować stos bez przesuwania obrazów ani stosowania zawiłości, obejść i samego „niereagującego” płótna. Nie byliśmy w stanie zrobić tego płynnie / rozsądnie z płótnem waniliowym + JS.
Pierwsze użycie z-indexna absolutnych elementach DIV w celu wygenerowania zawartości warstwowej we względnie pozycjonowanym opakowaniu. Następnie przepuść opakowanie przez html2canvas, aby uzyskać renderowane płótno, które możesz pozostawić bez zmian, lub wyprowadzić jako obraz, aby klient mógł go zapisać.
Jeśli masz cięższe obrazy, konwersja HTML do płótna zajmie trochę czasu, musieliśmy odejść od tego tylko dlatego, że renderowanie trwało długo.
Vilius
@Vilius yeah dobre wezwanie na ciężkie / duże obrazy. Próbowaliśmy trzymać się 300 KB lub mniej obrazów z nie więcej niż 4 warstwami, w przeciwnym razie klienci, którzy mają problemy z zasobami, poczuliby pieczenie podczas pobierania ostatecznego skompostowanego obrazu. Ciekawe, co przeszedłeś do tego skróconego czasu?
dhaupin,
Cóż, popełniliśmy duży błąd, używając elementów HTML do narysowania czegoś w pierwszej kolejności. Ponieważ nasz interfejs API zwrócił x, y, szerokość i wysokość, przeszliśmy do jscanavs, aby narysować obraz zamiast używać elementów html. Pamiętaj, że mieliśmy kilka problemów z obracaniem (punkty początkowe były nieco niezręczne i nieprzewidywalne) oraz nakładaniem na nie obrazów przy użyciu określonych wymiarów, ale wszystko zostało ostatecznie rozwiązane. Odkryliśmy również, że nasza aplikacja do przetwarzania obrazów pochłaniała dużo zasobów, więc również odeszliśmy od tego.
Vilius,
0
ale warstwa 02 pokryje wszystkie rysunki w warstwie 01. Użyłem tego do pokazania rysunków w obu warstwach. użyj stylu (background-color: transparent;).
Odpowiedzi:
Nie, jednak możesz nałożyć wiele
<canvas>
elementów jeden na drugi i osiągnąć coś podobnego.Narysuj pierwszą warstwę na
layer1
płótnie, a drugą nalayer2
płótnie. Następnie, gdy jesteśclearRect
na górnej warstwie, prześwituje wszystko, co znajduje się na niższym płótnie.źródło
display: none;
. Lub po prostu wyczyść płótno, jeśli ponowne narysowanie go ponownie, gdy warstwa powinna zostać wyświetlona, nie jest zbyt kosztowne.Powiązane z tym:
Jeśli masz coś na płótnie i chcesz narysować coś z tyłu - możesz to zrobić, zmieniając ustawienie context.globalCompositeOperation na „destination-over” - a następnie przywróć je do „source-over”, kiedy to zrobisz gotowe.
źródło
Możesz tworzyć wiele
canvas
elementów bez dołączania ich do dokumentu. To będą twoje warstwy :Następnie rób z nimi, co chcesz, a na koniec po prostu renderuj ich zawartość w odpowiedniej kolejności na docelowym płótnie, używając
drawImage
oncontext
.Przykład:
A oto kilka kodów: https://codepen.io/anon/pen/mQWMMW
źródło
Miałem też ten sam problem, podczas gdy wiele elementów płótna z pozycją: absolutne spełnia swoje zadanie, jeśli chcesz zapisać wynik do obrazu, to nie zadziała.
Więc poszedłem do przodu i zrobiłem prosty "system" warstwowania, aby zakodować tak, jakby każda warstwa miała swój własny kod, ale wszystko jest renderowane w tym samym elemencie.
https://github.com/federicojacobi/layeredCanvas
Zamierzam dodać dodatkowe możliwości, ale na razie wystarczy.
Możesz wykonywać wiele funkcji i wywoływać je w celu „sfałszowania” warstw.
źródło
Możesz również sprawdzić http://www.concretejs.com, który jest nowoczesnym, lekkim frameworkiem HTML5, który umożliwia wykrywanie trafień, nakładanie warstw i wiele innych peryferyjnych rzeczy. Możesz robić takie rzeczy:
źródło
Rozumiem, że Q nie chce korzystać z biblioteki, ale zaoferuję to innym osobom pochodzącym z wyszukiwań Google. @EricRowell wspomniał o dobrej wtyczce, ale jest też inna wtyczka, którą możesz wypróbować, html2canvas .
W naszym przypadku używamy warstwowych przezroczystych plików PNG z
z-index
widżetem „konstruktora produktu”. Html2canvas działał znakomicie, aby ugotować stos bez przesuwania obrazów ani stosowania zawiłości, obejść i samego „niereagującego” płótna. Nie byliśmy w stanie zrobić tego płynnie / rozsądnie z płótnem waniliowym + JS.Pierwsze użycie
z-index
na absolutnych elementach DIV w celu wygenerowania zawartości warstwowej we względnie pozycjonowanym opakowaniu. Następnie przepuść opakowanie przez html2canvas, aby uzyskać renderowane płótno, które możesz pozostawić bez zmian, lub wyprowadzić jako obraz, aby klient mógł go zapisać.źródło
ale warstwa 02 pokryje wszystkie rysunki w warstwie 01. Użyłem tego do pokazania rysunków w obu warstwach. użyj stylu (background-color: transparent;).
źródło