JPGraph, wykresy z PHP’a

Onego czasu próbowałem znaleźć coś co ułatwiłoby mi rysowanie prostych wykresów w PHP’ie inaczej niż z palca w GD. Kumpel polecił mi JPGraph.

JPGraph to świetna sprawa, do generowania statystyk jak chociażby na mojej stronie, ale biblioteka potrafi dużo więcej…

Załóżmy, że ze stronki zbieramy do bazy takie rzeczy jak: datę, adres IP, ilość połączeń z tego adresu. Prosta tabela (przykład w Postgre SQL’u):

CREATE TABLE wizyty
(
  pid serial NOT NULL,
  "data" date NOT NULL DEFAULT ('now'::text)::date,
  odslony integer NOT NULL DEFAULT 1,
  CONSTRAINT visits_pkey PRIMARY KEY (id)
);

Dane z takiej tabeli można łatwo wyciągnąć jednym select’em:

SELECT date_part('day', "data") AS x, sum(odslony) AS y
FROM wizyty
WHERE date > ('today'::date - '30 days'::interval)
GROUP BY "data"
ORDER BY "data"
LIMIT 30

Powyższe zapytanie wyciągnie nam z kolumny z datą tylko dzień miesiąca, który posłuży za etykietę (oś X) oraz sumę odsłon z danego dnia (oś Y), posortowane według daty i tylko z ostanich 30 dni.

W zależności od sposobu dostępu i pobierania wyników, trzeba je ładnie zapisać w dwóch tablicach. Ja to robię w prostej pętli:

foreach ($query->result() as $row) {
	$x[] = $row->x;
	$y[] = $row->y;
}

Mając dane została zabawa z ustawieniem oczekiwanych opcji wykresu:

/* bez tego ani rusz */
include_once 'jpgraph/jpgraph.php';
include_once 'jpgraph/jpgraph_bar.php';

/* szerokość */
$width = 400;

/* wysokość */
$height = 300;

$graph = new Graph($width, $height);

/* oś X tekst, oś Y wartości całkowite */
$graph->SetScale("textint");

/* kolorowa ramka */
$graph->SetFrame(true, '#222222');
$graph->SetMarginColor('#222222');

/* tytuł wykresu, trochę konfiguracji fontów i kolorów */
$graph->title->Set('Sumaryczna liczba odsłon');
$graph->title->SetFont(FF_VERDANA,FS_BOLD,10);
$graph->title->SetColor('#999999');

/* podobnież jak powyżej dla osi X */
$graph->xaxis->SetFont(FF_VERDANA,FS_NORMAL,8);
$graph->xaxis->SetColor('#999999');
$graph->yaxis->SetFont(FF_VERDANA,FS_NORMAL,8);
$graph->yaxis->SetColor('#999999');

/* dodatkowe ozdobniki ;) */
$graph->yscale->ticks->SupressZeroLabel(false);
$graph->yscale->ticks->SetColor('#999999');
$graph->xaxis->SetTickLabels($x);

/* genrujemy właściwy wykres, w tym przypadku słupkowy */
$bplot = new BarPlot($y);
$bplot->SetWidth(0.6);
$bplot->SetFillColor('#D01A71@0.25');
$bplot->SetColor('gray');

/* dodajemy wykres do obiektu $graph (który to może pomieścić
i wyświetlić wiele wykresów, co z resztą pokazane jest poniżej) */
$graph->Add($bplot);

/* teraz wykres liniowy */
$lplot = new LinePlot($y);

/* z wypełnieniem pod wykresem */
$lplot->SetFillColor('skyblue@0.5');
$lplot->SetColor('navy@0.7');
$lplot->SetBarCenter();

/* typ znacznika na łącznikach pomiędzy kolejnymi słupkami */
$lplot->mark->SetType(MARK_SQUARE);
$lplot->mark->SetColor('blue@0.5');
$lplot->mark->SetFillColor('lightblue');
$lplot->mark->SetSize(6);

/* wrzucamy kolejny wykres do obrazu */
$graph->Add($lplot);

/* a teraz magia... */
$graph->Stroke();

Co to robi… Ano dokładnie taki wykres jak ten poniżej:

 

allvisits

Co prawda ten wykres nie odpowiada w 100% podanemu źródłu. To statystyka z mojej strony, która niebieską linią zaznacza volumen pobranych danych – przykład jest nieco uproszczony.

Na pierwszy rzut oka powyższy skrypt wydaje się dość długi i jest tam dużo nie do końca jasnych opcji, ale najfajniejsze jest to, że tak na prawdę nie trzeba się tego uczyć. Biblioteka domyślnie dostarczana jest z masą przykładów. Wystarczy wybrać wykres podobny do tego, który sami chcemy zrobić – skopiować większość kodu. Znaleźć inne wykresy, których cechy chcemy powielić i po kilku próbach skleimy takiego Frankenstein’a jakiego świat nie widział wcześniej ;-D

Mój wykres akurat ma trochę zmieniony kolor tła ramki i fonty, tak aby lepiej wkomponował się w moją stronę – reszta bazuje na dwóch przykładach z dokumentacji. Na zrobienie pierwszego wykresu z wykorzystaniem JPGraph potrzebowałem ok. godziny. Teraz wystarcza mi 10 minut 🙂

 

Leave a Reply

Your email address will not be published. Required fields are marked *