Visit Mozilla.org

Przewodnik po canvas:Zastosowanie obrazków

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

Jedną z fajniejszych cech canvas jest możliwość użycia obrazów. Może być użyta do tworzenia dynamicznych kompozycji fotografii lub do stworzenia tła wykresu itp.. To jest też obecnie jedyny sposób aby dodać tekst(Specyfikacja nie zawiera żadnych funkcji do rysowania tekstu). Zewnętrzne obrazy mogą być użyte jeśli są w jednym z formatów obsługiwanych przez silnik Gecko (są to formaty PNG, GIF i JPEG). Inne elementy canvas znajdujące się na tej samej stronie mogą być użyte jako źródło obrazu.

[edytuj] Importowanie obrazków

Import obrazów odbywa się w dwóch podstawowych krokach:

  • Po pierwsze potrzebujemy odniesienia JavaScript do obiektu obrazu lub innego elementu canvas jako źródła. Nie jest możliwe użycie obrazów poprzez umieszczenie adresu URL do nich.
  • Po drugie rysujemy obraz na płótnie(canvas) używając funkcji drawImage.

Przyjrzyjmy się pierwszemu krokowi. Mamy dostępny wybór czterech podstawowych opcji:

[edytuj] Zastosowanie obrazków, które są na tej samej stronie

Możemy uzyskać dostęp do wszystkich obrazów na stronie używając kolekcji document.images, metody document.getElementsByTagName lub jeżeli wiemy jaki jest atrybut ID, metody document.getElementById.

[edytuj] Zastosowanie innych elementów canvas

Tak jak w przypadku normalnych obrazów uzyskujemy dostęp do innych elementów canvas używając jednej z dwóch metod document.getElementsByTagName lub metody document.getElementById. Upewnijcie się czy macie coś narysowane w źródłowym elemencie canvas przed użyciem tego w waszym docelowym elemencie canvas.

Jednym z wielu bardziej praktyczniejszych zastosowań mogłoby być użycie drugiego elementu canvas jako podglądu miniatur z innych większych elementów canvas.

[edytuj] Tworzenie obrazka od zera

Jeszcze jedną opcją jest utworzenie nowego obiektu Image w naszym skrypcie. Główną wadą tego podejścia jest to,że jeżeli nie chcemy zatrzymywać naszego skryptu w połowie z powodu, że potrzebuje on czekać aż obrazek zostanie zaladowany, potrzebujemy jakiejś formy preloadingu obrazu.

Gruntownie do utworzenia nowego obrazka potrzebujemy wykonać to:

var img = new Image();   //  Tworzy nowy obiekt Image 
img.src = 'myImage.png'; // Ustawia ścieżkę źródła

Kiedy ten skrypt zostanie wykonany, obraz zaczyna się wczytywać. Jeżeli wczytywanie nie jest ukończone kiedy instrukcja drawImage zostanie wykonana, skrypt zatrzyma się dopóki wczytywanie obrazu nie zostanie zakończone. Jeżeli nie jest nam to na coś potrzebne, użyjmy uchwytu zdarzenia onload :

var img = new Image();   // Tworzy nowy obiekt Image 
img.src = 'myImage.png'; // Ustawia ścieżkę źródła
img.onload = function(){
  // Tutaj wykonuje instrukcję drawImage 
}

Jeżeli stosujemy tylko jeden zewnętrzny obrazek to może być dobrym podejściem, jednakże skoro musimy śledzić więcej niż jeden obraz potrzebujemy uciec się do czegoś sprytniejszego. To jest poza zakresem tego tutoriala, aby przyjrzeć się metodom preloadingu obrazu możecie przejrzeć JavaScript Image Preloader dla uzyskania kompleksowego rozwiązania.

[edytuj] Zagnieżdżanie obrazków przez data: url

Innym możliwym sposobem na umieszczanie obrazów jest zastosowanie data: url. Dane url pozwalają na zdefiniowanie kompletnego obrazu jako zakodowany (Base64) łańcuch znaków bezpośrednio w kodzie. Jedną z zalet danych urls jest to, iż wynikowy obraz jest dostępny natychmiast bez kolejnego odwoływania się do serwera. (Inną zaletą jest to iż można wtedy zawrzeć w jednym pliku wszystkie wasze kody CSS, Javascript, HTML,oraz obrazy, czyniąc bardziej przenośnymi do innych lokalizacji). Wadą tej metody jest to iż obraz nie jest ukryty, i dla większych obrazów zakodowany url może stawać się dość długi:

