Spis treści:

Kategoria:HTMLJavaScriptCanvas


Rysowanie obrazków na elemencie canvas

Grafika rastrowa ma się dobrze

Kowalski pyta się szefa:
- 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!
W kilku wcześniejszych wpisach zajmowałem się elementem canvas od strony prostych operacji graficznych. Na pierwszą linię wysunięte były tam proste obiekty graficzne - linie, elipsy, prostokąty. Wiadomo nie od dziś, że takie obiekty nie są szczególnie atrakcyjne. Mało który programista lub grafik odważy się skonstruować aplikację (zwłaszcza grę) korzystający tylko z prostych figur geometrycznych. Może i dają się one skalować bezstratnie, ale jak za ich pomocą przedstawić twarze i krajobrazy? Obrazki z rozszerzeniami JPG, PNG, BMP - to wszystko są grafiki rastrowe. Inaczej mówiąc, reprezentacje obrazu za pomocą pionowo-poziomej siatki odpowiednio kolorowanych pikseli. Takimi tablicami pikseli zajmę się dziś.

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ć:

Ćwierćnuta
Rysunek ćwierćnuty powielany na elemencie canvas.

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:

Pięciolinia z powielonymi ćwierćnutami reprezentującymi dźwięki c1 - g2.

Kod jest na tyle prosty, że nie powinien sprawiać problemów.

Pełny listing

Popatrzmy, jak to wszystko zostało zrobione:

<html>
<head>
    <title>Rysowanie obrazków na elemencie canvas</title>
</head>
<body>
<figure>
    <img id="quartersrc="/Images/QuarterNote.pngalt="Ćwierćnuta/>
    <figcaption>Rysunek ćwierćnuty powielany na elemencie canvas.</figcaption>
</figure>
    
<figure>
    <canvas id="stavewidth="500height="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ążenieParametry
drawImage(img,x,y)
drawImage(img,x,y,width,height)
drawImage(img,sx,sy,swidth,sheight,x,y,width,height)

Poszczególne parametry oznaczają:

ParametrOpis
imgObiekt obrazka, innego płótna lub wideo. W przykładzie użyty został obiekt znacznika img.
xWspółrzędna x na płótnie docelowym, w której znajdzie się lewy brzeg obrazka źródłowego.
yWspółrzędna y na płótnie docelowym, w której znajdzie się górna krawędź obrazka źródłowego.
widthParametr opcjonalny. Określa pożądaną szerokość rysowanego obrazka. Jeżeli jest różny od wymiaru źródłowego, obrazek zostanie przeskalowany.
heightParametr opcjonalny. Określa pożądaną wysokość rysowanego obrazka. Jeżeli jest różny od wymiaru źródłowego, obrazek zostanie przeskalowany.
sxParametr opcjonalny. Współrzędna x, która definiuje lewą krawędź przycinania obrazka źródłowego.
syParametr opcjonalny. Współrzędna y, która definiuje górną krawędź przycinania obrazka źródłowego.
swidthParametr opcjonalny. Szerokość prostokąta definiującego krawędź przycinania obrazka źródłowego.
sheightParametr 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

, 2013-12-20

Brak komentarzy - bądź pierwszy

Dodaj komentarz
Wyślij
Ostatnie komentarze
chcę dodać kolumnę, która będzie połączeniem dwóch innych istniejących już kolumn, jak powinien wyglądać scrypt?
Przydałyby się jeszcze 2 rzeczy do cz. 3 i byłoby superanckie.
1. Na starcie sortuje wg jakiejś kolumny i tam jest już strzałeczka. Widok takiej strzałeczki daje znać użytkownikowi, że taką tabele można sortować, a na razie pojawia się ona tylko po kliknięciu.
2. Uwzględnienie polskich znaków, bo np. przy sortowaniu Nazwisk i Imion jest to bardzo uciążliwe.
Ogólnie bardzo fajnie i prosto.
PS. Jest ten artykuł z jQuery już dostępny.
bardo ciekawe , można dzięki takim wpisom dostrzec wędkę..
Bardzo dziękuję za jasne tłumaczenie z dobrze dobranym przykładem!