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キャンバスに最初のレイヤーを描画し、キャンバスに2番目のレイヤーを描画しますlayer2。次にclearRect、上のレイヤーに移動すると、下のキャンバスにあるものが透けて見えます。


レイヤーを非表示/再表示する方法はありますか?レイヤー1を非表示にしたり、レイヤー2を表示したり、必要に応じてその逆もできるようにします。
Zaraki

4
あなたはCSSでそれを隠すことができます-すなわちdisplay: none;。または、レイヤーを表示する必要があるときに再度描画するのにそれほど費用がかからない場合は、キャンバスをクリアします。
jimr

「左」と「上」に割り当てられる値は「0」ではなく「0px」である必要があります。
ブライアン・グリーン

6
@BryanGreen真実ではありません。「ただし、長さがゼロの場合、ユニット識別子はオプションです(つまり、<number> 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ドキュメントに追加せずに複数の要素を作成できます。これらはあなたのレイヤーになります:

次に、それらを使用して好きなことを行い、最後にdrawImageon を使用して宛先のキャンバスでコンテンツを適切な順序でレンダリングします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のコンテキスト外にあり、時間計測ができないことです。その結果、be DOMスタックキャンバスは、ベンチマークに含まれる合成レンダリング(DOMによって行われる)を取得しません
。–

@ Blindman67私はあなたの意味を知っています。このベンチマークをチェックアウトしてください:jsfiddle.net/9a9L8k7k/1。誤解しているかもしれませんが、キャンバスは3つあり、キャンバス1(ctx1)は実際のキャンバスです。Canvas 2(ctx2)とcanvas 3(ctx)は画面外にあります。画像は以前にctx3にレンダリングされています。このベンチマークのテスト1では、ctx3をctx1に直接レンダリングします。テスト2では、ctx3をctx2にレンダリングし、次にctx2をctx1にレンダリングします。テスト2は、私のコンピューターでのテスト1の30倍遅いです。そのため、中間キャンバスの使用は非常に遅くなります。
SCLeo 2017

@ Blindman67オフスクリーンキャンバスのトリックは、オフスクリーンキャンバスが静的な場合にのみ機能します。動的キャンバスを使用すると、パフォーマンスが大幅に低下します。(繰り返しますが、動的なオフスクリーンキャンバスは非常に遅いため、おそらくこの手法(複数のオフスクリーンキャンバスによるモックレイヤー)は望ましくないでしょう)
SCLeo

@ Blindman67重要:ベンチマークのアドレスはhttps://jsfiddle.net/9a9L8k7k/3です編集後に保存するのを忘れて、スタックオーバーフローによって以前のコメントを変更できなくなりました...
SCLeo

4
@ Blindman67すみません、それは私の間違いです。テストしたところ、複数のオフスクリーンキャンバスを使用すると、非常にスムーズに実行されます。そのベンチマークがオフスクリーンキャンバスの使用が遅いことを示している理由はまだわかりません。
SCLeo 2017

6

私も同じ問題を抱えていましたが、position:absoluteを持つ複数のcanvas要素が機能しますが、出力を画像に保存したい場合は機能しません。

そこで、私は先に進んで、各レイヤーに独自のコードがあるかのようにコーディングする単純なレイヤー化「システム」を実行しましたが、すべてが同じ要素にレンダリングされます。

https://github.com/federicojacobi/layeredCanvas

機能を追加するつもりですが、今のところは追加します。

複数の関数を実行してそれらを呼び出し、レイヤーを「偽造」することができます。


これは完璧です。
Nadir 2016年

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経由でアクセスできますか?
Garavani

0

Qがライブラリを使用したくないことを理解していますが、Google検索から来た他の人に提供します。@EricRowellは優れたプラグインについて言及しましたが、試してみることができる別のプラグインhtml2canvasもあります。

私たちのケースではz-index、「製品ビルダー」ウィジェットとして、レイヤー化された透明なPNGを使用しています。Html2canvasは、画像をプッシュしたり、複雑さ、回避策、および「応答しない」キャンバス自体を使用したりせずに、スタックを煮詰めるために見事に機能しました。バニラキャンバス+ JSでは、これをスムーズに行うことはできませんでした。

最初z-indexに絶対divで使用して、相対的に配置されたラッパー内に階層化コンテンツを生成します。次に、ラッパーをhtml2canvasにパイプして、レンダリングされたキャンバスを取得します。これはそのままにするか、クライアントが保存できるように画像として出力します。


より重い画像がある場合、HTMLをキャンバスに変換するのにしばらく時間がかかります。レンダリングに長い時間がかかったからといって、これから離れる必要がありました。
Vilius 2017

@Viliusええ、重い画像や大きな画像をお見逃しなく。4レイヤー以下の300K以下の画像を使用しようとしました。そうしないと、リソースに感染したクライアントは、最終的な堆肥化された画像をダウンロードするときにやけどを感じるでしょう。好奇心が強い、あなたはその短縮された時間に何を移しましたか?
dhaupin 2017年

そもそも、html要素を使用して何かを最初に描画することで大きな間違いを犯しました。APIがx、y、width、heightを返したため、html要素を使用する代わりにjscanavsに移動して画像を描画しました。回転に関する問題がいくつかありました(開始点は少し厄介で予測不可能でした)と、特定の寸法を使用して画像をそれに適用しましたが、最終的にはすべて解決されました。また、画像処理アプリケーションが大量のリソースを消費していることもわかりました。そのため、これも使用しなくなりました。
Vilius 2017年

0

しかし、レイヤー02はレイヤー01のすべての図面をカバーします。これを使用して、両方のレイヤーの図面を示しました。(background-color:transparent;)をスタイルで使用します。

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