var img_src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';

[edytuj] drawImage

Jeżeli mamy odsyłacz do naszego źródłowego obiektu obrazu możemy użyć metody drawImage do wyświetlenia go w canvas. Jak zobaczymy później metoda drawImage jest przeciążona i posiada trzy różne warianty. Wśród nich najbardziej podstawową forma jest poniższa.

drawImage(image, x, y)

Gdzie: image jest odniesieniem do naszego obrazka lub obiektu canvas. x i y są współrzędnymi miejsca w canvas, gdzie nasz obrazek powinien zostać umieszczony.

[edytuj] Przykład 1: drawImage

W następujacym przykładzie chcemy użyć zewnętrznego obrazu jako tła małej linii graficznej. Używanie teł może uczynić nasz skrypt znacznie mniejszym ponieważ nie musimy rysować skomplikowanego tła. Używając tylko jednego obrazu, tutaj użyjemy także uchwytu zdarzenia onload obiektu obrazu do wykonania instrukcji rysowania. Metoda drawImage umieszcza tło na współrzędnej (0,0) która jest lewym górnym rogiem elementu canvas.

Zobacz ten przykład

  function draw() {
    var ctx = document.getElementById('canvas').getContext('2d');
    var img = new Image();
    img.src = 'backdrop.png';
    img.onload = function(){
      ctx.drawImage(img,0,0);
      ctx.beginPath();
      ctx.moveTo(30,96);
      ctx.lineTo(70,66);
      ctx.lineTo(103,76);
      ctx.lineTo(170,15);
      ctx.stroke();
    }
  }

[edytuj] Skalowanie

Drugi wariant metody drawImage dodaje dwa nowe parametry i pozwala nam na umieszczenie skalowanych obrazków w canvas.

drawImage(image, x, y, width, height)

Gdzie: width i height jest rozmiarem obrazka w odpowiednim położeniu w canvas.

[edytuj] Przykład 2: drawImage

W tym przykładzie zastosujemy powtarzany kilkakrotnie obraz w elemencie canvas jako tapetę. Dokonamy tego w prosty sposób poprzez zapętlenie i umieszczenie przeskalowanych obrazków na różnych pozycjach. W kodzie poniżej pierwsza pętla for poprzez wiersze, a druga pętla for poprzez kolumny. Obrazek jest skalowany w jednej trzeciej jego oryginalnego rozmiaru, który wynosi 50x38 pikseli. Zobaczymy jak to zostało osiągnięte, poprzez utworzenie wzorca użytkownika, w dalszej części tego przewodnika.

Uwaga: Obrazy mogą stać się niewyraźne lub zbyt rozciągnięte, kiedy zbytnio je poddamy skalowaniu. Skalowanie najprawdopodobniej nie wypadnie najlepiej jeżeli dodalibyśmy tekst który musi pozostać czytelny.

Zobacz ten przykład

Źródło obrazka
Źródło obrazka
  function draw() {
    var ctx = document.getElementById('canvas').getContext('2d');
    var img = new Image();
    img.src = 'images/rhino.jpg';
    img.onload = function(){
      for (i=0;i<4;i++){
        for (j=0;j<3;j++){
          ctx.drawImage(img,j*50,i*38,50,38);
        }
      }
    }
  }

[edytuj] Krojenie

Trzeci i zarazem ostatni wariant metody drawImage posiada osiem nowych parametrów. Możemy zastosować tą metodę do wykrojenia części źródłowego obrazka i narysowania jej w elemencie canvas.

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

Pierwszy parametr image, dokładnie jak w innych wariantach, jest jednym z dwóch odniesień do obiektu obrazu lub innego elementu canvas. Dla ośmiu innych parametrów najlepiej spojrzeć na obraz po prawej. Pierwsze cztery parametry określają umiejscowienie i rozmiar krojonego źródłowego obrazu. Ostatnie cztery parametry określają umiejscowienie i rozmiar w docelowym elemencie canvas.

