Základy 2D grafiky v Silverlightu 2.0

V tomto článku se seznámíme se základními prvky 2D grafiky v Silverlightu. Nejdříve si všechny prvky představíme a pak se budeme věnovat tomu, jak s nimi pracovat a jak je kombinovat. Předvedeme si také výběr štětců a používání transformací.
Seriál: Praktické užití Silverlight 2.0 (12 dílů)
- Praktické užití Silverlight 2.0: Data Binding 15. 12. 2008
- Praktické užití Silverlight 2.0: DataGrid 22. 12. 2008
- Praktické užití Silverlight 2.0: UserControl 29. 12. 2008
- Co zajímavého přínáší Silverlight toolkit 5. 1. 2009
- Silverlight toolkit a vizualizace dat 12. 1. 2009
- Jak na komponenty AutoCompleteBox a TreeView ze Silverlight toolkitu 19. 1. 2009
- Nástroje pro tvorbu layoutu v Silverlightu 2.0 a Silverlight toolkitu 26. 1. 2009
- Design se styly a šablonami v Silverlightu 2.0 2. 2. 2009
- Základy 2D grafiky v Silverlightu 2.0 16. 2. 2009
- Dynamicky generované komponenty v Silverlightu 2.0 3. 3. 2009
- Úvod do streamování médií v Silverlightu 2.0 16. 3. 2009
- Práce s videem v Silverlightu 2.0 1. 6. 2009
Nálepky:
S tím, jak rostou nároky na vzhled aplikací, rostou také požadavky na znalost práce s grafikou. I když se budeme bavit o vzhledu firemního informačního systému, tak nikde není psáno, že by měl být ošklivý. Naopak. Někteří výrobci softwaru nasadili laťku ergonomie informačních systémů dosti vysoko a poslední dobou čím dál víc slýcháme od zákazníků věty typu: „Pořídil jsem si Maca a je v něm všechno hrozně hezké, chtěl bych, aby náš IS byl stejně hezký.“ Jelikož je XAML koncipovaný vektorově, je jako stvořený pro tvorbu „krásných GUI“.
Vše, co v XAMLu vytvoříte, je popsáno několika základními tvary. Pokud se zaměříme na jakoukoli komponentu XAMLu, třeba tlačítko, ComboBox
či textové pole, není to nic jiného než změť „tvarů“.
Celá práce s grafikou se dá rozdělit do třech částí:
- tvary (Shapes) – základní tvary, ze kterých se skládá veškerá grafika,
- štětce (Brushes) – jedná se o veškeré „malování“ – barvy, vzory, výplně,
- transformace (Transforms) – přizpůsobování základních tvarů (otáčení, deformace, posuny, …)
Tvary
Atomických prvků grafiky v XAMLu je pět:
Line
– linkaEllipse
– elipsa, kružniceRectangle
– obdélníkPolygon
– mnohoúhelníkPolyline
– spojitá linka
Tyto prvky jsou stejné nebo velice podobné ve většině vektorových jazyků (např. SVG).
Zde je ukázka syntaxe základních tvarů:
<!--Linka - definujeme počáteční a koncový bod-->
<Line Stroke="Black"
X1="0" Y1="0"
X2="100" Y2="50"
Margin="10"/>
<!--Elipsa - definujeme výšku a šířku-->
<Ellipse Stroke="Black"
Width="100"
Height="50"
Margin="10"/>
<!--Obdélník - definujeme výšku a šířku-->
<Rectangle Stroke="Black"
Width="100"
Height="50"
Margin="10"/>
<!--Obdélník - zakulacené rohy-->
<Rectangle Stroke="Black"
Width="100"
Height="50"
RadiusX="30"
RadiusY="10"
Margin="10"/>
<!--Mnohoúhelník - pomocí atributu Point definujeme každý bod,
který má mnohoúhelník protnout-->
<Polygon Stroke="Black"
Points="20,0 0,25 20,50 100,50 75,25 100,0"
Margin="10"/>
<!--Spojitá linka - na rozdíl od mnohoúhelníků je otevřená-->
<Polyline Stroke="Black"
Points="0,25 10,15 20,35 30,0 40,50 50,25 60,25 70,15 80,35 90,0 100,50"
Margin="10"/>
Zobrazení základních tvarů:

