Sloupcový graf skládaný

Sloupcový graf se někdy skládá z částí. Zatímco celková výška sloupce udává trend, výška jednotlivých částí sloupce (obvykle barevně odlišené) udávají podíl jeho složek. Např. trend prodeje a podíl regionů, nebo značek.

Pro tento článek si zvolíme příklad z ukázky Protokoly výroby (střední, dolní část obrázku). Graf nezobrazuje trend, ale počet dobrých a vadných kusů přepočtený na odpovídající čas a čas prostoje. Zelená část sloupce označuje dobu kdy se vyráběly dobré kusy, žlutá kusy vadné a oranžová je doba prostoje. Součet těchto časů by měl být 24 hodin. Cílem grafu je rychlá kontrola správnosti vložených údajů: počet dobrých a vadných kusů, takt linky a doba prostojů. To vše za tři směny. Jakákoli chyba zadaných údajů je okamžitě viditelná.

Hodnoty grafu jsou z reálného měsíčního grafu, zkráceného na 14 dní, obrázky pro kreslení sloupců jsou vypůjčeny z aplikace Spotřeba surovin.

24 h
16 h
8 h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
 dobré
 vadné
 prostoje

Pro kreslení skládaného grafu budeme potřebovat několik obrázků. Obrázek pozadí grafu je připraven včetně čar měřítka a tmavší části pro legendu. Jeho součástí může být i popis stupnice pokud se smíříme s horší kvalitou při tisku.

Různobarevné obrázky pro sloupce si připravíme podle potřeby. Šířku zvolíme podle skutečné šířky sloupce, výšku budeme měnit proto se zdá nepodstatná. V praxi jsem měl problémy s kreslením vysokých sloupců, které měly původní výšku menší než 8 pixelů. Proto připravuji obrázky pro sloupce s výškou min. 16 pixelů.


<style type="text/css">
/* graph bar: container, graph bar, holiday, workday */
.C {position: relative; width: 23px; left: 0; top:0; height:205px; float:left;}
.H {position: absolute; width: 20px; left: 0; z-index: 1;}
.DH, .DW {position: absolute; width: 20px; left: 0; top: 289px;
          z-index: 2; text-align: center;}
.DH {background: #fdd;}
.DW {background: #ddd;}

/* Y-axis description */
.Y {position: relative; left: 6px;}

/* legend below graph: text, image */
.Lt {position: relative; top: 0; left: 0; width:  92px; height: 16px;
     border: 0; float: left;}
.Li {width: 20px; height: 12px; border: 0;}
</style>

<body>

<div style="position: relative; width: 364px; height: 330px;">
<img style="position: absolute; width: 364px; height: 330px; top: 0; left: 0; 
  z-index: 0;" src="card.png">

<div class="C" style="width: 38px;">
<div class="Y" style="top: 26px;">24 h</div>
<div class="Y" style="top: 96px;">16 h</div>
<div class="Y" style="top:166px;"> 8 h</div>
</div>
...
<div class="C">
<img class="H" style="top: 57px; height: 229px;" src="barGreen.png">
<img class="H" style="top: 35px; height: 22px;" src="barYellow.png">
<div class="DH">2</div>
</div>

<div class="C">
<img class="H" style="top: 106px; height: 180px;" src="barGreen.png">
<img class="H" style="top:  98px; height:  8px;" src="barYellow.png">
<img class="H" style="top:  31px; height: 67px;" src="barOrange.png">
<div class="DW">3</div>
</div>
...

<div class="Lt" style='width: 36px;'>&nbsp;</div>
<div class="Lt"><img class="Li" src="barGreen.png">dobré</div>
<div class="Lt"><img class="Li" src="barYellow.png">vadné</div>
<div class="Lt"><img class="Li" src="barOrange.png">prostoje</div>

</div>

</body>

V sekci CSS definujeme třídy pro kreslení grafu. Třída .C je kontejner pro kreslení sloupců a kalendáře pod grafem. Má pozici relative, abychom uvnitř kontejneru mohli pozicovat prvky jako absolute. Třída .H slouží pro kreslení jednotlivých částí sloupců. Třídy .DH a .DW jsou pro vykresování datumu. Liší se barvou pozadí pro pracovní dny (DW) a dny volna (DH). Dále budeme potřebovat třídu pro popis stupnice (třída Y) a třídy pro legendu, která je umístěna pod grafem (Lt, Li).

HTML kód. Oblast grafu je vymezena tágem <div ...>, kterému je přiřazen inline styl a slouží jako kontejner pro celý graf. Následuje obrázek pozadí grafu (card), který má stejné rozměry jako kontejner grafu. Nyní již můžeme kreslit máš graf. Nejdříve vykreslíme popis osy Y. Do lokálního kontejneru třídy C umístíme 3 prvky div s popisem stupnice, každý prvek má stanovenu pozici top tak, aby text byl vykreslen vedle čáry z pozadí obrázku.

Ve výpisu HTML kódu je uveden jen 2. a 3. sloupec. Každý sloupec je uzavřen do lokálního kontejneru C, který "uplave vlevo" díky stylu float: left a kontejnery se řadí za sebou dokud nevyplní celou šířku vnějšího kontejneru grafu. Uvnitř lokálního kontejneru vykreslujeme jednotlivé sloupce grafu pozicované absloutně. Každému dílčímu sloupci musíme přiřadit vypočtené pozice top a height.

Pokud vychází nulová výška některého dílčího sloupce, tuto část HTML kódu vynecháme. Některé browsery totiž obrázky s výškou 0 pixelů vykreslí jako obrázek výšky 1 pixel. Poslední řádek uvnitř lokálního kontejneru je datum. Měli bychom rozhodnout, zda je pracovní, nebo volný den a podle toho nastavit odpovídající CSS třídu. Z datumu se zde vypisuje jen den. Měsíc a rok je uveden někde v nadpisu.

Nakonec vykreslíme legendu. Protože šířka vnějšího kontejneru je již vyčerpaná, můžeme použít pro prvky legendy pozicování relative. Tyto prvky se budou kreslit pod horní řadu sloupců a datumů. Pokud horní řada má proměnný celkový počet sloupců (dny v měsíci), můžeme se dostat do problémů. Pak totiž nemusí být vyčerpaná šířka vnějšího kontejneru a legenda se začne vykreslovat do horní řady. Řešení bude doplnit horní řadu do plné šířky vnějšího kontejneru, nebo použít pozicování absolute pro třídu Lt.

updated 18.05.2006