Pokud používáme různé statistiky přístupů, nebo provádíme jiné sběry dat, potřebujeme občas tato data nějak vyhodnotit. Ano, při použití SQL databází dokážeme poměrně snadno získat potřebné souhrnné hodnoty, ale někdy to přece jen nestačí. Někdy je nejen nutné, ale i prospěšné, data nějak vizualizovat. Třeba vytvořit graf. To je nejsnažší způsob, jak to provést. Nevíte jak? Dnes si to ukážeme.

PHP, pokud obsahuje knihovnu GD, umí poměrně snadno vytvářet obrázky v několika formátech. Jsou to GIF, JPG a PNG. Z hlediska vytvoření obrázku na formátu nezáleží. Jeho formát určí úvodní hlavička a příkaz pro vypsání obrázku v závěru skriptu, ostatní příkazy pro kreslení a psaní do obrázku jsou naprosto shodné.

Formát JPG je vhodný pro ukládání fotografií, neboť je založen na ztrátové kompresi, díky které dokáže, při relativním zachování vzhledu obrázku, rapidně snížit výsledný datový objem. Tento formát se však nehodí pro obyčejný graf s několika křivkami, který budeme v našem dnešním článku vytvářet.

Velice vhodný je formát GIF. Má výborný kompresní poměr právě pro takový typ obrázku, který dnes vytvoříme. Poslední dobou se diskutuje problém licenčních poplatků z vytváření GIF obrázků, a právě proto se poslední verze PHP začaly objevovat sice včetně knihovny GD, ale zato bez podpory obrázků GIF.

Jako nejvíce vhodný se tedy jeví formát PNG, který by měl být lepší alternativou obrázku GIF. Kromě většího počtu barev má menší velikost výsledného souboru. Dnešní prohlížeče ale mají se zobrazováním tohoto formátu stále určité problémy, takže raději zůstaneme u prověřeného GIFu.

V článku je na patřičných místech popsáno, jak lze velice snadno dosáhnout změny výsledného formátu obrázku. Kdo tedy bude mít chuť experimentovat, může, změnou pouhých dvou řádků programového kódu, ovlivnit výsledný grafický formát. Snadno si tak může ověřit jak možnosti svého prohlížeče, tak i výslednou velikost vygenerovaného bitmapového souboru.

Ještě než opravdu začneme, ukážeme si, co je cílem našeho snažení. Také proto, abychom si rozuměli, až budeme mluvit o jednotlivých částech grafu.

Graf

Takový graf si dnes nakreslíme. Jedná se o fiktivní statistiku. V MySQL tabulce máme pro 31 dní uloženy počty žen a mužů, kteří nás v tyto dny navštívili.

Nejprve se připojíme k databázi, ze které potřebujeme načíst statistická data. Způsob připojení zde nebudeme probírat, můžete jej najít v některém ze starších článků na Interval.cz. Provedeme první dotaz, kterým zjistíme mezní hodnoty naší statistiky – tedy maximální a minimální hodnoty pro obě číselné řady a počet hodnot.

@$vysledek = mysql_query(„select count(*)“
                        .“,max(muzi)“
                        .“,min(muzi)“
                        .“,max(zeny)“
                        .“,min(zeny)“
                        .“,max(length(den))“
                        .“ from lide“);
if (!$vysledek) exit;

Můžeme snadno nastavit všechny parametry grafu na začátku skriptu staticky, ale pak se bude náš skript obtížně modifikovat pro různé aplikace. My se tedy budeme, v mezích možností, snažit vše naprogramovat dynamicky, aby byl graf variabilní. Proto si zjišťujeme tyto mezní hodnoty. Maximální a minimální hodnoty použijeme pro ocejchování osy y, počet hodnot použijeme pro totéž na ose x. Poslední hodnota, max(length(den)), nám slouží k určení výšky spodního okraje grafu, kam budeme vypisovat popisky osy x. Protože výsledný obrázek zřejmě očekáváme v nějakém HTML dokumentu právě tak jako obrázek, nějaké vypisování chybových zpráv by nemělo význam. Proto běh skriptu při nezdařeném čtení z databáze ukončíme.

$mezni_hodnoty = mysql_fetch_row($vysledek); // výsledek převedeme do pole
$min = min($mezni_hodnoty[2], $mezni_hodnoty[4]); // zjistime minimalni hodnotu
$max = max($mezni_hodnoty[1], $mezni_hodnoty[3]); // zjistime maximalni hodnotu
$pocet_hodnot = $mezni_hodnoty[0]; //pocet hodnot grafu
$cislic_osy_x = $mezni_hodnoty[5] + 2; //přičtu ještě 2 znaky navíc
$sirka_obrazku = 600; // standardní šířka výsledného obrázku
$vyska_obrazku = 400; // standardní výška výsledného obrázku
$horni_okraj = 10; // horní okraj grafu
$fontsize = 1; // velikost použitého fontu
$nazev_osy_y = ‚Počet‘;
$nazev_osy_x = ‚Den‘;
$delka_vzorku_legendy = 10;
$nazev_krivky_1 = „Zeny“;
$nazev_krivky_2 = „Muzi“;

Načtené hodnoty si vložíme do pole $mezni_hodnoty. Zjistíme skutečné minimum a maximum hodnot. Do proměnné si uložíme i počet hodnot na ose x. Popisky osy x budeme vypisovat svisle, proto si do proměnné $cislic_osy_x uložíme počet znaků, který obsahuje nejdelší popiska osy x. Tento počet ještě zvýšíme o dva znaky, abychom měli nějakou rezervu od okraje obrázku i od osy x.

V dalších proměnných máme nastavenou šířku a výšku výsledného obrázku. Tyto dvě hodnoty můžeme změnit i pomocí parametrů zadaných "zvenku", při volání skriptu. Jak, to si povíme za chvíli. Horní okraj je nastaven pevně, protože nám jej variabilní hodnoty grafu většinou nijak neovlivní. $fontsize určuje velikost fontu použitého pro popisky os a legendu. Můžeme nastavit hodnoty 1-5.

Názvy os není třeba vysvětlovat, zastavíme se u dalších proměnných. $delka_vzorku_legendy určuje délku čárky, kterou použijeme jako vzorek v legendě grafu. Názvy křivek jsou také pro legendu.

// překontroluji si, zda je šířka nastavena zvenku, pomocí parametrů
if (IsSet($sirka))
  $sirka_obrazku = $sirka;
if (IsSet($vyska))
 $vyska_obrazku = $vyska;

Tady je výše zmíněný způsob modifikace velikosti obrázku pomocí parametrů zadaných "zvenku".

//vypočítám šířku pravého okraje grafu
$pravy_okraj = $delka_vzorku_legendy + (ImageFontWidth($fontsize)
  * (2 + max(strlen($nazev_krivky_1), strlen($nazev_krivky_2), strlen($nazev_osy_x))));

Pravý okraj grafu využijeme pro umístění legendy a název osy x. Jeho šířku vypočítáme tak, že si šířku jednoho znaku použitého fontu vynásobíme nejdelším textem legendy, a připočítáme délku vzorové čárky a patřičnou rezervu. Šířku znaku nám zjistí funkce ImageFontWidth. Pro určení výšky znaku použijeme obdobnou funkci ImageFontHeight. To ale budeme potřebovat až za chvíli.

// zjistím a nastavím levý okraj grafu
$cislic_osy_y = Ceil(Log10($max+1)) + 2; //přičtu ještě 2 znaky navíc
if (strlen($nazev_osy_y)+2 > $cislic_osy_y)
  $cislic_osy_y = strlen($nazev_osy_y)+2;
$bod0_x = ImageFontWidth($fontsize)*$cislic_osy_y; //poloha y-ové osy
// nastavím spodní okraj grafu
$bod0_y = ImageFontWidth($fontsize)*$cislic_osy_x; // poloha x-ové osy

Horní okraj máme nastavený napevno, pravý jsme vypočítali. Teď vypočítáme velikost levého okraje. Musí se nám do něj vejít i ten nejdelší popisek osy y. A musí se tam, s rezervou jednoho znaku před a za, vejít i název osy y. Šířku levého okraje uložíme do proměnné $bod0_x, protože je to vlastně x-ová souřadnice počátečního bodu grafu. Do proměnné $bod0_y si podobným způsobem vypočítáme spodní okraj grafu, určený pro popisky osy x. To je y-ová souřadnice počátečního bodu grafu.

Pokračování příště, přeji vám hezký den.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět