Przewodnik po canvas:Kompozycje
z Mozilla Developer Center, polskiego centrum programistów Mozilli.
Spis treści |
UWAGA: Tłumaczenie tej strony nie zostało zakończone.
Może być ona niekompletna lub wymagać korekty.
Chcesz pomóc? | Dokończ tłumaczenie | Sprawdź ortografię | Więcej takich stron...
We wszystkich wcześniejszych przykładach kształty były rysowane zawsze jeden na górze innego. This is more than adequate for most situations. This for instance limits us in what order composit shapes are built up. We can however change this behaviour by setting the globalCompositeOperation property.
[edytuj] globalCompositeOperation
Nie tylko możemy rysować nowe kształty za istniejącymi, lecz możemy także je użyć do maskowania niektórych obszarów, czyszczenia obszarów canvas (nie ograniczonych do prostokątnych kształtów, jak czyni metoda clearRect i więcej.
globalCompositeOperation = type
Własność type jest łańcuchem znaków reprezentującym jedną z dwunastu złożonych operacji. Każdy z dostępnych typów jest opisany poniżej.
Uwaga: We wszystkich przykładach poniżej niebieski kwadrat jest rysowany jako pierwszy i odnosi się do 'istniejącej zawartości canvas'. Czerwony okrąg jest rysowany jako drugi i jest określony jako 'nowy kształt'.
|
source-over (domyślna wartość) |
destination-over | ||
|
source-in |
destination-in | ||
|
source-out |
destination-out | ||
|
source-atop |
destination-atop | ||
|
lighter |
darker | ||
|
xor |
copy |
Uwaga: Aktualnie ustawienia copy i darker nie robią nic w przeglądarkach opartych na Gecko 1.8 i nowszych(Firefox 1.5 itd.).
[edytuj] Obcinanie ścieżek
A clipping path is like a normal canvas shape but it acts as a mask to hide unwanted parts of shapes. This is visualized in the image on the right. The red star shape is our clipping path. Everything that's falls outside of this path won't get drawn on the canvas.If we compare clipping paths to the globalCompositeOperation property we've seen above; settings that achieve more or less the same effect are source-in and source-atop. The most important differences between the two are that clipping paths are never actually drawn to the canvas and the clipping path is never affected by adding new shapes. This makes clipping paths ideal for drawing multiple shapes in a restricted area.
W rozdziale o Rysowaniu kształtów I only mentioned the stroke and fill methods. There's however a third method we can use with paths and that's clip.
clip()
We use the clip method to create a new clipping path. By default the canvas element has a clipping path that's the exact same size as the canvas itself (ie no clipping occurs).
[edytuj] Przykład clip
In this example I'll be using a circular clipping path to restrict the drawing of a set of random stars to a particular region.
In the first few lines of code I draw a black rectangle the size of the canvas as a backdrop and translate the origin to the center. Below this I create the circular clipping path by drawing an arc. By calling the clip method the clipping path is created. Clipping paths are also part of the canvas save state. If we wanted to keep the original clipping path we could have saved the canvas state before creating the new one.
After creating the clipping path everything that's drawn afterwards should only appear inside the path. You can see this clearly at the radial gradient that's drawn next. After this a set of 50 randomly positioned and scaled stars is drawn (I'm using a custom function for this). Again the stars only appear inside the defined clipping path.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.fillRect(0,0,150,150);
ctx.translate(75,75);
// Create a circular clipping path
ctx.beginPath();
ctx.arc(0,0,60,0,Math.PI*2,true);
ctx.clip();
// draw background
var lingrad = ctx.createLinearGradient(0,-75,0,75);
lingrad.addColorStop(0, '#232256');
lingrad.addColorStop(1, '#143778');
ctx.fillStyle = lingrad;
ctx.fillRect(-75,-75,150,150);
// draw stars
for (j=1;j<50;j++){
ctx.save();
ctx.fillStyle = '#fff';
ctx.translate(75-Math.floor(Math.random()*150),
75-Math.floor(Math.random()*150));
drawStar(ctx,Math.floor(Math.random()*4)+2);
ctx.restore();
}
}
function drawStar(ctx,r){
ctx.save();
ctx.beginPath()
ctx.moveTo(r,0);
for (i=0;i<9;i++){
ctx.rotate(Math.PI/5);
if(i%2 == 0) {
ctx.lineTo((r/0.525731)*0.200811,0);
} else {
ctx.lineTo(r,0);
}
}
ctx.closePath();
ctx.fill();
ctx.restore();
}













