Grafy, grafy, grafy... a jak na ně v PHP
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Grafy, grafy, grafy... a jak na ně v PHPGrafy, grafy, grafy... a jak na ně v PHP

 

Grafy, grafy, grafy... a jak na ně v PHP

Google       Google       8. 1. 2008       48 303×

Často máte na stránkách nějaké statistické údaje, které potřebujete přehledně prezentovat. Třeba počet zobrazení stránky za určitý den, nebo počty kusů, počty reakcí a další různé informace. Nejpřehlednějšími možnostmi zobrazení těchto informací jsou tabulky a grafy. Tabulky předpokládám zvládne každý, kdo trochu zná (X)HTML, takže se dneska podíváme, jak si vytvořit graf podobný tomuto.

Na začátek tohoto článku bychom si měli povědět něco málo o vlastnostech kreslení v PHP. Měli byste mít vždy na paměti, že kreslit v PHP je stejné jako kreslit na papír. Pokud na papíře uděláte jednu čáru a přes ní druhou čáru, tak ta druhá bude vždy vidět celá, ale první bude překryta druhou. A totéž platí v PHP. Prvek, který nakreslím až na konci celého skriptu půjde nejlépe vidět. Takže pokud chcete něco ohraničit, nejdříve nakreslete výplň a teprve pak okraje.

Jak už jsem psal v úvodu, náplní dnešního článku bude kreslení grafu. V případě zájmu bych udělal kompletní článek (popřípadě seriál) o kreslení a využití GD knihovny v PHP. Současně předpokládám, že máte aspoň základní znalosti PHP, takže nebudu vysvětlovat typy proměnných, vytvoření pole, apod.

Jelikož bude článek poměrně rozsáhlý, bude na konci k dispozici celý vzorový kód.

Funkce PHP pro práci s grafikou poznáte tak, že začínají slovem image. V každé funkci se musíte odkázat na daný obrázek, aby bylo zřetelné, k čemu daný prvek patří.

Souřadnicový systém obrázku

K určení přesné polohy prvku v obrázku slouží souřadnicový systém, který se skládá z hodnot x a y. Pokud zadáte, že hodnota x a y je nula, ocitnete se v levém horním rohu. Jakmile chcete posunout prvek více doprava, musíte zvětšit hodnotu x. Jestliže naopak chcete tento prvek posunout více doleva, hodnotu x zmenšete. Stejná pravidla se týkají i hodnoty y. Pokud zvětšíte tuto hodnotu, prvek se posune směrem dolů. Pro názornost se podívejte na obrázek.

Nastavení parametrů obrázku

Před samotným skriptem pro kreslení potřebujeme ještě nastavit několik parametrů. Nastavíme si rozměry samotného obrázku, rozměry osy x a y, font pro popisky (je možno použít jakýkoliv True Type font), maximální hodnotu pro koeficient 1 a taky rozdíl v pixelech mezi nulou a maximální hodnotou. Dále si nastavíme souřadnice sloupců grafu a hodnot na ose x. A jako poslední část v tomto kroku si nastavíme hodnoty, které budeme chtít do grafu zanést – u pole s hodnotami musíte dbát na jednu věc: první prvek pole musí být nula a až další prvky mohou být naše hodnoty, protože s prvním prvkem pole se nepracuje.

//definovani nekolika promennych
$font = "./ARIAL.TTF"; //definovani cesty k fontu pro pismo
$width = 700; //sirka obrazku
$height = 500; //vyska obrazku
$osax_start=90; //pocatek osy x
$osax_konec=410; //konec osy x
$osax_x=100; //souradnice x se pro osu x nemeni
$osay_start=90; //pocatek osy y
$osay_konec=650; //konec osy y
$osay_y=400; //souradnice y se pro osu y nemeni
$maximum_hodnota=1200; //maximalni hodnota pri koeficientu 1
$pixely=300; //mezera mezi nulou a maximalni hodnotou (pri koef. 1 je rozsah 0-1200)

//body na ose x - souradnice x = 100
$bodX = array( 400, 350, 300, 250, 200, 150, 100);