Sestavování tvarů – Geometry
Někdy budeme chtít definovat daleko složitější tvary a dále s nimi pracovat. K tomu využijeme nástroj Geometry
. Všechny obsažené prvky zapouzdří do prvku Path
(cesta); následně s celým prvkem lze nakládat jako s celistvou jednotkou.
Existují dva způsoby, jak vytvářet složené tvary. V prvním případě si definujeme path.Data
sami pomocí základních tvarů. Tuto možnost zvolíme v případě, kdy budeme dynamicky generovat tvar. Definice tvaru pak následně může vypadat takto:
<Path Margin="10" Fill="LightGray" StrokeThickness="0">
<Path.Data>
<GeometryGroup FillRule="EvenOdd">
<EllipseGeometry Center="50,50" RadiusX="50" RadiusY="25"/>
<EllipseGeometry Center="50,50" RadiusX="20" RadiusY="25"/>
<EllipseGeometry Center="50,50" RadiusX="5" RadiusY="4"/>
</GeometryGroup>
</Path.Data>
</Path>
Výsledek:

V ukázce jsme naskládali tři elipsy do jedné skupiny, které jsme přiřadili pravidlo pro vykreslování FillRule
.
Druhou variantou je definování Path.Data
pomocí PMS (Path Markup Syntax). PMS je speciálním mini jazykem sloužícím k popsání cesty ( Path
).
<Path Stroke="Black"
Fill="Gray"
Data="M 10,100 C 10,300 300,-200 300,100" />
Veškeré informace o tom, jak má tvar vypadat, jsou popsány pomocí kódu v atributu Data
(M zančí počátek a C označuje kontrolní body křivky). Výsledná křivka:

Druhý způsob není primárně určen pro psaní ruční programátorem. S tímto formátem zápisu cesty se setkáte hlavně v případě, pokud jste grafiku zpracovávali v Expression Blend 2.
Štětce
V případě, že jsme si již nějaký ten tvar vytvořili, budeme chtít, aby pěkně vypadal. V jazyku XAML nalezneme 5 druhů štětců, kterými můžeme náš tvar nakreslit.
SolidColorBrush
U tohoto štětce je tvar vyplněn jednou barvou. Existují dva způsoby, jak tento druh štětce uplatnit. Prvním je definování barvy přímo v těle tvaru (jelikož atributy Fill
a Stroke
jsou typu System.Windows.Media.SolidColorBrush
) a nebo definováním v těle atributu.
<!--SolidColorbrush-->
<Rectangle Stroke="Black"
Width="200"
Height="100"
Margin="10">
<Rectangle.Fill>
<SolidColorBrush Color="LightGray"/>
</Rectangle.Fill>
</Rectangle>
<!--SolidColorbrush – definice v těle-->
<Rectangle Stroke="Black"
Width="200"
Height="100"
Margin="10"
Fill="LightGray"/>
Výsledek je v obou případech stejný:

LinearGradientBrush
Jedná se o plynulé vyplnění lineárním přechodem mezi barvami. Nejprve musíme definovat počáteční (Startpoint
) a koncový (EndPoint
) bod přechodu ( GradientStop
). Tím určíme směr přechodu (levý horní roh má souřadnice 0,0 a pravý dolní 1,1 – v příkladu tedy jde přechod z levého dolního rohu do pravého horního). Pokud bychom směr nedefinovali, přechod půjde z levého horního rohu do pravého dolního.
Dále pokračujeme tím, že definujeme body přechodu. U nich definujeme barvu Color
a Offset
, což indikuje polohu mezi počátečním a koncovým bodem.
<!--LineargradientBrush-->
<Rectangle Stroke="Black"
Width="200"
Height="100"
Margin="10">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Red" Offset=".25"/>
<GradientStop Color="Green" Offset=".5"/>
<GradientStop Color="Blue" Offset=".75"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

