Spis treści:

Kategoria:HTMLJavaScriptCanvas


Prosty wykres w HTML5

Drobne oszczędności

-Proszę wybaczyć panie kierowniku, ale w tym miesiącu nie dostałem premii.
-Wybaczam panu
Lekkie i proste rozwiązania mają to do siebie, że nie zawsze od razu przypadają do gustu. Zwykle lepsze wrażenie sprawia wielki, wszystko mający, kolorowy komponent lub wielki kolorowy obrazek, ilustracja. Te skomplikowane elementy strony zwykle są duże, czasami wymagają zwielokrotnienia. Wiele wykresów w postaci obrazków to wiele żądań HTTP. Nie trzeba chyba przypominać, że to również wpływa na wydajność serwera WWW. Rzeczy wydają się błahe, dopóki na naszą stronę nie przywędruje kilkadziesiąt, kilkaset tysięcy użytkowników - w takim przypadku nawet niewielkie ograniczenie transferu i liczby żądań może być zauważalne. Z innej strony, jeżeli mamy wykupiony hosting z ograniczonym miesięcznym transferem i nagle nam tego transferu braknie...

Ktoś może powiedzieć, że można kupić lepszy transfer, lepszy serwer. Z jednej strony to prawda, ale znajdą się też argumenty przeciwne. Po pierwsze, nie mamy wpływu na przepustowość łącza czytelników naszych stron, a po drugie - ile zaoszczędziłyby wielkie firmy informatyczne, gdyby zmnijejszyć rozmiar lub wydajność ich stron choćby o 1%? To są grube miliony.

Jest jeszcze inna zaleta stworzenia prostego wykresu - poznajemy nowe techniki, które mogą nam się kiedyś przydać w zupełnie innym obszarze. I jeszcze jedno - mamy w zasadzie nieograniczone możliwości dostosowania naszego wykresu. Duże przeróbki w gotowym komponencie są niekiedy znacznie bardziej czasochłonne i ryzykowne niż zmiany we własnym, prostym rozwiązaniu.

Żebym nie został źle zrozumiany - stosowanie obcych komponentów nie jest złe i często nie trzeba wymyślać wszystkiego od nowa. Wszystko zależy od konkretnego przypadku.

Wykres słupkowy - opis algorytmu

Algorytm jest prosty i składa się z kilku kroków.

  1. Wyznaczenie maksymalnej wartości.
  2. Narysowanie konkretnego słupka o długości proporcjonalnej do maksymalnej wartości.

Na początku należy ustalić, w jaki sposób przekazywane będą dane. Uznałem, że potrzebne będą nazwy słupków oraz, co jasne, wartości. Najłatwiej przekazać takie dane w postaci tablicy:

drawHBar("wykres",
  [
    ["Krzysztof",100],
    ["Tomek",93],
    ["Michał",80],
    ["Elwira",60],
    ["Bogumił",48],
    ["Aneta",36],
    ["Jakub",30],
    ["Eryk",28],
    ["Karol",26],
    ["Bolesław",20]
  ]);

Pierwszy parametr będzie określał nazwę kontrolki, na której będziemy rysować, drugi to tablica etykiet z wartościami. Przejdźmy do implementacji.

Implementacja prostego wykresu w HTML

Przyjrzyjmy się przykładowej implementacji pokazanej na poniższym listingu.

function drawHBar(cName, data)
{
  //Znajdź maksymalną wartość
  var max = 1;
  for (var i=0; i<data.length; i++)
    if (data[i][1]>max)
      max = data[i][1];
  
  //wymiary wykresu, czcionki, odstępy
  var barMargin = 2;
  var textOffset = 5;
  var height = document.getElementById(cName).clientHeight;
  var width = document.getElementById(cName).clientWidth;
  var barHeight = height/data.length;
  var fontHeight = barHeight-4*barMargin; 
  
  var canvas = document.getElementById(cName);
  var ctx = canvas.getContext("2d");
  ctx.font=fontHeight+"px Arial";
  for (var i=0; i<data.length; i++)
  {
    //narysuj słupek
    ctx.fillStyle="#B0B0FF";
    ctx.fillRect(0,i*barHeight+barMargin,width*data[i][1]/max,barHeight-2*barMargin);
    ctx.strokeRect(0,i*barHeight+barMargin,width*data[i][1]/max,barHeight-2*barMargin);
    
    //wypisz tekst
    ctx.fillStyle="#000000";
    ctx.fillText(data[i][0]+" ("+data[i][1]+")", textOffset, (i+1)*barHeight-3*barMargin);
  }
}