//body na ose y - souradnice y = 400
$bodY = array( 100, 200, 300, 400, 500, 600);

//zobrazovane hodnoty
$hodnoty = array(0, 1000, 256, 489, 777, 645); //prvni vzdy nula, az za ni hodnoty!!

Vytvoření obrázku

Pro vytvoření obrázku slouží funkce imagecreate().

Popis funkce:
resource imagecreate ( int $sirka, int $vyska )

sirka → udává šířku obrázku v pixelech
vyska → udává výšku obrázku v pixelech

Návratové hodnoty
Funkce vrací obrázek. Pokud dojde k chybě, vrací FALSE.

//vytvoreni obrazku o rozmerech $width x $height
$im=imagecreate($width, $height);

Hrátky s barvou

Pro odlišení sloupců a zpestření grafu použijeme barvy. Stejně jako prvky, tak i vlastnosti musíme odkazovat na daný obrázek. Funkce imagecolorallocate() nám vytvoří ukazatel na barvu, ale paletu barev si bere z obrázku. Takže pokud tuto funkci použijete na obrázek, který je definovaný jako černobílý, můžete z něj extrahovat maximálně odstíny šedé, ale nikdy barvy. Výhodou je tento případ, kdy si obrázek vytváříme pomocí funkce imagecreate(), jelikož obsahuje paletu všech barev. Barva jde ale bohužel použít pouze na obrázek se zdrojovou paletou. Základem pro definování barev je znalost zápisu této barvy v RGB formátu.

Popis funkce:
int imagecolorallocate ( resource $obrazek, int $cervena, int $zelena, int $modra )

obrazek → udává zdrojovou paletu
cervena → udává množství červené složky
zelena → udává množství zelené složky
modra → udává množství modré složky

Návratové hodnoty
Funkce vrací identifikátor barvy. Pokud dojde k chybě, vrací FALSE.

//definice barev ve tvaru R,G,B (cervena, zelena, modra)
$bg=imagecolorallocate($im,255,255,255); //barva pozadi
$white=imagecolorallocate($im,255,255,255); //bila barva
$black=imagecolorallocate($im,0,0,0); //cerna barva
$red=imagecolorallocate($im,255,0,0); //cervena barva
$green=imagecolorallocate($im,0,255,0); //zelena barva
$blue=imagecolorallocate($im,0,0,255); //modra barva
$grey_light=imagecolorallocate($im,204,204,204); //svetle-seda barva
$grey_dark=imagecolorallocate($im,153,153,153); //tmave-seda barva

Nastavení tloušťky čar a jejich narýsování

Stejně jako při kreslení na papíře máte možnost volby mezi tenkým a tlustým štětcem, máte ho i zde. Můžete kreslit pentilkou, nebo kopáčem.

Ale pozor, platí zde jedno poměrně důležité pravidlo. Hodnoty x a y, které zadáte platí pro střed této přímky. Tloušťka se projeví tím, že se rovnoměrně rozdělí na obě strany od středu přímky.

Pro určení tloušťky přímky nám slouží funkce imagesetthickness(), kde zadáváme obrázek a požadovanou tloušťku. Toto nastavení platí pro všechny čáry, které nakreslíme (trojúhelník, samostatná čára, polygon, …), a platí po dobu, než nastavíme jinou tloušťku.

Popis funkce:
bool imagesetthickness ( resource $obrazek, int $tloustka )

obrazek → udává obrázek
tloustka → udává požadovanou tloušťku

Návratové hodnoty
V případě provedení vrací TRUE. Pokud dojde k chybě, vrací FALSE.

Takže už víme, jak si nastavit tloušťku jednotlivých čar. Nyní vám prozradím postup pro kreslení. Chceme-li nakreslit čáru, musíme určit, do kterého obrázku ji chceme nakreslit, jakou barvou, ale hlavně odkud a kam – zadávají se hodnoty x,y jak pro výchozí bod, tak i pro koncový bod. Matematicky řečeno, zadáváme krajní body úsečky. Pro kreslení nám slouží funkce imageline().

