html5-캔버스 요소-여러 레이어


176

확장 라이브러리가 없으면 동일한 캔버스 요소에 여러 레이어를 가질 수 있습니까?

상단 레이어에서 clearRect를 수행하면 하단 레이어가 지워지지 않습니까?

감사.


radikalfx.com/2009/10/16/canvas-collage를 살펴 보십시오 . 그는 일종의 "레이어"기술을 사용합니다.
Matthew

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상단 레이어에 있을 때 하단 캔버스에있는 모든 내용이 표시됩니다.


레이어를 숨기거나 숨기기를 해제하는 방법이 있습니까?. layer1을 숨기고 layer2를 표시하고 필요할 때 그 반대로 할 수 있도록 .. ??
Zaraki

4
CSS로 숨길 수 display: none;있습니다. 즉 . 또는 레이어를 표시해야 할 때 다시 그리기가 너무 비싸지 않으면 캔버스를 지우십시오.
jimr

'left'및 'top'에 지정된 값은 '0'이 아닌 '0px'이어야합니다.
Bryan Green

6
@BryanGreen 사실이 아닙니다. "그러나 길이가 0 인 경우 단위 식별자는 선택 사항입니다 (즉, <숫자> 0으로 구문 적으로 표현할 수 있음)." w3.org/TR/css3-values/#lengths
xehpuk

여러 캔버스의 컴포지션 유형을 제어 할 수 있습니까?
ziyuang

40

이것과 관련하여 :

캔버스에 무언가가 있고 그 뒤에 무언가를 그리려면 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" />


그렇습니다. 문제가되는 것처럼 지우는 경우에는 괜찮습니다. 두 레이어가 동시에 지워집니다. 다시는 맞지 않습니다.
Pardeep Jain

27

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


4
@SCLeo는 "성능 킬러. ~ 10 배 정도 느리다"고 말한 것은 완전히 잘못된 것입니다. 단일 DOM 캔버스를 사용하고 오프 스크린 캔버스를 렌더링하는 사용 사례에 따라 DOM에서 캔버스를 스택하는 것보다 빠릅니다. 일반적인 실수는 렌더링 호출 벤치마킹, 캔버스 그리기 호출 시간 초과, DOM 렌더링이 Javascript 컨텍스트 외부에 있으며 시간 초과가 불가능하다는 것입니다. 결과는 수 DOM 캔버스가 합성이 벤치 마크에 포함 (DOM에 의해 수행) 렌더링하지 않는 스택이다 ..
Blindman67

@ Blindman67 무슨 말인지 알 겠어. jsfiddle.net/9a9L8k7k/1 벤치 마크를 확인하십시오 . 오해의 경우 3 개의 캔버스가 있으며 캔버스 1 (ctx1)은 실제 캔버스입니다. 캔버스 2 (ctx2)와 캔버스 3 (ctx)이 화면에서 벗어납니다. 이미지는 이전에 ctx3에 렌더링되었습니다. 이 벤치 마크의 테스트 1에서 ctx3을 ctx1에 직접 렌더링합니다. 테스트 2에서는 ctx3을 ctx2에 렌더링 한 다음 ctx2를 ctx1에 렌더링합니다. 테스트 2는 내 컴퓨터의 테스트 1보다 30 배 느립니다. 그래서 중간 캔버스를 사용하는 것이 훨씬 느리다고 말합니다.
SCLeo April

@ Blindman67 오프 스크린 캔버스의 트릭은 오프 스크린 캔버스가 정적 일 때만 작동합니다. 동적 캔버스를 사용하면 성능이 크게 손상됩니다. (다시 말해서, 동적 오프 스크린 캔버스는 매우 느리기 때문에 아마도이 기술 (여러 개의 오프 스크린 캔버스에 의한 모의 레이어)은 바람직하지 않을 것입니다)
SCLeo

