Utility a widgety pro práci s grafikou v knihovně JAK
Na této stránce jsou zobrazeny ukázky využití utilit a widgetů pro práci s grafikou ve stránkách při použití knihovny JAK.
Plátno SVG a VML
Čím se internetové aplikace zesložiťují, tím častěji je nutné vizualizovat data jinak než textovou reprezentací. Pokud jsou data často měněny, není vhodné je vizualizovat na straně serveru a pak přenášet ke klientovi jako výsledný obrázek, ale je daleko lepší tyto data vizualizovat na klientovi přímo. Většinou se jedná o různé grafy, ale zobrazovat můžeme např. trasu na mapě, nebo graf reprezentující síť, aj.
Pro vizualizaci jsme použili standard SVG a pro Internet Explorer je použita technologie VML. Tyto technologie jsou reprezentovány soubory svg.js a vml.js a funkčnost v nich obsažená je definována rozhraním v souboru vector.js (SZN.Vector.Canvas). V SZN.Vector je také jedna statická metoda SZN.Vector.getCanvas(), která přejímá jako parametry rozměry plátna a vrací reprezentaci plátna (SVG nebo VML element) s ohledem na prohlížeč.
Pro použití VML v Internet Exploreru musí stránka definovat VML jmenný prostor a také defaultní VML styl. Bohužel tyto údaje jsou závislé na verzi prohlížeče a proto nedoporučujeme nastavovat jmené prostor a styl ručně. O přidání správných hodnot do stránky se postará přímo knihovna.
Po vytvoření plátna můžeme do něj začít kreslit jednotlivá primitiva pomocí metod definovaných v rozhranní SZN.Vector.Canvas. Ukažme si příklad:
var canvas = SZN.Vector.getCanvas(100,100);
SZN.gEl('canvas1').appendChild(canvas.getContainer());
var circle = new SZN.Vector.Circle(canvas, new SZN.Vec2d(50,50), 20, {color: '#ff0000'});
var circle1 = new SZN.Vector.Circle(canvas, new SZN.Vec2d(50,75), 20, {color: '#ff00ff', opacity: 0.7});
var circle2 = new SZN.Vector.Circle(canvas, new SZN.Vec2d(75,50), 20, {color: '#ff00ff', opacity: 0.7});
var circle3 = new SZN.Vector.Circle(canvas, new SZN.Vec2d(25,50), 20, {color: '#ff00ff', opacity: 0.7});
var circle4 = new SZN.Vector.Circle(canvas, new SZN.Vec2d(50,25), 20, {color: '#ff00ff', opacity: 0.7});
V příkladu je vidět na prvních dvou řádcích vytvoření plátna a jeho připnutí do dokumentu. Na obrázku je vykresleno 5 kruhů. Vše co je možno vykreslit je definováno ve jmeném prostoru SZN.Vector jako třídy:
- Path - obecný element, který je definován SVG formátovacím řetězcem. Podporováno je vykreslení Bézierovy křivky, lomené čáry a eliptického úseku.
- Circle - element pro tvorbu kružnice. Nastavuje se střed (viz. příklad), poloměr a vzhled
- Polygon - element vykresluje mnohoúhelník. Nastavuje se pole bodů a vzhled
- Line - čára. Nastavuje se pole bodů a vzhled. Pokud se v objektu popisující vzhled nastaví vlastnost curvature na číslo větší než 0, pak je čára tvořena Bézierovou křivkou.
Prvním parametrem konstruktoru každé z tříd primitiv je reference na vytvořené plátno. V dalším příkladu zobrazíme polygon (trojúhelník) a čáru u které půjde měnit dynamicky křivost.
var canvas = SZN.Vector.getCanvas(150,150);
SZN.gEl('canvas2').appendChild(canvas.getContainer());
//vykresleni cerveneho trojuhelniku
var polygon = new SZN.Vector.Polygon(canvas,
[ new SZN.Vec2d(10,10),
new SZN.Vec2d(10,70),
new SZN.Vec2d(40,70)
],
{color: '#bb3333', outlineColor: '#ff0000', outlineWidth: 2}
);
var line = new SZN.Vector.Line(canvas,
[ new SZN.Vec2d(120,100),
new SZN.Vec2d(120,50),
new SZN.Vec2d(80, 50),
new SZN.Vec2d(55, 75),
new SZN.Vec2d(80,100),
new SZN.Vec2d(120,100)
],
{title: 'šipka', color: '#00dd00', outlineWidth: 2}
);
Výběrem stupně zakřivení bude měnit zelená šipka svůj tvar.
Při vytváření křivek, nebo definování středu kruhu, definujeme body pomocí SZN.Vec2d třídy. V souboru geometry.js jsou definovány třídy, které popisují vektory v N rozměrném prostoru:
- SZN.VecNd - n-rozměrný vektor, obsahuje metody:
- dot - pro skalární součin vektorů
- multiply - pro vektorový součin
- unit - pro vytvoření jednotkového vektoru
- plus - pro sčítání vektorrů
- minus - pro odečítání vektorů
- norm - pro vrácení normy vektoru (výchozí je Euklidovská)
- SZN.Vec2d - dvourozměrný vektor, specializace n-rozměrného vektoru, obsahuje navíc metody:
- normal - pro vrácení normály
- symmetry - pro zrcadlení vektoru dle zadané osy
Volitelné parametry tříd Circle, Line, Polygon a Path
Jak bylo zmíněno výše, prvním parametrem konstruktoru všech těchto tříd je reference na objekt vektorového plátna. Další parametry se již liší třída od třídy.
Circle
Třída Circle vyžaduje tyto parametry:
- canvas - reference na objekt plátna
- center - objekt středu, instance SZN.Vec2d
- radius - poloměr zakřivení v px
- options - volitelný parametr s dalšími vlastnostmi
Parametr options můžeme ovlivnit tyto vlastnosti instance třídy SZN.Vector.Circle:
- color - barva výplně, výchozí barva je průhledná [""]
- outlineColor - barva kružnice, výchozí barva je černá [#000]
- outlineOpacity - průhlednost kružnice, hodnoty jsou od 0 do 1, kdy 1 je plně neprůhledná [1]
- outlineWidth - tloušťka vykreslené kružnice v px [1]
- title - zobrazený titulek v bublině po najetí myší nad element, výchozí je prázný [""]
Line
Třída Line vyžaduje tyto parametry:
- canvas - reference na objekt plátna
- points - pole bodů (instancí SZN.Vec2d)
- options - volitelný parametr s dalšími vlastnostmi
Parametr options můžeme ovlivnit tyto vlastnosti instance třídy SZN.Vector.Line:
- width - tloušťka čáry v px [1]
- curvature - zakřivení čáry, pokud je 0, kreslíme mezi body úsečky, jinak bezierovu křivku [0]
- opacity - průhlednost čáry, nabývá hodnot mezi 0 a 1, kdy 1 je čára neprůhledná [1]
- color - barva čáry, výchozí barva je černá [#000]
- outlineWidth - tloušťka vytažení (obrysu) čáry v px, ve výchozím stavu, nemá čára žádné vytažení [0]
- outlineColor - barva vytažení, výchozí barva je bílá [#fff]
- outlineOpacity - průhlednost vytažení čáry, definováno v rozmezí 0 a 1, výchozí hodnota je [1]
- symmetricCP - boolean hodnota určující zda se mají kontrolní body pro zakřivení bezierovou křivkou počítat symetricky [true]
- title - zobrazený titulek v bublině po najetí myší nad element, výchozí je prázný [""]
Při kreslení zakřivené čáry (curvature > 0) je možné si vybrat parametrem symetricCP metodu, kterou budou počítány kontrolní body křivky. Ve výchozím nastavení jsou kontrolní body vypočítávány symetricky kolem prostředního bodu:
var canvas = SZN.Vector.getCanvas(200,200);
SZN.gEl('controlPoints1').appendChild(canvas.getContainer());
var points = [ new SZN.Vec2d(40,40),
new SZN.Vec2d(150,100),
new SZN.Vec2d(100, 160) ];
var line = new SZN.Vector.Line(canvas,
points,
{title: 'Čára', color: '#00dd00', outlineWidth: 3, curvature: 30}
);
Hodnota curvature udává 1/2 vzdálenosti kontrolních bodů od středového bodu křivky. Kontrolní body jsou umístěny na úsečce rovnoběžné se spojnicí počátečního a koncového bodu. Body křivky jsou červené a kontrolní body zelené. Kontrolní body u počátečního a koncového bodu jsou umístěny na spojnici tohoto bodu s bodem středovým. To zajišťuje přimykání křivky k této spojnici.
Pro volbu symetricCP = false neudává parametr curvature vzdálenost kontrolních bodů od prostředního bodu křivky, ale poměrnou vzdálenost krajního bodu křivky k prostřednímu bodu. Tedy vzdálenost krajního bodu k prostřednímu na té straně, na které je kontrolní bod vykreslen, je přenásobena procentním koeficientem a výsledek je vzdálenost kontrolního bodu od středního budu křivky. Kontrolní body opět leží na rovnoběžce se spojnicí počátečního a koncového bodu křivky.
var canvas = SZN.Vector.getCanvas(200,200);
SZN.gEl('controlPoints1').appendChild(canvas.getContainer());
var points = [ new SZN.Vec2d(40,40),
new SZN.Vec2d(150,100),
new SZN.Vec2d(100, 160) ];
var line = new SZN.Vector.Line(canvas,
points,
{title: 'Čára', color: '#00dd00', outlineWidth: 3, curvature: 30, symetricCP: false}
);
Polygon
Třída Polygon vyžaduje tyto parametry:
- canvas - reference na objekt plátna
- points - pole bodů (instancí SZN.Vec2d)
- options - volitelný parametr s dalšími vlastnostmi
Parametr options můžeme ovlivnit tyto vlastnosti instance třídy SZN.Vector.Polygon:
- curvature - zakřivení čáry ohraničující mnohoúhelník, pokud je 0, kreslíme mezi body úsečky, jinak bezierovu křivku [0]
- opacity - průhlednost výplně mnohoúhelníku, nabývá hodnot mezi 0 a 1, kdy 1 značí neprůhlednost [1]
- color - barva výplně, výchozí barva je černá [#000]
- outlineWidth - tloušťka vytažení (obrysu) v px, ve výchozím stavu, nemá mnohoúhelník žádné vytažení [0]
- outlineColor - barva vytažení, výchozí barva je bílá [#fff]
- outlineOpacity - průhlednost vytažení čáry, definováno v rozmezí 0 a 1, výchozí hodnota je [1]
- symmetricCP - boolean hodnota určující zda se mají kontrolní body pro zakřivení bezierovou křivkou počítat symetricky [true]
- title - zobrazený titulek v bublině po najetí myší nad element, výchozí je prázný [""]
Path
Třída Path vyžaduje tyto parametry:
- canvas - reference na objekt plátna
- format - formátovací řetězec dle SVG
- options - volitelný parametr s dalšími vlastnostmi
Parametr options můžeme ovlivnit tyto vlastnosti instance třídy SZN.Vector.Path:
- color - barva čáry, výchozí hodnotou je žádná barva ["none"]
- opacity - průhlednost čáry, definováno v rozmezí 0 a 1, kdy 1 je neprůhledná čára [1]
- width - šířka čáry v px [0]
- outlineColor - barva obrysu (obtažení) čáry, výchozí hodnotou je černá barva [#fff]
- outlineOpacity - průhlednost obrysu, definováno v rozmezí 0 a 1, kdy 1 je neprůhledná čára [1]
- outlineWidth - šířka obrysu v px [1]
- title - zobrazený titulek v bublině po najetí myší nad element, výchozí je prázný [""]
- jak.js
Stáhnout skripty pro práci s plátnem vector.zip.
Grafy
Kreslení čar a objektů je jen předzvěst větších widgetů a to widgetů pro kreslení koláčového grafu a čárového/sloupcového grafu. Pro kreslení grafu je potřeba načíst skripty pro práci s plátnem a dále soubor se skriptem grafu (piechart.js, lbchart.js).
Pro vykreslení grafu musíme zabezpečit element, který bude mít definovány rozměry, do kterého bude graf vykreslen a data. První ukázka je koláčový graf:
var piechart = new SZN.PieChart('pieChartDiv', [
{label: 'IE', data: 74},
{label: 'Firefox', data: 23},
{label: 'Opera', data: 2},
{label: 'Ostatní', data: 1}
]);
Vzhled grafu lze ovlivnit třetím parametrem, kterým je konfigurační objekt. Ovlivnitelné vlastnosti jsou:
- padding - padding ve vymezeném prostoru rodičovského prvku
- depth - v pixelech udaná výška koláče
- skew - číslo mezi 0 a 1 určuje zkosení grafu (při skew=1 a depth=0 je graf 2D)
- legend - boolean/string hodnota určující zda a kde bude zobrazena legenda [false|left|right|top|bottom]
- legendWidth - rozměr v pixelech, určující velikost strany barevného čtverečku kresleného v legendě
- labelDistance - vzálenost v px popisku výseče od grafu, výchozí hodnota je 20
- legendDistance - vzálenost v px legendy od grafu, výchozí hodnota je 15
- prefix - řetězec, který bude vypisován před číselné hodnoty
- sufix - řetězec, který bude vypisován za číselné hodnoty (např. znak měny)
- colors - pole řetězců barev, které se budou periodicky opakovat při kreslení grafu
- outlineColor - vlastnost předdefinovávající barvu rámečku grafu a legendy (černá). Vlastnost je objekt s vlastnostmi legend a graph. Pokud předdefinováváme, je nutné zadat obě.
Pokud chceme vykreslovat 2D graf zobrazující např. z čeho se skládá cena 1l benzínu, který stojí 30,50 Kč, nakonfigurujeme graf takto:
var piechart = new SZN.PieChart('pieChartDiv2',
[{label: 'Cena bez daní', data: 13.79},
{label: 'DPH 19%', data: 4.87 },
{label: 'Spotřební daň', data: 11.84}],
{depth:0, skew:1, suffix:" Kč", legendWidth:20, legend: 'bottom', padding: 10, legendDistance: 35, labelDistance:28});
Ovlivnit vzhled textů v legendě a v popiscích výsečí jde pomocí CSS tříd, které jsou jim přiřazeny. Tyto třídy jsou legend a label.
Vytvoření sloupcového nebo čárového grafu je stejně snadné jako grafu koláčového. Jediný rozdíl je v tom, že lze předat více řad hodnot a navíc předáváme hodnoty pro osu X:
var lbchart = new SZN.LBChart('lbChart',
[ {label: "Nezaměstnanost", data: [6,4,5]},
{label: "Růst DPH", data: [2.8, 3.2, 4.8] }
],
/*popisky osy X*/
['2005','2006','2007']);
Samozřejmě lze graf konfigurovat. Popisky osy X lze předávat pomocí konfiguračního objektu, kde kromě vlastního popisku můžeme definovat barvu a tloušťku svislé čáry. Na následujícím grafu zobrazíme svislou mřížku:
var lbchart = new SZN.LBChart('lbChart',
[ {label: "Nezaměstnanost", data: [6,4,5]},
{label: "Růst DPH", data: [2.8, 3.2, 4.8] }
],
/*popisky osy X*/
[ {label:'2005', color: '#000', width: '0px'},
{label:'2006', color: '#000', width: '1px'},
{label:'2007', color: '#000', width: '1px'}
]);
Dále bychom mohli chtít vykreslit některé sloupce sloupcovým grafem. Pak stačí do definice řady přidat vlastnost type s hodnotou bar. Dále lze u čárových řad (type = line) přidávat značky, jakou budou vykresleny body a to tak, že do definice řady přidáme vlastnost marker. Tato vlastnost musí obsahovat konstrukor dané značky a na výběr jsou třídy definované v souboru lbchart.js, popřípadě vlastní:
- SZN.Marker.Circle - vybarvené kolečko
- SZN.Marker.Square - vybarvený čtvereček
- SZN.Marker.Triangle - vybarvený trojúhelník
- SZN.Marker.Plus - znak plus +
- SZN.Marker.Cross - znak křížku ×
Většina nastavení grafu ohledně paddingu a legendy je shodná s koláčovým grafem. Přibyly navíc tyto vlastnosti:
- rows - konfigurační objekt s vlastnostmi:
- count - počet řádek (hodnot na svislé ose), který by měl generátor grafu optimálně vykreslit
- color - barva vodorovných řádek
- rowColor - barva vodorovných řádek
- markerSize - velikost v px, udávající velikost obsaného čtverce do kterého je umístěna značka hodnoty
- barWidth - šířka jednoho sloupce při kreslení sloupcového grafu
- outlineWidth - tloušťka ohraničující čáry sloupců sloupcového grafu
- lineWidth - tloušťka čáry čárového grafu
- labels - pole s hodnotami pro osu X
- zero - boolean hodnota, která určuje zda graf bude zobrazovat nulovou hodnotu
- merge - boolean hodnota, která určuje zda se mohou sloupce vykreslovat přes sebe
- axes - konfigurační objekt s vlastnostmi:
- draw - boolean hodnota, která určuje zda se mají vykreslit osy.
- color - určuje barvu os
- colors - pole s hodnotami barev, které budou využity pro jednotlivé datové řady
- pointer - boolean hodnota, která určuje, zda bude zobrazena pod kurzorem svislá čára pro snadnější odečítání hodnot (false)
- legend - konfigurační objekt s vlastnostmi:
- draw - boolean/string hodnota určující zda a kde bude zobrazena legenda [false|left|right|top|bottom]
- width - šířka prvků legendy
- barMinSize - minimální výška sloupce v px, všem sloupcům je tato výška přičtena
- min - minimální hodnota na ose Y
- max - maximální hodnota na ose Y
Při vykreslení grafu je nejdříve vykreslena legenda a poté do zbylého místa graf. Ve výchozím nastavení je rozdíl minimální a maximální vykreslované hodnoty podělen výškou vymezeného prostoru a tím je získán krok pro vykreslení počtu vodorovných čar rows. Nicméně pokud jsou data plochá, algoritmus se tímto nastavením nemusí řídit. Důležitým nastavením je vlastnost zero. Pokud máme hodnoty např. mezi 10 až 100, tak při automatickém nastavení graf nevykreslí nulovou hodnotu. Pak je nutné nastavit zero na true, abychom vykreslovali graf mezi hodnotami 0 až 100.
Níže vykreslený graf je vytvořen tímto nastavením:
var labels = [2000,2001,2002,2003,2004,2005,2006,2007];
//nastaveni dat, kde d1 az d5 jsou pole s daty
var data = [
{
data:d1,
label:"leonard",
type:"bar"
},
{
data:d2,
label:"sheldon",
type:"bar"
},
{
data:d3,
label:"howard",
type:"line",
marker: SZN.Marker.Circle
},
{
data:d4,
label:"rajesh",
type:"bar"
},
{
data:d5,
label:"penny",
type:"bar"
}
];
//nastaveni grafu
var o = {
barWidth: 10,
lineWidth: 3,
outlineWidth: 1,
min: 0,
max: 130,
rows: {count: 10}
};
//vytvoreni grafu
window.l = new SZN.LBChart("lbChart", data, labels, o);
Požadované knihovny:
- jak.js
- vector.js
- vml.js
- svg.js
- geometry.js
Stáhnout skripty pro tvorbu grafů charts.zip.
Animace CSS parametrů
Velice často se v internetových aplikacích používá animace CSS vlastnosti, aby aplikace vypadala více dynamická. Často jsou animovány průhlednosti boxů, nebo jejich pozice pro jejich objevování a mizení. Ve všech popsaných widgetech jsme se bez animací obešli, a pokud byly použity (widget pro řazení), pak jsou přímo naprogramovány ve widgetu. Vlastní animace je trochu magie, neboť je masivně využíváná funkce setInterval a dále je vhodné jednoduše umožnit animaci různými křivkami - lineárně, po sinusovce, atd.
Pokud z vlastní animace extrahujeme nosnou myšlenku, jde vlastně o interpolaci vlastnosti v čase mezi mezními hodnotami. Interpolace je prováděna podle předem zadané funkce.
V souboru interpolator.js jsou definovány dvě třídy:
- SZN.Interpolator - obecná třída, umožňující interpovaci libovolného intervalu dle zvolené funkce s voláním návratové hodnoty.
- SZN.CSSInterpolator - specializovaná třída, která se stará o interpolaci CSS vlastností
Ve většině případů budeme animovat CSS vlastnosti, proto se zaměříme na CSS interpolátor. Jeho konstruktor vyžaduje tři parametry. Prvním je element, který bude animován, druhým parametrem je doba v ms, po kterou má animace trvat, a třetím je konfigurační literálový objekt s volitelnými parametry pro nastavení animace:
- frequency - čas v ms, který je mezi jednotlivými kroky animace.
- interpolation - číselná hodnota určující typ interpolační funkce. Lze volit pomocí konstant:
- SZN.Interpolator.LINEAR - lineární interpolace
- SZN.Interpolator.QUADRATIC - interpolace dle kvadratické funkce x2
- SZN.Interpolator.SQRT - linterpolace dle odmocninové funkce x1/2
- SZN.Interpolator.SIN - interpolace po sinusovce
- SZN.Interpolator.ASIN - interpolace po arcussinus
Dále je důležitá metoda addProperty, které předáváme název CSS vlastnosti, počáteční a koncovou hodnotu a případnou jednotku. Kód níže zobrazí po kliknutí na skrytý ostavec s textem.
//zobrazeni odstavce
var i = new SZN.CSSInterpolator(SZN.gEl('hiddenParagraph'), 1000, {});
i.addProperty('height', 0, 87, 'px');
i.start();
Samozřejmě po jeden časový úsek (jednu instanci interpolátoru) mužeme animovat více CSS vlastností najednou. Po stisknutí se objeví odstavec textu a bude podbarven žlutě, po čase bude spuštěn druhý interpolátor, který podbarvení zruší.
function showParagraph2() {
var i = new SZN.CSSInterpolator(SZN.gEl('hiddenParagraph2'), 700, {endCallback: ligheBackground});
i.addProperty('height', 0, 87, 'px');
i.addColorProperty('backgroundColor', '#ffffff', '#ffff00');
i.start();
SZN.gEl('showText2').disabled = true;
}
function ligheBackground() {
var i = new SZN.CSSInterpolator(SZN.gEl('hiddenParagraph2'), 500, {endCallback: fadeBackground});
i.addColorProperty('backgroundColor', '#ffff00', '#ffff77');
setTimeout(function(){i.start()}, 500);
}
function fadeBackground() {
var i = new SZN.CSSInterpolator(SZN.gEl('hiddenParagraph2'), 700);
i.addColorProperty('backgroundColor', '#ffff77', '#ffffff');
setTimeout(function(){i.start()}, 2000);
}
Požadované knihovny:
- jak.js
Stáhnout skripty pro tvorbu animací interpolators.zip.