Popis funkce:
bool imageline ( resource $obrazek, int $vychozi_x, int $vychozi_y, int $koncove_x, int $koncove_y, int $barva )

obrazek → udává obrázek
vychozi_xx souřadnice výchozího bodu
vychozi_yy souřadnice výchozího bodu
koncove_xx souřadnice koncového bodu
koncove_yy souřadnice koncového bodu
barva → udává barvu čáry

Návratové hodnoty
V případě provedení vrací TRUE. Pokud dojde k chybě, vrací FALSE.

Kreslení polygonů (mnohoúhelníků)

Pro ty z vás, kteří by nevěděli, co si pod tímto pojmem představit, tak si řekneme, jak nakreslit různé geometrické tvary (čtverec, obdélník, trojúhelník, lichoběžník, kosočtverec, krychli, kvádr, …), kromě kruhových. Postup je přibližně stejný jako u linek, akorát zde neurčujeme pouze dva body, ale musíme zadat všechny vrcholy obrazce. Pro vykreslení mnohoúhelníku se používá funkce imagepolygon(), kam se zadává obrázek, kde má být obrazec vykreslen, dále formou pole souřadnice vrcholů, počet souřadnic a barva obrazce.

Popis funkce:
bool imagepolygon ( resource $obrazek, array $vrcholy, int $pocet_vrcholu, int $barva )

obrazek → udává obrázek
vrcholy → pole obsahující souřadnice vrcholů
vrcholy jsou zadávány:
vrcholy[0] = vrchol_x0,
vrcholy[1] = vrchol_y0,
vrcholy[2] = vrchol_x1,
vrcholy[3] = vrchol_y1,
.
.
.
pocet_vrcholu → udává počet vrcholů
barva → udává barvu čáry

Návratové hodnoty
V případě provedení vrací TRUE. Pokud dojde k chybě, vrací FALSE.

Pozadí grafu

Už víte jak nakreslit přímku, mnohoúhelník, jak změnit tloušťku přímky, tak si to teď všechno spojíme a vytvoříme si pozadí pro graf včetně záchytných čar. Nenechte se zmást funkcí imagefilledpolygon(), je to v podstatě totéž jako funkce imagepolygon(), akorát zde bude ten mnohoúhelník vybarvený.

//nastaveni tloustek car
imagesetthickness($im, 2);

//narysovani pozadi grafu
//definice pozic rohu polygonu
$hodnoty_pozadi = array(
            $osay_start+10,  $osax_start,  // bod 1 (x, y)
            $osay_start+10,  $osax_konec-10, // bod 2 (x, y)
            $osay_konec, $osax_konec-10,  // bod 3 (x, y)
            $osay_konec,  $osax_start,  // bod 4 (x, y)
            );

//narysovani vybarveneho polygonu
imagefilledpolygon($im, $hodnoty_pozadi, 4, $grey_light);

//narysovani okraju polygonu
imageline($im, $osax_x, $osax_start, $osay_konec, $osax_start, $grey_dark);
imageline($im, $osay_konec, $osay_y, $osay_konec, $osax_start, $grey_dark);


//narysovani zachytnych linek pro hodnoty na ose x
for($a=1;$a<7;$a++) {
    imageline($im, $osay_start+10, $bodX[$a], $osay_konec, $bodX[$a], $grey_dark);
}

//narysovani zachytnych linek pro hodnoty na ose y
for($b=1;$b<6;$b++) {
    imageline($im, $bodY[$b], $osax_start, $bodY[$b], $osax_konec-10, $grey_dark);
}

Výpočet rozsahu

Původně je skript nastaven tak, že je rozsah od 0 do 1200. A pro případ vyšší hodnoty je zde funkce pro výpočet koeficientu. Tímto koeficientem vynásobíme rozsahy, díky tomu bude skript schopen zobrazit v grafu jakoukoliv hodnotu.

//vypocet koeficientu
$nejvetsi=max($hodnoty);
if($nejvetsi > $maximum_hodnota) {
    $koef=ceil($nejvetsi/$maximum_hodnota);
    $maximum_hodnota=$maximum_hodnota*$koef;
} else {
    $koef=1;
}

