Vytváření obrázkových grafů pomocí PHP 2.

    0

    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ý:

    <IMG SRC=“graf.php“>

    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.

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

    Odpovědět