Krojenie może być użytecznym narzędziem kiedy potrzebujemy tworzyć kompozycje. Możecie mieć wszystkie elementy w pojedynczym pliku obrazu i użyć tej metody do składania kompletnego rysunku. Dla przykładu, jeżeli potrzebowaliśmy utworzyć wykres moglibyśmy obraz PNG zawierający cały potrzebny tekst w jednym pliku i zależnie od danych mógłby zmieniać skalę wykresu bez większych trudności. Jeszcze jedną zaletą jest to że nie musimy załadowywać każdego obrazu osobno.

[edytuj] Przykład 3: drawImage

W tym przykładzie użyjemy tego samego nosorożca jakiego widzieliśmy powyżej, lecz tym razem wykroimy jego głowę i połączymy ze zdjęciem ramki. Obraz zdjęcia ramki zawiera efekt cienia który jest zapisany jako 24-bitowy obraz PNG. Ponieważ 24-bitowe obrazyt PNG zawierają pełny 8-bitowy kanał alpha, w przeciwieństwie do formatów GIF i 8-bitowego PNG. Możemy umieszczać go na każdym tle i nie musimy się martwić o matowe tło.

Weźmy inne podejście do wczytywania obrazów niż w przykładzie powyżej. Po prostu umieścimy obrazy bezpośrednio w dokumencie HTML i użyjemy reguły CSS do ukrycia ich z widoku(display:none). Przydzielając obu obrazom atrybut id tworzymy je łatwiejszymi do wybrania. Skrypt staje się bardziej prosty. Najpierw rysujemy wykrojony i przeskalowany obraz w elemencie canvas (pierwsza instrukcja drawImage), a następnie umieszczamy ramkę na wierzchu (druga instrukcja drawImage).

Zobacz ten przykład

Źródło obrazka
Źródło obrazka
function draw() {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');

  // Rysuje wykrojony element
  ctx.drawImage(document.getElementById('source'),
                33,71,104,124,21,20,87,104);

  // Rysuje ramkę
  ctx.drawImage(document.getElementById('frame'),0,0);
}

[edytuj] Przykład galerii

W ostatnim przykładzie tego rozdziału zrobimy galerię sztuki. Galeria składa się z tabeli zawierającej kilka obrazków. Gdy strona jest wczytywana, dla każdego obrazu na stronie zostanie wstawiony element canvas, a wokół niego zostanie narysowana ramka.

W naszym przypadku, wszystkie obrazy mają ustaloną szerokość i wysokość, zatem wykonujemy ramkę, która jest narysowana wokół. Możemy tak zmodyfikować skrypt, że używa on szerokości obrazu i wysokości by sprawić, że ramka jest w sam raz wokół niego.

Kod poniżej powinien być jasny. Robimy pętlę tworząc tablicę obrazów i stosownie dodajemy nowe elementy canvas. Prawdopodobnie jedyną rzeczą wartą uwagi w tym przykładzie (nie trzeba być obeznanym z DOM) jest zastosowana metoda insertBefore. insertBefore jest metodą wierzchołka (komórka tabeli) elementu rodzica obrazka (obrazka), przed którym chcemy wstawić nasz nowy węzeł (element canvas).

Zobacz ten przykład

function draw() {

  // Pętla przez wszystkie obrazki
  for (i=0;i<document.images.length;i++){

    // Nie dodawaj elementu canvas dla ramki obrazu
    if (document.images[i].getAttribute('id')!='frame'){

      // Utworzenie elementu canvas
      canvas = document.createElement('CANVAS');
      canvas.setAttribute('width',132);
      canvas.setAttribute('height',150);

      // Umieszczenie przed obrazem
      document.images[i].parentNode.insertBefore(canvas,document.images[i]);

      ctx = canvas.getContext('2d');

      // Rysowanie obrazu w elemencie canvas
      ctx.drawImage(document.images[i],15,20);

      // Dodanie ramki
      ctx.drawImage(document.getElementById('frame'),0,0);
    }
  }
}