Zápis textu do obrázku

Díky možnosti použít fonty True Type pro zápis do obrázku není problém s češtinou, i když na některých stránkách jsem viděl funkce, které převáděli diakritiku na ASCII znaky. Nejsem si jist, jak je to u starších verzí PHP, ale u PHP 5 už knihovna GD nemá problémy s diakritikou. Navíc funkce pro použití TTF slučuje několik funkcí. Ve funkci imagettftext() nastavujete velikost písma, barvu textu, sklon textu, font a počátek textu. Na rozdíl od funkcí imagechar() a imagecharup() je možno zapsat libovolně dlouhý text.

Popis funkce:
array imagettftext ( resource $obrazek, float $velikost, float $sklon, int $pozice_x, int $pozice_y, int $barva, string $font, string $text)

obrazek → udává obrázek
velikost → udává velikost písma v pixelech
sklon → udává sklon písma ve stupních
pozice_x → udává x polohu začátku textu
pozice_y → udává y polohu začátku textu
barva → udává barvu čáry
font → udává cestu ttf fontu
text → text, který bude do obrázku zapsán

Výpočet velikosti sloupce a vykreslení

Jelikož jsme si již ukázali veškeré potřebné věci, můžeme přejít k vykreslení samotných sloupců grafu. Vytvoříme si cyklus, kde budeme z pole hodnoty brát jednu hodnotu za druhou a vypočítáme si její velikost v grafu. Doufám, že je všem jasné, jak vypočítáme velikost pomocí procent. Když známe velikost sloupce, necháme si vygenerovat náhodnou barvu (kdo by chtěl, může si jednotlivé barvy předem nadefinovat). Nakreslíme sloupec o tloušťce 30 pixelů od vypočítané hodnoty dolů směrem k ose.

//vypocet a rysovani grafu hodnot
for($c=1;$c<6;$c++) {

      $cislo=$hodnoty[$c];
      $procento_px=$pixely/100;
      $mezi=$maximum_hodnota/100;
      $procento_vl=$cislo/$mezi;
      $vypocet=$procento_vl*$procento_px;
      $vysledekY=$osay_y-$vypocet;

//nahodne generovani cervene slozky
$R=rand(51,200);
//nahodne generovani zelene slozky
$G=rand(51,200);
//nahodne generovani modre slozky
$B=rand(51,200);
$barva=imagecolorallocate($im, $R, $G, $B);

imagesetthickness($im, 30);
imageline($im, $bodY[$c], $vysledekY, $bodY[$c], $osay_y, $barva);
imagesetthickness($im, 2);
imagettftext ($im, 12, 0, $bodY[$c]-15, $vysledekY-10, $black, $font, $hodnoty[$c]);
}

Vytvoření os

Jestliže máte již vykresleny všechny sloupce, můžeme přejí k vykreslování jednotlivých os, jejich popisu a vytvoření nadpisu grafu. Osy je potřeba vytvořit až na samotném konci skriptu, protože pokud bychom je vytvořili hnedka na začátku, následné vykreslování sloupců by je překrylo – viz úvod článku.

/************************************************************/
/*      Tato cast musi byt az na konci celeho skriptu!      */
/************************************************************/

//nadpis grafu
imagettftext ($im, 20, 0, $osax_start-50, $osax_start-30, $black, $font, "Vzorový graf vytvořený v PHP");

//narysovani osy x
imageline($im, $osax_x, $osax_start, $osax_x, $osax_konec, $black);

//popisky osy x
for($d=1;$d<7;$d++) {
    $hodnota_osy=200*$d*$koef;
    imagettftext ($im, 12, 0, $osax_x-50, $bodX[$d]+6, $black, $font, $hodnota_osy);
}

//narysovani osy y
imageline($im, $osay_start, $osay_y, $osay_konec, $osay_y, $black);

//popisky osy y
for($e=1;$e<6;$e++) {
    imagettftext ($im, 12, 0, $bodY[$e]-30, $osay_y+20, $black, $font, "Sloupec ".$e);
}

