web-dev-qa-db-ja.com

HTML5 CanvasセットZ-Index

HTML5キャンバスで描画されたオブジェクトのz-indexを設定することは可能ですか?

1つのオブジェクトが「プレーヤー」の前にあり、別のオブジェクトが「プレーヤー」の後ろにあるように取得しようとしています。

37
Eli Stone

はい。はいの種類。合成を使用して既存のピクセルを「後ろに描画」できます。

ctx.globalCompositeOperation='destination-over';

以下に例とデモを示します。

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

var cx=100;

drawCircle()
cx+=20;

ctx.globalCompositeOperation='destination-over';

$("#test").click(function(){
  drawCircle();
  cx+=20;
});

function drawCircle(){
  ctx.beginPath();
  ctx.arc(cx,150,20,0,Math.PI*2);
  ctx.closePath();
  ctx.fillStyle=randomColor();
  ctx.fill();
}

function randomColor(){ 
  return('#'+Math.floor(Math.random()*16777215).toString(16));
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id="test">Draw new circle behind.</button><br>
<canvas id="canvas" width=300 height=300></canvas>
51
markE

背後にあるものを最初に描画し、それから他のオブジェクトを描画します。

ヒットテストを行うには、表示リストを逆方向に繰り返して各オブジェクトをテストする必要があります。これは、オブジェクトの境界を本当によく知っている場合に機能します。

または、描画されたすべてのオブジェクトに固有の色を使用して、同じオブジェクトを別のインメモリキャンバスに描画するなど、いくつかの標準的なグラフィックトリックを試してみることもできます。きちんとした;-)

5
Joe Parry

または、描画するオブジェクトを含む配列を使用してから、各子のzIndexプロパティを使用してこの配列を並べ替えることもできます。次に、その配列を反復して描画します。

var canvas = document.querySelector('#game-canvas');
var ctx = canvas.getContext('2d');

// Define our shape "class".
var Shape = function (x, y, z, width, height) {
  this.x = x;
  this.y = y;
  this.zIndex = z;
  this.width = width;
  this.height = height;
};
// Define the shape draw function.
Shape.prototype.draw = function () {
  ctx.fillStyle = 'Lime';
  ctx.fillRect(this.x, this.y, this.width, this.height);
};

// let's store the objects to be drawn.
var objects = [
  new Shape(10, 10, 0, 30, 30), // should be drawn first.
  new Shape(50, 10, 2, 30, 30), // should be drawn third.
  new Shape(90, 10, 1, 30, 30)  // should be drawn second.
];

// For performance reasons, we will first map to a temp array, sort and map the temp array to the objects array.
var map = objects.map(function (el, index) {
  return { index : index, value : el.zIndex };
});

// Now we need to sort the array by z index.
map.sort(function (a, b) {
  return a. value - b.value;
});

// We finaly rebuilt our sorted objects array.
var objectsSorted = map.map(function (el) {
  return objects[el.index];
});

// Now that objects are sorted, we can iterate to draw them.
for (var i = 0; i < objectsSorted.length; i++) {
  objectsSorted[i].draw();
}

// Enjoy !

私はそのコードをテストせずに携帯電話で書いたので、タイプミスがあるかもしれないことに注意してください。

4
SkyzohKey

私が見つけた解決策は、2つのキャンバスを使用することです(ちらつき、ちらつきを取り除きます!)。 (以上)

あなたが何らかの種類のゲームを作成していると仮定します(プレイヤーについて言及しているため)。それを例として使用します。

ウィンドウの動作からページを取得し、最初にキャンバスを背景として配置し、その上に別のキャンバスをプレーヤーキャンバスとして配置できます。プレーヤーのキャンバスを「ダーティ」または変更されたときはいつでも変更済みとしてマークし、必要な場合にのみ変更されたレイヤーを再描画できます。つまり、プレーヤーが移動するかアクションを実行した場合にのみ、2番目のキャンバスを更新します。

この方法はさらに進めることができ、プレーヤーの統計が変更されたときにのみ変更されるゲームプレイの統計を含むHUDの3番目のキャンバスを追加できます。

Htmlは次のようになります。

<canvas id="background-canvas" height="500" width="1000" style="border:1px solid #000000;"></canvas>
<canvas id="player-canvas" height="500" width="1000" style="border:1px solid #000000;"></canvas>
<canvas id="hud-canvas" height="500" width="1000" style="border:1px solid #000000;"></canvas>
4
nicholeous

申し訳ありませんが、いや、canvas要素にはz-indexがあり、その上に描画されたものはすべてそのレイヤーになります。

キャンバス上のさまざまなものを参照している場合は、はい、描画されたものはすべて、前にあったものの上に描画されます。

1
Andrew