Dnes přicházím s druhou, závěrečnou polovinou PHP skriptu pro vytváření obrázkových grafů. V poněkud rozsáhlejším článku si ukážeme, jak načíst data z databáze a kreslit jejich křivky do grafu.
Minule jsme si připravili všechny potřebné hodnoty, aby graf byl snadno modifikovatelný. Jak rozměrově, tak i počtem hodnot. Dnes všechny připravené a vypočítané parametry použijeme. Dostáváme se totiž k vlastnímu kreslení grafu.
// nejprve pošlu hlavičku obrázku Header(„Content-Type: image/gif“); // vytvořím prázdný obrázek $im = ImageCreate($sirka_obrazku, $vyska_obrazku); // nadefinuji si barvy, ktere budu potřebovat $bila = ImageColorAllocate($im, 255, 255, 255); $cerna = ImageColorAllocate($im, 0, 0, 0); $cervena = ImageColorAllocate($im, 255, 0, 0); $zelena = ImageColorAllocate($im, 0, 255, 0); |
|
Zahájíme vlastní práci s grafikou. Nejprve odešleme hlavičku obrázku. Protože chceme vytvořit obrázek ve formátu GIF, je zde uvedeno image/gif. Kdybychom chtěli vytvořit obrázek PNG, museli bychom za poslední lomítko místo gif napsat png, u JPG obrázku potom jpg.
Dále vytvoříme v paměti prázdný obrázek požadovaných rozměrů. Do proměnné $im obdržíme jeho identifikátor, pomocí kterého dále s obrázkem pracujeme. A nakonec nadefinujeme a v paletě obrázku alokujeme barvy, které budeme používat. Bílou barvou nebudeme sice kreslit, ale bude použita jako pozadí obrázku.
//nakreslím osu x ImageLine($im, $bod0_x-1, $vyska_obrazku-$bod0_y, $sirka_obrazku-$pravy_okraj, $vyska_obrazku-$bod0_y, $cerna); //nakreslím osu y ImageLine($im, $bod0_x, $vyska_obrazku-$bod0_y+1, $bod0_x, $horni_okraj, $cerna); |
|
Nakreslíme osy x a y. Použijeme k tomu funkci $ImageLine, jejímiž parametry jsou: identifikátor obrázku do nějž kreslíme, x-ová souřadnice počátečního bodu, y-ová souřadnice počátečního bodu, x-ová souřadnice koncového bodu, y-ová souřadnice koncového bodu a nakonec barva čáry.
Dlužno podotknout, že počátek souřadnicového systému vlastního obrázku je v levém horním rohu. A na to nesmíme při kreslení našeho grafu, který má samozřejmě počátek blízko levého dolního rohu, zapomenout.
//nejprve si spočítám, kolik asi popisek osy y se mi na výšku vejde $pocet_popisek_osy_y = round(($vyska_obrazku – $bod0_y – $horni_okraj) / (2 * ImageFontHeight($fontsize))); //podle toho spočítám krok osy y $krok_hodnot_osy_y = ceil(($max-$min)/($pocet_popisek_osy_y)); //vypočítám převodní koeficient osy y $koeficient_y = floor(($vyska_obrazku – $bod0_y – $horni_okraj) / ($max – $min)); // vypíši hodnoty osy y for ($i=$min;$i<=$max; $i+=$krok_hodnot_osy_y) { $pomy = $vyska_obrazku – $bod0_y – (($i-$min) * $koeficient_y); // ryska na ose y ImageLine($im, $bod0_x-2, $pomy, $bod0_x+1, $pomy, $cerna); // popiska rysky na ose y ImageString($im, $fontsize, 0, $pomy-round(ImageFontHeight($fontsize)/2), str_pad($i, $cislic_osy_y-1, “ „, STR_PAD_LEFT), $cerna); } // a ještě vypíši název osy y ImageString($im, $fontsize, 0, $horni_okraj, str_pad($nazev_osy_y, $cislic_osy_y-1, “ „, STR_PAD_LEFT), $cerna); |
|
Na osu y postupně vyneseme cejchování, popisky hodnot a název osy. Postup je vidět v předchozí ukázce kódu. Musíme si nejprve určit, v jakém intervalu osu y ocejchujeme. Dále musíme vypočítat koeficient, kterým budeme násobit y-ové hodnoty grafu. Tento koeficient využijeme nejen při kreslení křivek grafu, ale i teď hned při cejchování osy y. Nakonec ještě vypíšeme název osy.
//vypočítám převodní koeficient osy x $koeficient_x = floor(($sirka_obrazku – $bod0_x – $pravy_okraj) / $pocet_hodnot); //zjistím si, jak budu vypisovat popisky osy x $pocet_popisek_osy_x = $sirka_obrazku / (ImageFontHeight($fontsize) * 2); if ($pocet_popisek_osy_x > $pocet_hodnot) $interval_popisek_x = 1; //budu zobrazovat popisku každé hodnoty osy x else //budu zobrazovat popisky pouze určitých hodnot osy x $interval_popisek_x = ceil($pocet_hodnot / $pocet_popisek_osy_x); |
|
Podobným způsobem si připravíme i osu x. Zde však předem víme počet hodnot, které chceme na ose x vynášet ($pocet_hodnot), a potřebujeme zjistit, jestli se nám na šířku grafu vejdou popisky všech hodnot, nebo jestli budeme některé vynechávat. Vypočítáme si vlastně krok pro osu x. Do proměnné $pocet_hodnot si uložíme, kolikátou hodnotu na ose x budeme popisovat. Pokud je to 1, jako v první větvi podmínky if, znamená to, že budeme popisku tisknout u každé 1., tedy u každé hodnoty. V případě vyššího čísla, např. 2, to bude pouze každá druhá popiska.
//provedu dotaz do databáze, na hodnoty grafu @$vysledek = mysql_query(„select den, muzi, zeny“ .“ from lide“ .“ order by den“); if (!$vysledek): { // mám smůlu, nepodařilo se mi získat data z tabulky // vypíšu o tom do obrázku zprávu ImageString($im, $fontsize, $bod0_x+5, $horni_okraj, „Nepodařilo se přečíst hodnoty grafu z tabulky“, $cerna); } else: { |
|
Začínáme pracovat na vykreslení křivek grafu. Tomu samozřejmě předchází dotaz do databáze a zjištění hodnot grafu. Pokud se mi nezdaří z databáze data přečíst, mohu o tom vypsat zprávu do obrázku. Teď už to jde, protože obrázek je již vytvořen.
$pocet = mysql_NumRows($vysledek); if ($pocet_hodnot > $pocet) $pocet_hodnot = $pocet; // kdyby mezitim nahodou nekdo nejaky udaj vymazal //vypisu prvni popisku osy x ImageStringUp($im, $fontsize, $bod0_x-round(ImageFontHeight($fontsize)/2), $vyska_obrazku, str_pad(mysql_result($vysledek, 0, „den“), $cislic_osy_x-1, “ „, STR_PAD_LEFT), $cerna); $posledni_x = $bod0_x; $posl_y_zeny = $vyska_obrazku – $bod0_y – ((mysql_result($vysledek, 0, „zeny“) – $min) * $koeficient_y); $posl_y_muzi = $vyska_obrazku – $bod0_y – ((mysql_result($vysledek, 0, „muzi“) – $min) * $koeficient_y); |
|
Podařilo se načíst data z tabulky, a my si pro kontrolu zjistíme, zda se jejich počet od prvního dotazu náhodou nezměnil. Pokud by někdo nějakou větu vymazal, dostali bychom hodnot méně, než očekáváme, a na konci vykreslovací smyčky by došlo k chybě.
Pokud náhodou data mezitím přibyla, budeme přebývající ignorovat, protože na ně stejně nemáme místo. Do proměnných $posledni_x, $posl_y_zeny a $posl_y_muzi si budeme v každém kroku ukládat polohy naposledy nakreslených bodů, abych z nich mohli pokračovat přímkou do dalších bodů. A protže teď jsme teprve na počátku, na první hodnotě osy x, pouze si do těchto proměnných uložíme hodnoty, ze kterých budeme kreslit přímky do 2. bodu.
$i = 1; while ($i<$pocet_hodnot): // vypočítám x polohu této hodnoty grafu $pom_x = ($i * $koeficient_x) + $bod0_x; // vypočítám y polohu obou hodnot $pom_y_zeny = $vyska_obrazku – $bod0_y – ((mysql_result($vysledek, $i, „zeny“) – $min) * $koeficient_y); $pom_y_muzi = $vyska_obrazku – $bod0_y – ((mysql_result($vysledek, $i, „muzi“) – $min) * $koeficient_y); //nakreslím křivky od minulého k tomuto bodu ImageLine($im, $posledni_x, $posl_y_zeny, $pom_x, $pom_y_zeny, $cervena); ImageLine($im, $posledni_x, $posl_y_muzi, $pom_x, $pom_y_muzi, $zelena); // vykreslím rysku na ose x ImageLine($im, $pom_x, $vyska_obrazku – $bod0_y + 2, $pom_x, $vyska_obrazku – $bod0_y – 2, $cerna); // vypíšu popisku osy x if (round($i/$interval_popisek_x) == ($i/$interval_popisek_x)) ImageStringUp($im, $fontsize, $pom_x – round(ImageFontHeight($fontsize)/2), $vyska_obrazku, str_pad(mysql_result($vysledek, $i, „den“), $cislic_osy_x-1, “ „, STR_PAD_LEFT), $cerna); // nastavím současné hodnoty jako minulé $posledni_x = $pom_x; $posl_y_zeny = $pom_y_zeny; $posl_y_muzi = $pom_y_muzi; $i++; endwhile; |
|
Pomocí této smyčky vykreslíme celý graf. Nejprve vypočítáme pomocí koeficientů x-ovou a y-ové souřadnice kreslených bodů. Nakreslíme křivky z minulých bodů do těchto bodů. Uděláme rysku na osu x. A pokud je to zrovna ryska, ktará spadá do intervalu pro vypsání popisky osy x, vytiskneme i popisku osy x. Nakonec uložíme současné souřadnice pro použití v příštím kroku do pomocných proměnných.
//vypíši název osy x ImageString($im, $fontsize, $sirka_obrazku – $pravy_okraj, $vyska_obrazku-$bod0_y + 5, $nazev_osy_x, $cerna); |
|
Dokončili jsme vykreslování obou křivek grafu, a teď nám zbývá vytisknout název osy x.
$pom_x = $sirka_obrazku – $pravy_okraj; //vypíši legendu pro muže ImageString($im, $fontsize, $pom_x + $delka_vzorku_legendy + ImageFontWidth($fontsize), $horni_okraj, $nazev_krivky_1, $cerna); //vzorek pro legendu $pom_y = $horni_okraj + round(ImageFontHeight($fontsize)/2); ImageLine($im, $pom_x, $pom_y, $pom_x + $delka_vzorku_legendy, $pom_y, $cervena); //vypíši legendu pro ženy ImageString($im, $fontsize, $pom_x + $delka_vzorku_legendy + ImageFontWidth($fontsize), $horni_okraj + (ImageFontHeight($fontsize) * 2), $nazev_krivky_2, $cerna); $pom_y += + (ImageFontHeight($fontsize) * 2); ImageLine($im, $pom_x, $pom_y, $pom_x + $delka_vzorku_legendy, $pom_y, $zelena); |
|
Aby byl graf kompletní, musíme jej opatřit legendou. Vzorkem čar, které barvou odpovídají křivkám grafu, včetně popisu, které hodnoty křivky této barvy představují.
} endif; mysql_Close(); ImageGIF($im); ?> |
|
Ukončíme větev, ve které jsme vykreslovali graf a uzavřeme spojení s databází. Nakonec přichází příkaz, kterým uzavřeme obrázek a odešleme jej návštěvníkovi stránky. Pracovali jsme s formátem GIF, proto příkaz ImageGIF. Pokud bychom vytvářeli obrázek PNG, byl by zde příkaz ImagePNG, v případě obrázku JPG pochopitelně ImageJPG.
Z libovolného HTML dokumentu teď můžeme zavolat náš skript pomocí tagu IMG, a dostaneme celý graf ve formě obrázku. V tomto tagu můžeme skript zavolat s parametry, kterými určíme velikost požadovaného grafu.
Tag pro zobrazení grafu je úplně obyčejný:
Pro určení velikosti požadovaného grafu můžeme zadat parametry sirka a vyska:
<IMG SRC=“graf.php?sirka=300&vyska=200″> |
|
Pokud budeme chtít být opravdu důslední:
<IMG SRC=“graf.php?sirka=300&vyska=200″ WIDTH=“300″ HEIGHT=“200″ BORDER=“0″ ALT=“Graf“> |
|
Skript graf.php můžeme zavolat prostým zadáním jeho URL. Např. www.nasedomena.cz/graf.php. Pak se nám v prohlížeči zobrazí obrázek grafu ve standardních rozměrech, tedy 600×400 bodů. Skript ale můžeme volat z nějakého HTML dokumentu pomocí standardního tagu pro zobrazení obrázků – IMG. To se nám samozřejmě hodí, pokud potřebujeme graf nějak okomentovat, nebo zakomponovat do standardního vzhledu našeho webu.
Abychom mohli snadno měnit velikost obrázku z jiných HTML dokumentů, naprogramovali jsme si do skriptu jednoduchou pomůcku. Kontrolujeme, jestli jsou zadány nějaké hodnoty v proměnných $sirka a $vyska. Pokud ano, standardní rozměry grafu se změní na tyto hodnoty. Pamatujete? A teď se dostáváme k tomu, jak předat požadovanou šířku a výšku našemu skriptu. Do pole SRC tagu IMG, kterým voláme náš skript, napíšeme toto: "graf.php?sirka=300&vyska=200". Jsou to parametry, pro které si PHP automaticky vytvoří proměnné $sirka a $vyska, a vloží do nich hodnoty 300 a 200. Není nic snažšího. Možná namítnete, že velikost obrázku se přece ovlivňuje pomocí height a width. Máte pravdu. Ale v žádném případě by se neměly tyto parametry používat tak, že se pomocí nich zobrazí obrázek 800×600 bodů jako náhled ve velikosti 150×100 bodů. Pro tyto účely bychom měli mít dvě verze obrázků. Velké a jejich zmenšeniny.
Po Internetu bychom měli posílat a stahovat pouze nezbytně nutné množství dat. Jde o rychlost a o peníze. Proto si, pokud chceme jen náhled grafu, už při volání skriptu rovnou řekneme, pomocí parametrů sirka a vyska, že chceme náš graf jen malý. Není nic snažšího, než udělat tento malý náhled jako hypertextový odkaz (<a href=“…), a při kliknutí na náhled grafu se skript zavolá ještě jednou, a zobrazí se v normální velikosti.
A to je už opravdu vše. Celý příklad si můžete stáhnout zde. Obsahuje kromě skriptu, který jsme právě probrali, také i skript pro vytvoření tabulky lidé s demonstračními hodnotami. Dále je zde soubor zobraz_graf.htm, v němž je ukázáno, jak zobrazit graf v HTML dokumentu, i včetně volání skriptu s parametry.
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.