Zakončení článku a skriptu

Celý tento článek by byl zbytečný, kdybych na konci neuvedl poslední tři funkce, které použijeme. Je to funkce header(), kdy browser informujeme o typu souboru, který chceme zobrazit, taky funkce imagejpeg(), kterou obrázek zobrazíme/uložíme. A jako poslední bude funkce imagedestroy() pro uvolnění paměti.

Popis funkce:
bool imagejpeg ( resource $obrazek [, string $soubor [, int $kvalita ]] )

obrazek → udává obrázek
soubor (nepovinné) → udává cestu k souboru, kam má být obrázek uložen. Není-li uvedena, obrázek se rovnou zobrazí.
kvalita (nepovinné) → udává kvalitu uloženého obrázku

Popis funkce:
bool imagedestroy ( resource $obrazek )

obrazek → udává obrázek, který má být vyhozen
Títmo se uvolní paměť.

//zobrazeni obrazku
header("Content-type: image/jpeg"); //oznameni browseru o typu obrazku - nesmi chybet!! 
imagejpeg($im); //vykresleni obrazku
imagedestroy($im); //uvolneni pameti

Zdrojový kód:

Stáhněte si ho, tento soubor si uložte na server a k němu do složky přidejte font, případně změňte cestu k fontu.

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
Autor vystudoval SPŠe ve Frenštátě pod Radhoštěm a to v oboru Automatizace. Po škole začal na plný úvazek pracovat pro firmu Siemens VDO jakožto technik výrobních prostředků. V současné době pracuje jakožto PLC Specialista ve firmě IMI Norgren CZ. Zvládá programování PLC od firem Mitsubishi, Omron a Beckhoff, ale autorovou nejsilnější stránkou jsou PLC SIEMENS. Dále se zajímá o identifikaci kusů ve výrobě, strojové vidění a průmyslovou komunikaci. Jeho zájmem v IT jsou PHP, HTML, CSS, JavaScript, RSS, MySQL, MS MQL, Visual Basic.NET, C# a ASP.NET. Mimo IT se zabývá historickým šermem a ohňovými efekty. Rád poslouchá starší skupiny jako třeba Scorpions, Queen, Def lepard, Kiss, Gun's roses a podobné "klasiky" ;-)
Web    

Nové články

Obrázek ke článku Stavebnice umělé inteligence 1

Stavebnice umělé inteligence 1

Článek popisuje první část stavebnice umělé inteligence. Obsahuje lineární a plošnou optimalizaci.  Demo verzi je možné použít pro výuku i zájmovou činnost. Profesionální verze je určena pro vývojáře, kteří chtějí integrovat popsané moduly do svých systémů.

Obrázek ke článku Hybridní inteligentní systémy 2

Hybridní inteligentní systémy 2

V technické praxi využíváme často kombinaci různých disciplín umělé inteligence a klasických výpočtů. Takovým systémům říkáme hybridní systémy. V tomto článku se zmíním o určitém typu hybridního systému, který je užitečný ve velmi složitých výrobních procesech.

Obrázek ke článku Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Vedení týmu v oboru informačních technologií se nijak zvlášť neliší od jiných oborů. Přesto však IT manažeři čelí výzvě v podobě velmi rychlého rozvoje a tím i rostoucími nároky na své lidi. Udržet pozornost, motivaci a efektivitu týmu vyžaduje opravdu pevné manažerské základy a zároveň otevřenost a flexibilitu pro stále nové výzvy.

Obrázek ke článku Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Za poslední rok se podoba práce zaměstnanců změnila k nepoznání. Především plošné zavedení home office, které mělo být zpočátku jen dočasným opatřením, je pro mnohé už více než rok každodenní realitou. Co ale dělat, když se při práci z domova ztrácí motivace, zaměstnanci přestávají komunikovat a dříve fungující tým se rozpadá na skupinu solitérů? Odborníci na personalistiku dali dohromady několik rad, jak udržet tým v chodu, i když pracovní podmínky nejsou ideální.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý