Rysowanie obrazków na elemencie canvas
Grafika rastrowa ma się dobrze
- Szefie, da mi pan urlop? Bo teściowa przyjeżdża!
A szef na to:
- Nie ma mowy!
- Wiedziałem, że z szefa dobry człowiek!
Przygotowanie obrazków
Zanim narysujemy jakiś obrazek na płótnie, musimy go pobrać. Najłatwiejszym rozwiązaniem jest pobranie tego obrazka z elementu imgIstnieje także możliwość kopiowania bloków pomiędzy płótnami, a także dynamiczne pobieranie obrazków z serwera na żądanie. Techniki te nie będą dzisiaj poruszane. i tak też zrobię. W przykładzie założyłem, że w katalogu ze stroną HTML jest katalog Images, w którym znajdzie się przedstawony w dalszej części obrazek wzorcowy.
Program demonstracyjny będzie reprezentował czystą pięciolinię z wielokrotnie powieloną ćwierćnutą. Powiem więcej - ćwierćnuty będą odpowiednio poukładane! Przejdźmy do tego, co chcemy uzyskać.
Prezentacja efektu - pięciolinia z ćwierćnutami
Popatrzmy najpierw na efekt. Potem pokażę, w jaki sposób można go uzyskać:
To powyżej to nuta wzorcowa, zasób. Nuta nie musi być widoczna, ale uznałem, że wypadałoby ją pokazać. Korzystając z tego jednego zasobu można przekształcić element canvas na poniższy twór:
Kod jest na tyle prosty, że nie powinien sprawiać problemów.
Pełny listing
Popatrzmy, jak to wszystko zostało zrobione:
<head>
<title>Rysowanie obrazków na elemencie canvas</title>
</head>
<body>
<figure>
<img id="quarter" src="/Images/QuarterNote.png" alt="Ćwierćnuta" />
<figcaption>Rysunek ćwierćnuty powielany na elemencie canvas.</figcaption>
</figure>
<figure>
<canvas id="stave" width="500" height="200"></canvas>
<figcaption>Pięciolinia z powielonymi ćwierćnutami reprezentującymi dźwięki c<sup>1</sup> - g<sup>2</sup>.</figcaption>
</figure>
<script>
function Canvas(id) {
var canvas = document.getElementById(id);
this.Context = canvas.getContext("2d");
this.Quarter = document.getElementById("quarter");
this.Width = canvas.width;
this.Height = canvas.height;
}
Canvas.prototype.DrawQuarter = function (x, y) {
// środek nuty ma współrzędne [12,50]
this.Context.drawImage(this.Quarter, x - 12, y - 50);
}
Canvas.prototype.DrawStave = function () {
for (var i = 0; i < 5; i++) {
this.Context.beginPath();
this.Context.moveTo(0, 135 - i * 15);
this.Context.lineTo(this.Width, 135 - i * 15);
this.Context.stroke();
}
}
window.addEventListener("load", function () {
var canvas = new Canvas("stave");
// narysuj ćwierćnuty od c1 do g2
for (var i = 0; i < 12; i++) {
canvas.DrawQuarter(30 + i * 40, 150 - 15 * i / 2);
}
// narysuj pięciolinię
canvas.DrawStave();
}, false);
</script>
</body>
</html>
Samo rysowanie obrazków nie jest szczególnie trudne - sprowadza się do pobrania kontekstu (czynność wymagana przed wykonaniem jakiejkolwiek operacji graficznej na płótnie) i wywołania funkcji drawImage:
Przeciążenie | Parametry |
---|---|
drawImage | (img,x,y) |
drawImage | (img,x,y,width,height) |
drawImage | (img,sx,sy,swidth,sheight,x,y,width,height) |
Poszczególne parametry oznaczają:
Parametr | Opis |
---|---|
img | Obiekt obrazka, innego płótna lub wideo. W przykładzie użyty został obiekt znacznika img. |
x | Współrzędna x na płótnie docelowym, w której znajdzie się lewy brzeg obrazka źródłowego. |
y | Współrzędna y na płótnie docelowym, w której znajdzie się górna krawędź obrazka źródłowego. |
width | Parametr opcjonalny. Określa pożądaną szerokość rysowanego obrazka. Jeżeli jest różny od wymiaru źródłowego, obrazek zostanie przeskalowany. |
height | Parametr opcjonalny. Określa pożądaną wysokość rysowanego obrazka. Jeżeli jest różny od wymiaru źródłowego, obrazek zostanie przeskalowany. |
sx | Parametr opcjonalny. Współrzędna x, która definiuje lewą krawędź przycinania obrazka źródłowego. |
sy | Parametr opcjonalny. Współrzędna y, która definiuje górną krawędź przycinania obrazka źródłowego. |
swidth | Parametr opcjonalny. Szerokość prostokąta definiującego krawędź przycinania obrazka źródłowego. |
sheight | Parametr opcjonalny. Wysokość prostokąta definiującego krawędź przycinania obrazka źródłowego. |
Garść wyjaśnień należy się samej logice. Po załadowaniu się strony rysowane są ćwierćnuty. Pierwsza w odstępie 30 pikseli od lewej, każda następna co 40 pikseli (40 * i). Wysokość dźwięku również zwiększa się wraz z indeksem i. Linie pięciolinii będą rysowane co 15 pikseli, więc sama nuta musi się tam zmieścić w dwóch położeniach (150 - 15 * i / 2). Wartość 150 oznacza bazowe położenie dźwięku c1, a same nuty będą coraz wyżej. Trochę magicznych liczb znajduje się w funkcji rysującej: DrawQuarter. Trzeba wiedzieć, że położenie nuty wskazuje środek kółeczka. Obrazek jest natomiast rysowany względem lewego górnego narożnika obrazka źródłowego. Wartości 12 i 50 oznaczają zatem odpowiednio: 12 - odległość środka kółeczka od lewej krawędzi, 15 - odległość środka kółeczka od górnej krawędzi. Sama pięciolinia, rysowana w funkcji DrawStave również korzysta z pewnych ustaleń. Muzycznie rzecz ujmując dźwięk c1 znajduje się na pierwszej dorysowanej linii z dołu. Pierwsza linia będzie zatem 15 pikseli wyżej, czyli na poziomie 135 pikseli od góry. Przypomnę, że linie miały być co 15 pikseli.
Podsumowanie
Znawcy muzyki są zapewne zniesmaczeni pewnym drobnym błędem: nuty od trzeciej linii wzwyż powinno się rysować z ogonkiem skierowanym w dółW praktyce zależy to od kierunku sąsiadujących nut oraz od relacji (uśrednienia) pozycji wszystkich nut, z którymi rozważana nuta jest zgrupowana. oraz braku dodatkowej linii przy dźwięku c1. Pierwszy problem można rozwiązać wykonując proste przekształcenie (obrót o 180 stopni względem środka kółeczka), drugi - rysując jedną linię w miejscu nuty. To zadanie pozostawiam do samodzielnego rozwiązania.
Kategoria:HTMLJavaScriptCanvas
Brak komentarzy - bądź pierwszy