Postaram się teraz wyjaśnić wszystkie etapy. Na początku wyliczam wartość maksymalną przeglądając wszystkie wartości przekazane w parametrze - największą z nich zapisuję w zmiennej max. Następnie wyliczam kilka zmiennych pomocniczych, które określają kolejno:

  • barMargin - Określa odstęp pomiędzy krawędzią słupka i obszarem przeznaczonym na słupek oraz odstęp pomiędzy krawędzią słupka a krawędzią tekstu. Dzięki temu drobnemu przesunięciu słupki i opisy nie nakładają się na siebie.
  • textOffset - Definiuje odstęp tekstu (nazwy wartości) od lewej krawędzi.
  • height - Wysokość całego wykresu.
  • width - Szerokość całego wykresu.
  • barHeight - Obszar przeznaczony na jeden słupek.
  • fontHeight - Wysokość czcionki określona jako obszar na słupek pomniejszony o 4 odstępy barMargin. Jeden odstęp jest dla słupka na górze, drugi odstęp dla czcionki na górze, dwa kolejne na dole.

Kolejnym etapem jest pobranie obiektu, na którym można rysować (kontekst elementu canvas). Wyszukiwany jest on po identyfikatorze, co wymusza z jednej strony zdefiniowanie takiego elementu:

<canvas id="wykreswidth="600height="240/>

A z drugiej strony wykonanie odpowiednich instrukcji JavaScript:

var canvas = document.getElementById(cName);
var ctx = canvas.getContext("2d");

Na tak pobranym kontekście można już rysować. Rysowanie polega na ustawianiu określonych atrybutów i wywoływaniu kolejnych metod. Atrybuty stałe można ustawić przed pętlą (na przykład wygląd czcionki: ctx.font), pozostałe w bardziej odpowiednim miejscu.

Zestaw potrzebnych metod elementu canvas

Do narysowania wykresu wystarczy kilka metod i atrybutów:

  • fillStyle - Określa sposób wypełnienia obiektów graficznych.
  • fillRect - Rysuje wypełniony prostokąt z parametrami (pozycjaX, pozycjaY, szerokość, wysokość).
  • strokeRect - Rysuje prostokątną ramkę z parametrami (pozycjaX, pozycjaY, szerokość, wysokość).
  • fillText - Rysuje (wypisuje) tekst z parametrami (tekst, pozycjaX, pozycjaY). Wysokość zależy od ustawień czcionki (ctx.font), szerokość od ustawień czcionki i wyświetlanego tekstu.

To w zasadzie wszystko. Wystarcza to, aby cieszyć się prostym wykresem:

Rys 1. Wynik rocznej oceny pracowników.

Nic nie stoi na przeszkodzi, aby taki wykres jakoś upiększyć, przekazać kolor w postaci parametru. To już pozostawiam do samodzielengo opracownia. Gdyby pojawiły się jakieś problemy, można skorzystać z komentarzy.

Kategoria:HTMLJavaScriptCanvas

, 2013-12-20

Brak komentarzy - bądź pierwszy

Dodaj komentarz
Wyślij
Ostatnie komentarze
Dzieki za te informacje. były kluczowe
Dobrze wyjaśnione, dzięki !
a z innej strony - co gdybym ciąg znaków chciał mieć rozbity nie na wiersze a na kolumny? Czyli ciąg ABCD: 1. kolumna: A, 2. kolumna: B, 3. kolumna: C, 4 kolumna: D?
Ciekawy artykuł.
Czy można za pomocą EF wysłać swoje zapytanie?
Czy lepiej do tego użyć ADO.net i DataTable?