Grafy v ASP.NET – koláče
V předchozím článku o grafech v ASP.NET jsem vám ukázal jak lze vytvořit čárové grafy. Dnes se dozvíte jak podobným způsobem vytvořit graf koláčový.
Pro příklad (zdrojový kód) jsem zvolil jako datový zdroj ankety na Intervalu, které se pravidelně obměňují na hlavní stránce. Jak udělat takovouto anketu (ovšem pouze v klasickém ASP) jste si měli možnost přečíst v seriálu článků Anketa krok za krokem (1, 2, 3,). Jak si můžete všimnout, je v příkladu zobrazeno pomocí jednoho ASPX několik grafů. Údaje pro grafy jsou vybírány z databáze na základě parametru idankety
. Vstupní parametr je ošetřen tak, aby nemohl obsahovat nic jiného než číslo.
Povšimněte si také způsobu předání parametru do SQL dotazu. Tento způsob je přehledný a minimalizuje možnost podvržení nesprávných parametrů. Pokud chcete použít v SQL dotazu parametr, záleží na tom, zda použijete OleDbCommand nebo SqlCommand. Bohužel každý z těchto zprostředkovatelů dat vyžaduje jiný způsob zápisu parametrů. Zatímco OleDbCommand vyžaduje pro označení parametru ? (otazník), SqlCommand používá pojmenované parametry, kde jméno parametru začíná znakem @ (zavináč). Zápis parametrů pro SQLCommand bude vypadat takto:
SqlCommand cmd=new SqlCommand(„SELECT SUM(redaction_anketa_odpovedi.hlasy)
AS celkem, redaction_anketa_otazky.Otazka FROM redaction_anketa_odpovedi
INNER JOIN redaction_anketa_otazky ON redaction_anketa_odpovedi.idankety =
redaction_anketa_otazky.id GROUP BY redaction_anketa_otazky.id, redaction_anketa_otazky.Otazka
HAVING (redaction_anketa_otazky.id = @idanketa) SELECT odpoved, hlasy FROM
redaction_anketa_odpovedi
WHERE (idankety = @idanketa) ORDER BY hlasy DESC“,conn);
cmd.Parameters.Add(„@idanketa“,idankety);
SqlDataReader rdr=cmd.ExecuteReader();
rdr.Read();
A pro OleDbCommand provedeme zápis tímto způsobem:
OleDbCommand cmd=new OleDbCommand(„SELECT SUM(redaction_anketa_odpovedi.hlasy)
AS celkem, redaction_anketa_otazky.Otazka FROM redaction_anketa_odpovedi
INNER JOIN redaction_anketa_otazky ON redaction_anketa_odpovedi.idankety =
redaction_anketa_otazky.id GROUP BY redaction_anketa_otazky.id, redaction_anketa_otazky.Otazka
HAVING (redaction_anketa_otazky.id = ?) SELECT odpoved, hlasy FROM redaction_anketa_odpovedi
WHERE (idankety = ?) ORDER BY hlasy DESC“,conn);
cmd.Parameters.Add(„redaction_anketa_otazky.id“,idankety);
cmd.Parameters.Add(„idankety“,idankety);
OleDbDataReader rdr=cmd.ExecuteReader();
Stejně jako v minulém článku používám dva SQL dotazy, pomocí kterých dostanu dvě sady záznamů. Všimněte si, že ačkoliv používám jen jeden parametr idankety
, v zápise pro OleDbCommand mám použity dva parametry jiného jména, kdežto v zápise pro SqlCommand si parametr pojmenuji a nadále pak používám jeden jediný.
Po „malém výletu“ do ADO.NET se vrátíme opět k tvorbě grafu. Základním „stavebním“ kamenem bude metoda FillPie třídy Graphics (vyplněná kruhová výseč). Metoda FillPie má tři různé způsoby zápisu parametrů a v příkladě je použit tento:
public void FillPie(
Brush brush,
float x,
float y,
float width,
float height,
float startAngle,
float sweepAngle
);
Parametr Brush určuje typ výplně, která bude použita pro vyplnění výseče – x,y určuje souřadnice levého horního rohu čtverce (či obélníku) opsaného útvaru, ze kterého se vykresluje výseč, width,height určuje velikost objektu (pokud nejsou shodné, bude se vykreslovat výseč elipsy), startAngle určuje počáteční úhel vykreslované výseče (úhel se bere od osy x – „tři hodiny“ – ve směru hodinových ručiček), sweepAngle určuje úhel vykreslované výseče (opět ve směru hodinových ručiček). Úhly se zadávají ve stupních a při výpočtu doporučuji počítat s datovým typem float a nepoužít metodu FillPie s parametry typu int, nýbrž s typem float. Důvodem je skutečnost, že by při výpočtu v oboru čísel int došlo k velké nepřesnosti a vykreslené výseče by neuzavřely kruh.
private void Page_Load(object sender, System.EventArgs e)
{
int idankety=0;
string ErrorText=““;
try
{
idankety=Convert.ToInt16(Request.QueryString.GetValues(„idankety“)[0]);
}
catch
{
ErrorText=“Chybný parametr“;
}
// vytvoření „obrázku“
const int width = 400, height = 400;
Bitmap objBitmap = new Bitmap(width, height);
Graphics objGraphics = Graphics.FromImage(objBitmap);
// ramecek kolem grafu
objGraphics.FillRectangle(new LinearGradientBrush(new Point(10,10),
new Point(100,100),Color.Red,Color.Blue), 0, 0, width, height);
// pozadi grafu
objGraphics.FillRectangle(new SolidBrush(Color.White), 2, 2, width – 4, height – 4);
// Nastavíme font pro popis
Font fontPopis = new Font(„Times New Roman“, 12, FontStyle.Bold);
// Nastavíme formátování textu
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
try
{
// připojovací řetězec do SQL serveru
const string sqlConnectionString=“Data Source=localhost;User ID=sa;Password=asdf;Initial Catalog=INTERVAL;“;
// Vytvoření spojení do databáze
SqlConnection conn=new SqlConnection(sqlConnectionString);
conn.Open();
// provedení výběru da
SqlCommand cmd=new SqlCommand(„SELECT SUM(redaction_anketa_odpovedi.hlasy)
AS celkem,redaction_anketa_otazky.Otazka FROM redaction_anketa_odpovedi
INNER JOIN redaction_anketa_otazky ON redaction_anketa_odpovedi.idankety =
redaction_anketa_otazky.id GROUP BY redaction_anketa_otazky.id, redaction_anketa_otazky.Otazka
HAVING (redaction_anketa_otazky.id = @idanketa) SELECT odpoved, hlasy FROM
redaction_anketa_odpovedi
WHERE (idankety = @idanketa) ORDER BY hlasy DESC“,conn);
cmd.Parameters.Add(„@idanketa“,idankety);
SqlDataReader rdr=cmd.ExecuteReader();
rdr.Read();
objGraphics.DrawString(rdr[„Otazka“].ToString(), fontPopis, new SolidBrush(Color.Black),
new Rectangle(5,5,390,40),stringFormat);
float jedenstupen= 360.0F/float.Parse(rdr[„celkem“].ToString());
rdr.NextResult();
float celkovyuhel=0.0F;
float uheldilku;
int polozka=0;
Font fontPopisOdpoved = new Font(„Times New Roman“, 10, FontStyle.Bold);
// Nastavíme formátování textu
StringFormat stringFormatOdpoved = new StringFormat();
stringFormatOdpoved.Alignment = StringAlignment.Near;
stringFormatOdpoved.LineAlignment = StringAlignment.Far;
Color Barva;
int posunx,posuny;
while(rdr.Read())
{
uheldilku= float.Parse(rdr[„hlasy“].ToString())*jedenstupen;
// predvoleni barvy vyplne
switch(polozka)
{
case 0: Barva=Color.FromArgb(153,51,102);break;
case 1: Barva=Color.FromArgb(102,0,102);break;
case 2: Barva=Color.FromArgb(0,102,204);break;
case 3: Barva=Color.FromArgb(153,153,255);break;
case 4: Barva=Color.FromArgb(0,204,45);break;
default: Barva=Color.Black;break;
}
// prvni vysec bude posuna ven ze stredu
if (polozka==0)
{
posunx=10;
posuny=10;
}
else
{
posunx=0;
posuny=0;
}
objGraphics.FillPie(new SolidBrush(Barva),60+posunx,50+posuny,220,220,celkovyuhel,uheldilku);
celkovyuhel=celkovyuhel+uheldilku;
// vypis legendy
objGraphics.DrawString(rdr[„hlasy“].ToString(), fontPopisOdpoved, new SolidBrush(Barva),
new Rectangle(5, 280+(15*polozka),390,20),stringFormatOdpoved);
objGraphics.DrawString(rdr[„odpoved“].ToString(), fontPopisOdpoved, new SolidBrush(Barva),
new Rectangle(35, 280+(15*polozka),390,20),stringFormatOdpoved);
polozka++;
}
// zavření spojení do databáze a uvolneni nepotrebnych objektu z pameti
cmd.Dispose();
rdr.Close();
conn.Close();
stringFormatOdpoved.Dispose();
fontPopisOdpoved.Dispose();
}
catch
{
if (idankety>0)
{
ErrorText=“Nejsou k dispozici žádná data“;
}
}
// pokud doslo v prubehu prace k chybě vypsat hlášení
if (ErrorText.Length>0)
{
objGraphics.DrawString(ErrorText, fontPopis, new SolidBrush(Color.Black),
new Rectangle(5,5,390,40),stringFormat);
objGraphics.FillEllipse(new SolidBrush(Color.Red),60,60,280,280);
}
// odeslaní výsledku na klienta
Response.ContentType = („image/gif“);
objBitmap.Save (Response.OutputStream,ImageFormat.Gif);
// uvolnění paměti
fontPopis.Dispose();
stringFormat.Dispose();
objGraphics.Dispose();
objBitmap.Dispose();
}
Užitečným doplněním grafu by bylo zamezení zobrazení grafu z jiného serveru způsobem, který popsal Pavel Růžička v článku Dynamické obrázkové nadpisy v ASP.NET. Toto ošetření nemá vliv na funkčnost příkladu, a proto jsem je z důvodu přehlednosti do kódu nezahrnul.
Mohlo by vás také zajímat
-
Thunderbolt 4 vs. OCuLink: Přišel čas na upgrade?
27. května 2024 -
Monitory OLED: klíčové pojmy a funkce
13. května 2024 -
Šokující data od Microsoftu: Kyberútoky rostou o stovky procent!
8. listopadu 2024 -
Optimalizace a zlepšení výkonu kódu: tipy a triky
14. srpna 2023
Nejnovější
-
Výkonný a kompaktní: ASOME Max Studio s výjimečným poměrem cena/výkon
11. listopadu 2024 -
Šokující data od Microsoftu: Kyberútoky rostou o stovky procent!
8. listopadu 2024 -
Chcete jedinečnou doménu? Objevte koncovky FOOD, MEME a MUSIC!
7. listopadu 2024 -
OpenAI představilo novou funkci ChatGPT Search
6. listopadu 2024