RadialGradientBrush
Vyplnění plynulým radiálním (kruhovým) přechodem mezi barvami. V podstatě se chová identicky jako lineární přechod. U kruhového přechodu si navíc můžeme definovat střed pomocí atributu GradientOrigin
, centrum přechodu pomocíCenter
(měrný střed přechodu) nebo zploštění pomocíRadiusX
a RadiusY
.
<!--RadialgradientBrush-->
<Rectangle Stroke="Black"
Width="200"
Height="100"
Margin="10">
<Rectangle.Fill>
<RadialGradientBrush Center=".75,.75"
GradientOrigin=".55,.55"
RadiusY=".3">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Red" Offset=".25"/>
<GradientStop Color="Green" Offset=".5"/>
<GradientStop Color="Blue" Offset=".75"/>
<GradientStop Color="Yellow" Offset="1"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>

ImageBrush
Jedná se o vyplnění tvaru obrázkem.
<!--ImageBrush-->
<Ellipse Stroke="Black"
Width="200"
Height="100"
Margin="10">
<Ellipse.Fill>
<ImageBrush ImageSource="images/euro.jpg"/>
</Ellipse.Fill>
</Ellipse>

VideoBrush
Vyplnění tvaru videem. Zde je jedna malá zvláštnost. Nejdříve musíme definovat MediaElement a pojmenovat jej. Následně jej můžeme použít jako štětec.
<!--VideoBrush-->
<MediaElement x:Name="MojeVideo"
Source="video/golf.wmv"
Opacity="0"
AutoPlay="True"/>
<Polygon Stroke="Black"
Points="20,0 0,50 20,100 200,100 175,50 200,0"
Margin="10">
<Polygon.Fill>
<VideoBrush SourceName="MojeVideo"/>
</Polygon.Fill>
</Polygon>
Na závěr musím u štětců podotknout, že je můžete používat všude, kde se objevuje definice barvy. Tedy i u všech pozadí (Canvas, StackPanel, Grid, TextBox), či u písma.
<!--Pismo-->
<TextBlock FontFamily="Arial"
FontSize="100"
FontWeight="Bold"
Text="EURO2008">
<TextBlock.Foreground>
<ImageBrush ImageSource="images/euro.jpg"
Stretch="UniformToFill"/>
</TextBlock.Foreground>
</TextBlock>

Transformace
Poslední částí našeho článku jsou transformace. Jedná se o 4 základní úkony, jak nakládat s tvary nebo jinými komponentami. Jedná se o: otočení, zmenšení/zvětšení, zkosení a posun. Transformace se definují v atributu RenderTransform
. Pokud provádíme více než jednu transformaci vytvářímeTransformGroup
(skupinu transformací).
<!--ukazka transformaci-->
<Rectangle Width="200"
Height="100"
Stroke="Black"
Fill="LightGray">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1.5"
ScaleY="2"/>
<SkewTransform AngleX="25"
AngleY="5"/>
<RotateTransform Angle="60"/>
<TranslateTransform X="100"/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
Obdélník před transformací:

Obdélník po provedení transformací (je větší, zkosený, otočený a posunutý):

Závěrem
Stejně jako tomu bylo u stylů, šablon a animací, i základy práce s grafikou je nutné alespoň teoreticky znát. I přestože ve většině případů dostanete design hotový od grafika, je nutné porozumět alespoň struktuře. Nejvíc své znalosti struktury 2D grafiky využijete tehdy, pokud budete chtít grafiku dynamicky vytvářet.
Příště
Příště se vrhneme na téma, které je dle mého názoru o trochu více zábavné. Budeme se věnovat dynamickému generování komponent z logiky.
jde tam importovat grafika z Illustratoru nebo Corelu? popřípadě existují už nějaké nástroje pro vytváření grafiky od někoho jiného než MS?
Umí to poslední verze Illustratoru. Jak na PC tak na Mac.
to je fajn, programy od MS mají čím dál tím horší GUI, takže bude asi lepší sázet na jistotu
Pekne a prehledne shrnuti, jen ten posledni obrazek je trochu nakrivo a chybi mu uprostred carka :-)