2012-02-06 13 views
28

Czy można ustawić indeks Z rysowane obiektu w kanwie HTML5?Zestaw obrazów HTML5 z-index

Próbuję dostać to więc jeden obiekt może być infront z „gracz”, a inny obiekt znajduje się za „odtwarzacz”

+0

Jest to absolutnie możliwe, ale musisz samodzielnie zarządzać szeregiem obiektów, które chcesz narysować. –

+0

Istnieje kilka rozwiązań: użycie wielu elementów canvas lub wybór kolejności, w której prawidłowo rysujesz obiekty na płótnie. Zobacz następujące pytania: * [implementacja-warstwy-w-html5-canvas] (http://stackoverflow.com/questions/4422907/implementing-layers-in-html5-canvas) * [html5-canvas-element-multiple- warstwy] (http://stackoverflow.com/questions/3008635/html5-canvas-element-multiple-layers) – styfle

Odpowiedz

36

Yes..kind YES. Możesz użyć compositing, aby "zaciągnąć" istniejące piksele.

ctx.globalCompositeOperation='destination-over'; 

Oto przykład i Demo:

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>

+0

dlaczego mówisz "rodzaj"? dla mnie wygląda to jak jedyne prawdziwe rozwiązanie tutaj. – lordvlad

+3

Mówię "rodzaj", ponieważ kompozycja nie jest tak elastyczna jak refaktoryzacja rysunków, aby pojawiły się poprawnie z-warstwami w pierwszej kolejności. Kompozycja obejmuje tylko 2 "warstwy". Jedna warstwa to istniejące piksele na płótnie, a druga to nowo rysowane piksele. Refaktoryzacja w celu narysowania odpowiednio warstwowych rysunków daje tyle warstw, ile potrzeba. – markE

+1

stackoverflow jest świetny! – Li3ro

1

Niestety, ale nope, element canvas będzie miał z-index i wszystko na niej narysowane będzie na tej warstwie.

Jeśli mówisz o różnych rzeczach na płótnie, to tak, wszystko, co jest rysowane, zostanie narysowane na tym, co było wcześniej.

3

Po prostu narysuj rzeczy za sobą, a następnie przedmiot, a następnie inne obiekty.

Aby wykonać test trafienia, konieczne może być wykonanie iteracji wstecznej na liście wyświetlania, testowanie każdego obiektu. To zadziała, jeśli znasz dobrze granice obiektów.

A może warto wypróbować niektóre standardowe sztuczki graficzne, takie jak rysowanie tych samych obiektów na innym płótnie w pamięci, z unikalnymi kolorami dla każdego narysowanego obiektu: aby przetestować to, po prostu sprawdź kolor piksela na płótnie znajdującym się w pamięci. Zgrabny ;-)

4

Rozwiązaniem, które znalazłem dla mnie działa (i pozbyłem się migotania, hurra!) Jest użycie dwóch płócien. (lub więcej)

Zakładam, że robisz coś w rodzaju gry (ponieważ wspomniałeś o graczu) i używasz tego jako przykładu.

Możesz wziąć stronę od sposobu, w jaki działa okno, i najpierw umieść płótno jako tło z innym płótnem jako płótnem gracza. Możesz oznaczyć płótno gracza jako "brudne" lub zmienić po każdej zmianie i przerysować zmienioną warstwę tylko wtedy, gdy jest taka potrzeba. Oznacza to, że aktualizujesz tylko drugie płótno, gdy gracz porusza się lub wykonuje akcję.

Ta metoda może zostać zastosowana jeszcze dalej i możesz dodać trzecie płótno do HUD ze statystykami rozgrywki, które zmieniają się tylko wtedy, gdy zmieni się statystyki gracza.

HTML może wyglądać tak:

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

Lub może po prostu użyć tablicę zawierającą swoich obiektów, jakie należy wyciągnąć następnie sortować tej tablicy przy użyciu właściwość zIndex każde dziecko. Następnie jist iteruj tę tablicę i narysuj.

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 - b; 
}); 

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

Zauważ, że nie zrobił przetestowane ten kod i napisał je na mój telefon, więc nie może być literówki, ale które powinny pozwolenia, aby zrozumieć zasadę, mam nadzieję.

+0

Myślę, że 'map.sort (function (a, b) {return a - b;}); 'powinno być' map.sort (function (a, b) {return a.value - b.value;}); ', nie sądzę, że możesz po prostu minus dwa obiekty. – dud3

Powiązane problemy