@ Blindman67 중요 : 벤치 마크 주소는 https://jsfiddle.net/9a9L8k7k/3입니다 . 편집 후 저장을 잊어 버리고 스택 오버플로로 인해 이전 주석을 더 이상 변경할 수 없습니다.
SCLeo

4
@ Blindman67 죄송합니다. 실수입니다. 테스트를 거쳐 여러 오프 스크린 캔버스를 사용하는 것이 매우 부드럽게 실행된다는 것을 알았습니다. 벤치 마크에서 오프 스크린 캔버스를 사용하는 것이 그렇게 느리다는 것을 여전히 알 수 없습니다.
SCLeo

6

나는 같은 문제가 있었지만 position : absolute가있는 여러 캔버스 요소가 작업을 수행하지만 출력을 이미지에 저장하려는 경우 작동하지 않습니다.

각 레이어마다 고유의 코드가있는 것처럼 코딩하기 위해 간단한 계층화 "시스템"을 수행했지만 모두 동일한 요소로 렌더링됩니다.

https://github.com/federicojacobi/layeredCanvas

추가 기능을 추가하려고하지만 지금은 가능합니다.

레이어를 "가짜"만들기 위해 여러 기능을 수행하고 호출 할 수 있습니다.


이것은 완벽하다.
Nadir

4

또한 히트 감지, 계층화 및 기타 많은 주변 장치를 가능하게하는 현대적이고 가벼운 Html5 캔버스 프레임 워크 인 http://www.concretejs.com 을 확인 하십시오 . 다음과 같은 작업을 수행 할 수 있습니다.

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를 통해 액세스 할 수 있습니까?
Garavani

0

Q는 라이브러리를 사용하고 싶지 않지만 Google 검색에서 온 다른 사람들에게이 라이브러리를 제공 할 것임을 이해합니다. @EricRowell 당신이 시도 할 수있는 다른 플러그인도있다, 좋은 플러그인을 언급하지만, html2canvas가 .

우리의 경우 z-index에는 "제품 빌더"위젯으로 레이어 투명 PNG를 사용 하고 있습니다. Html2canvas는 이미지를 밀거나 복잡성, 해결 방법 및 "무응답"캔버스 자체를 사용하지 않고 스택을 끓이기 위해 훌륭하게 작동했습니다. 우리는 바닐라 캔버스 + JS로 이것을 매끄럽게 / 제정신으로 할 수 없었습니다.

z-index절대 div를 먼저 사용 하여 상대적으로 배치 된 래퍼 내에 계층화 된 컨텐츠를 생성하십시오. 그런 다음 래퍼를 html2canvas를 통해 파이프하여 렌더링 된 캔버스를 가져 오십시오. 클라이언트는 캔버스를 그대로두고 이미지로 출력 할 수 있습니다.


더 무거운 이미지가있는 경우 HTML을 캔버스로 변환하는 데 시간이 걸립니다. 렌더링 시간이 오래 걸리기 때문에이 문제에서 벗어나야했습니다.
Vilius

@Vilius 네, 무겁고 큰 이미지는 좋은 전화입니다. 우리는 4 레이어를 넘지 않는 300K 이하의 이미지를 고수하려고 노력했습니다. 궁금한 점, 그 단축 된 시간으로 무엇을 옮겼습니까?
dhaupin

글쎄, 우리는 처음에 무언가를 그리는 데 html 요소를 사용하여 큰 실수를했습니다. api가 x, y, width 및 height를 반환했기 때문에 html 요소를 사용하는 대신 이미지를 그리기 위해 jscanavs로 이동했습니다. 회전 (시작점이 약간 어색하고 예측할 수 없음)과 특정 치수를 사용하여 이미지를 적용하는 데 몇 가지 문제가 있었지만 결국에는 모두 해결되었습니다. 또한 이미지 처리 응용 프로그램에서 많은 리소스를 소모하고 있다는 사실도 발견했습니다.
Vilius

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>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.