WPF — це не просто фреймворк для кнопок та текстових полів. Це потужна графічна система, побудована на DirectX, що дозволяє створювати складну векторну графіку, градієнти, трансформації та навіть відтворювати відео прямо в інтерфейсі.
Уявіть: ви можете намалювати будь-яку фігуру через Path з SVG-подібним синтаксисом, застосувати градієнтний фон з кількома кольорами, обернути елемент на 45 градусів, і все це буде масштабуватися без втрати якості, бо це вектор. Або вставити відео як фон для кнопки через MediaElement. WPF робить це природно та елегантно.
У цій статті ми детально розберемо всі графічні можливості WPF: від базових фігур (Rectangle, Ellipse) до складних Path з кривими Безьє, від простих кольорів до радіальних градієнтів, від статичних зображень до відео. Ви навчитесь створювати професійні візуальні ефекти без зовнішніх бібліотек.
WPF надає набір готових фігур через класи, що успадковуються від Shape.
<Rectangle Width="200" Height="100"
Fill="#3b82f6"
Stroke="#1e40af"
StrokeThickness="2"
RadiusX="8"
RadiusY="8"/>
Властивості:
Fill — заповнення (колір або Brush)Stroke — обведення (колір або Brush)StrokeThickness — товщина обведенняRadiusX, RadiusY — заокруглення кутівLoading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Border Background="#f8fafc" Padding="40" CornerRadius="8">
<StackPanel Spacing="16" HorizontalAlignment="Center">
<TextBlock Text="📐 Rectangle Shapes"
FontSize="20" FontWeight="Bold"
Foreground="#1e293b"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal" Spacing="16">
<!-- Звичайний прямокутник -->
<Rectangle Width="100" Height="80"
Fill="#3b82f6"
Stroke="#1e40af"
StrokeThickness="2"/>
<!-- З заокругленими кутами -->
<Rectangle Width="100" Height="80"
Fill="#22c55e"
Stroke="#16a34a"
StrokeThickness="2"
RadiusX="12"
RadiusY="12"/>
<!-- Лише обведення -->
<Rectangle Width="100" Height="80"
Stroke="#f59e0b"
StrokeThickness="3"
RadiusX="8"
RadiusY="8"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Коло -->
<Ellipse Width="100" Height="100"
Fill="#ef4444"
Stroke="#dc2626"
StrokeThickness="2"/>
<!-- Еліпс -->
<Ellipse Width="150" Height="80"
Fill="#8b5cf6"
Stroke="#7c3aed"
StrokeThickness="2"/>
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Border Background="#f8fafc" Padding="40" CornerRadius="8">
<StackPanel Spacing="16" HorizontalAlignment="Center">
<TextBlock Text="⭕ Ellipse Shapes"
FontSize="20" FontWeight="Bold"
Foreground="#1e293b"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal" Spacing="16" HorizontalAlignment="Center">
<!-- Коло -->
<Ellipse Width="80" Height="80"
Fill="#ef4444"
Stroke="#dc2626"
StrokeThickness="2"/>
<!-- Еліпс горизонтальний -->
<Ellipse Width="120" Height="80"
Fill="#8b5cf6"
Stroke="#7c3aed"
StrokeThickness="2"/>
<!-- Еліпс вертикальний -->
<Ellipse Width="80" Height="120"
Fill="#06b6d4"
Stroke="#0891b2"
StrokeThickness="2"/>
</StackPanel>
</StackPanel>
</Border>
<Line X1="0" Y1="0" X2="200" Y2="100"
Stroke="#64748b"
StrokeThickness="2"/>
Властивості:
X1, Y1 — початкова точкаX2, Y2 — кінцева точкаStroke — колір лініїStrokeThickness — товщина<!-- Трикутник -->
<Polygon Points="50,0 100,100 0,100"
Fill="#f59e0b"
Stroke="#d97706"
StrokeThickness="2"/>
<!-- П'ятикутник -->
<Polygon Points="50,0 100,38 81,100 19,100 0,38"
Fill="#10b981"
Stroke="#059669"
StrokeThickness="2"/>
Points формат: "x1,y1 x2,y2 x3,y3 ..." — список координат вершин.
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Border Background="#f8fafc" Padding="40" CornerRadius="8">
<StackPanel Spacing="16" HorizontalAlignment="Center">
<TextBlock Text="🔺 Polygon Shapes"
FontSize="20" FontWeight="Bold"
Foreground="#1e293b"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal" Spacing="24" HorizontalAlignment="Center">
<!-- Трикутник -->
<Polygon Points="50,0 100,86 0,86"
Fill="#f59e0b"
Stroke="#d97706"
StrokeThickness="2"/>
<!-- Квадрат (через Polygon) -->
<Polygon Points="0,0 80,0 80,80 0,80"
Fill="#3b82f6"
Stroke="#1e40af"
StrokeThickness="2"/>
<!-- Зірка -->
<Polygon Points="50,0 61,35 98,35 68,57 79,91 50,70 21,91 32,57 2,35 39,35"
Fill="#ef4444"
Stroke="#dc2626"
StrokeThickness="2"/>
</StackPanel>
</StackPanel>
</Border>
<Polyline Points="0,50 50,0 100,50 150,0 200,50"
Stroke="#3b82f6"
StrokeThickness="3"
Fill="Transparent"/>
Різниця з Polygon: Polyline не замикає фігуру автоматично.
<!-- Пунктирна лінія -->
<Line X1="0" Y1="0" X2="200" Y2="0"
Stroke="#64748b"
StrokeThickness="2"
StrokeDashArray="4,2"/>
<!-- Штрих-пунктирна -->
<Line X1="0" Y1="0" X2="200" Y2="0"
Stroke="#64748b"
StrokeThickness="2"
StrokeDashArray="8,2,2,2"/>
StrokeDashArray формат: "dash,gap,dash,gap,..." — довжина штриха та проміжку.
Path — це універсальна фігура, що може описати будь-яку форму через PathGeometry. Синтаксис схожий на SVG.
<Path Stroke="#3b82f6" StrokeThickness="2" Fill="#93c5fd">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="10,50">
<LineSegment Point="50,10"/>
<LineSegment Point="90,50"/>
<LineSegment Point="50,90"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
Замість багатослівного XML, WPF підтримує компактний синтаксис через Data атрибут:
<Path Data="M 10,50 L 50,10 L 90,50 L 50,90 Z"
Stroke="#3b82f6"
StrokeThickness="2"
Fill="#93c5fd"/>
Команди mini-language:
| Команда | Опис | Приклад |
|---|---|---|
M x,y | Move to (переміститися) | M 10,20 |
L x,y | Line to (лінія до) | L 50,60 |
H x | Horizontal line (горизонтальна лінія) | H 100 |
V y | Vertical line (вертикальна лінія) | V 80 |
C x1,y1 x2,y2 x,y | Cubic Bezier curve (кубічна крива) | C 20,20 40,20 50,10 |
Q x1,y1 x,y | Quadratic Bezier curve (квадратична крива) | Q 30,30 50,10 |
A rx,ry angle large sweep x,y | Arc (дуга) | A 30,30 0 0 1 50,50 |
Z | Close path (замкнути фігуру) | Z |
Малі літери (m, l, h, v, c, q, a) — відносні координати (від поточної позиції).
<Path Data="M 50,20 C 50,10 40,0 30,0 C 15,0 0,15 0,30 C 0,45 15,60 50,90 C 85,60 100,45 100,30 C 100,15 85,0 70,0 C 60,0 50,10 50,20 Z"
Fill="#ef4444"
Stroke="#dc2626"
StrokeThickness="2"/>
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Border Background="#f8fafc" Padding="40" CornerRadius="8">
<StackPanel Spacing="20" HorizontalAlignment="Center">
<TextBlock Text="💎 Path Shapes"
FontSize="20" FontWeight="Bold"
Foreground="#1e293b"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal" Spacing="24" HorizontalAlignment="Center">
<!-- Серце -->
<Path Data="M 50,20 C 50,10 40,0 30,0 C 15,0 0,15 0,30 C 0,45 15,60 50,90 C 85,60 100,45 100,30 C 100,15 85,0 70,0 C 60,0 50,10 50,20 Z"
Fill="#ef4444"
Stroke="#dc2626"
StrokeThickness="2"
Width="80"
Height="80"
Stretch="Uniform"/>
<!-- Зірка (через Path) -->
<Path Data="M 50,0 L 61,35 L 98,35 L 68,57 L 79,91 L 50,70 L 21,91 L 32,57 L 2,35 L 39,35 Z"
Fill="#f59e0b"
Stroke="#d97706"
StrokeThickness="2"
Width="80"
Height="80"
Stretch="Uniform"/>
<!-- Хмара -->
<Path Data="M 20,40 C 20,30 30,20 40,20 C 45,20 50,22 53,25 C 56,18 63,13 71,13 C 82,13 91,22 91,33 C 91,34 91,35 90,36 C 96,38 100,44 100,51 C 100,60 93,67 84,67 L 20,67 C 9,67 0,58 0,47 C 0,38 6,30 15,28 C 16,28 17,28 18,28 C 18,33 19,37 20,40 Z"
Fill="#06b6d4"
Stroke="#0891b2"
StrokeThickness="2"
Width="80"
Height="60"
Stretch="Uniform"/>
</StackPanel>
</StackPanel>
</Border>
Багато графічних редакторів (Figma, Illustrator, Inkscape) експортують SVG. Ви можете скопіювати d атрибут з SVG <path> і вставити в WPF Path.Data:
SVG:
<svg>
<path d="M 10,10 L 50,50 L 10,90 Z" fill="blue"/>
</svg>
WPF:
<Path Data="M 10,10 L 50,50 L 10,90 Z" Fill="Blue"/>
Brush визначає, як заповнюється фігура або фон елемента. WPF підтримує кілька типів Brush.
<Rectangle Fill="#3b82f6"/>
<!-- Або через об'єкт -->
<Rectangle>
<Rectangle.Fill>
<SolidColorBrush Color="#3b82f6"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#3b82f6" Offset="0"/>
<GradientStop Color="#8b5cf6" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Властивості:
StartPoint, EndPoint — напрямок градієнта (0,0 = верхній лівий, 1,1 = нижній правий)GradientStop — колір на певній позиції (Offset від 0 до 1)Напрямки градієнта:
<!-- Горизонтальний (зліва направо) -->
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<!-- Вертикальний (зверху вниз) -->
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<!-- Діагональний -->
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<!-- Знизу вгору -->
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Border Background="#f8fafc" Padding="40" CornerRadius="8">
<StackPanel Spacing="16" HorizontalAlignment="Center">
<TextBlock Text="🎨 Linear Gradients"
FontSize="20" FontWeight="Bold"
Foreground="#1e293b"
HorizontalAlignment="Center"/>
<StackPanel Spacing="12">
<!-- Горизонтальний градієнт -->
<Border Width="300" Height="60" CornerRadius="8">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#3b82f6" Offset="0"/>
<GradientStop Color="#8b5cf6" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<TextBlock Text="Horizontal"
Foreground="White"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- Вертикальний градієнт -->
<Border Width="300" Height="60" CornerRadius="8">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#22c55e" Offset="0"/>
<GradientStop Color="#06b6d4" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<TextBlock Text="Vertical"
Foreground="White"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- Діагональний градієнт -->
<Border Width="300" Height="60" CornerRadius="8">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#f59e0b" Offset="0"/>
<GradientStop Color="#ef4444" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<TextBlock Text="Diagonal"
Foreground="White"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- Багатоколірний градієнт -->
<Border Width="300" Height="60" CornerRadius="8">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#ef4444" Offset="0"/>
<GradientStop Color="#f59e0b" Offset="0.25"/>
<GradientStop Color="#22c55e" Offset="0.5"/>
<GradientStop Color="#3b82f6" Offset="0.75"/>
<GradientStop Color="#8b5cf6" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<TextBlock Text="Rainbow"
Foreground="White"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</StackPanel>
</StackPanel>
</Border>
<Ellipse Width="200" Height="200">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#ffffff" Offset="0"/>
<GradientStop Color="#3b82f6" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
Властивості:
Center — центр градієнта (за замовчуванням 0.5,0.5)RadiusX, RadiusY — радіус градієнтаGradientOrigin — точка початку градієнтаLoading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Border Background="#f8fafc" Padding="40" CornerRadius="8">
<StackPanel Spacing="16" HorizontalAlignment="Center">
<TextBlock Text="🌟 Radial Gradients"
FontSize="20" FontWeight="Bold"
Foreground="#1e293b"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal" Spacing="20" HorizontalAlignment="Center">
<!-- Центрований радіальний градієнт -->
<Ellipse Width="120" Height="120">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#ffffff" Offset="0"/>
<GradientStop Color="#3b82f6" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!-- Зміщений центр -->
<Ellipse Width="120" Height="120">
<Ellipse.Fill>
<RadialGradientBrush Center="0.3,0.3" GradientOrigin="0.3,0.3">
<GradientStop Color="#ffffff" Offset="0"/>
<GradientStop Color="#22c55e" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!-- Багатоколірний -->
<Ellipse Width="120" Height="120">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#fef3c7" Offset="0"/>
<GradientStop Color="#fbbf24" Offset="0.5"/>
<GradientStop Color="#f59e0b" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
</StackPanel>
</StackPanel>
</Border>
<Rectangle Width="200" Height="200">
<Rectangle.Fill>
<ImageBrush ImageSource="/Assets/pattern.png"
TileMode="Tile"
Viewport="0,0,0.25,0.25"/>
</Rectangle.Fill>
</Rectangle>
Властивості:
ImageSource — шлях до зображенняStretch — як масштабувати (None, Fill, Uniform, UniformToFill)TileMode — режим повторення (None, Tile, FlipX, FlipY, FlipXY)Viewport — розмір плитки при TileMode="Tile"VisualBrush дозволяє використовувати будь-який WPF елемент як текстуру. Це потужна можливість для створення ефектів дзеркала, повторюваних патернів з UI-елементів, тощо.
<Grid>
<!-- Оригінальний елемент -->
<StackPanel x:Name="OriginalContent" Width="200">
<TextBlock Text="Hello WPF!" FontSize="24" FontWeight="Bold"/>
<Button Content="Click Me"/>
</StackPanel>
<!-- Використання як Brush -->
<Rectangle Width="200" Height="200" Margin="250,0,0,0">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=OriginalContent}"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
Приклад: Повторюваний патерн з кнопки
<Border Width="400" Height="300">
<Border.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,0.2,0.2">
<VisualBrush.Visual>
<Button Content="🎨" Width="50" Height="50"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.Background>
</Border>
Geometry — це математичний опис форми без візуального представлення. Використовується для Clip (обрізання), Data у Path, або як основа для Drawing.
<!-- Обрізання елемента по колу -->
<Image Source="/Assets/photo.jpg" Width="200" Height="200">
<Image.Clip>
<EllipseGeometry Center="100,100" RadiusX="100" RadiusY="100"/>
</Image.Clip>
</Image>
<!-- Обрізання по прямокутнику з заокругленими кутами -->
<Border Background="Blue" Width="200" Height="100">
<Border.Clip>
<RectangleGeometry Rect="0,0,200,100" RadiusX="20" RadiusY="20"/>
</Border.Clip>
</Border>
<Path Stroke="Black" StrokeThickness="2" Fill="#3b82f6">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<RectangleGeometry Rect="0,0,100,100"/>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="50,50" RadiusX="40" RadiusY="40"/>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
GeometryCombineMode:
Union — об'єднання (A + B)Intersect — перетин (A ∩ B)Xor — виключне АБО (A ⊕ B)Exclude — різниця (A - B)Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Border Background="#f8fafc" Padding="40" CornerRadius="8">
<StackPanel Spacing="20" HorizontalAlignment="Center">
<TextBlock Text="🔀 Combined Geometries"
FontSize="20" FontWeight="Bold"
Foreground="#1e293b"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal" Spacing="24" HorizontalAlignment="Center">
<!-- Union -->
<StackPanel Spacing="8">
<Path Stroke="#1e40af" StrokeThickness="2" Fill="#3b82f6" Width="100" Height="100">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="35,50" RadiusX="35" RadiusY="35"/>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="65,50" RadiusX="35" RadiusY="35"/>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<TextBlock Text="Union" FontSize="12" Foreground="#64748b" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Intersect -->
<StackPanel Spacing="8">
<Path Stroke="#16a34a" StrokeThickness="2" Fill="#22c55e" Width="100" Height="100">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Intersect">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="35,50" RadiusX="35" RadiusY="35"/>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="65,50" RadiusX="35" RadiusY="35"/>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<TextBlock Text="Intersect" FontSize="12" Foreground="#64748b" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Exclude -->
<StackPanel Spacing="8">
<Path Stroke="#dc2626" StrokeThickness="2" Fill="#ef4444" Width="100" Height="100">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="35,50" RadiusX="35" RadiusY="35"/>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="65,50" RadiusX="35" RadiusY="35"/>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<TextBlock Text="Exclude" FontSize="12" Foreground="#64748b" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Xor -->
<StackPanel Spacing="8">
<Path Stroke="#7c3aed" StrokeThickness="2" Fill="#8b5cf6" Width="100" Height="100">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Xor">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="35,50" RadiusX="35" RadiusY="35"/>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="65,50" RadiusX="35" RadiusY="35"/>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<TextBlock Text="Xor" FontSize="12" Foreground="#64748b" HorizontalAlignment="Center"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
<PathGeometry>
<PathFigure StartPoint="10,50" IsClosed="True">
<LineSegment Point="50,10"/>
<ArcSegment Point="90,50" Size="40,40" SweepDirection="Clockwise"/>
<LineSegment Point="50,90"/>
</PathFigure>
</PathGeometry>
Drawing — це легковаговий спосіб створення векторної графіки без повноцінних UI-елементів. Використовується для іконок, складних векторних зображень.
<Image Width="100" Height="100">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup>
<!-- Коло -->
<GeometryDrawing Brush="#3b82f6">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="50,50" RadiusX="40" RadiusY="40"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
<!-- Трикутник всередині -->
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<PathGeometry>
<PathFigure StartPoint="35,60" IsClosed="True">
<LineSegment Point="50,35"/>
<LineSegment Point="65,60"/>
</PathFigure>
</PathGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
Переваги Drawing над Shape:
Недоліки:
Transforms дозволяють обертати, масштабувати, переміщувати та нахиляти елементи.
<Rectangle Width="100" Height="50" Fill="#3b82f6">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" CenterX="50" CenterY="25"/>
</Rectangle.RenderTransform>
</Rectangle>
Властивості:
Angle — кут обертання в градусахCenterX, CenterY — точка обертання<Button Content="Scaled">
<Button.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5" CenterX="50" CenterY="25"/>
</Button.RenderTransform>
</Button>
Властивості:
ScaleX, ScaleY — коефіцієнт масштабування (1 = 100%, 2 = 200%, 0.5 = 50%)CenterX, CenterY — точка масштабування<Ellipse Width="50" Height="50" Fill="#22c55e">
<Ellipse.RenderTransform>
<TranslateTransform X="100" Y="50"/>
</Ellipse.RenderTransform>
</Ellipse>
Властивості:
X, Y — зміщення по осях<Rectangle Width="100" Height="50" Fill="#f59e0b">
<Rectangle.RenderTransform>
<SkewTransform AngleX="20" AngleY="0"/>
</Rectangle.RenderTransform>
</Rectangle>
Властивості:
AngleX, AngleY — кут нахилу по осях<Border Width="100" Height="100" Background="#8b5cf6">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1.2" ScaleY="1.2"/>
<RotateTransform Angle="15"/>
<TranslateTransform X="50" Y="20"/>
</TransformGroup>
</Border.RenderTransform>
</Border>
Порядок застосування: Трансформації застосовуються в порядку, в якому вони визначені в TransformGroup.
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Border Background="#f8fafc" Padding="40" CornerRadius="8">
<StackPanel Spacing="24" HorizontalAlignment="Center">
<TextBlock Text="🔄 Transforms"
FontSize="20" FontWeight="Bold"
Foreground="#1e293b"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal" Spacing="32" HorizontalAlignment="Center">
<!-- Оригінал -->
<StackPanel Spacing="8">
<Rectangle Width="80" Height="80" Fill="#3b82f6" Stroke="#1e40af" StrokeThickness="2"/>
<TextBlock Text="Original" FontSize="12" Foreground="#64748b" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Rotate -->
<StackPanel Spacing="8">
<Rectangle Width="80" Height="80" Fill="#22c55e" Stroke="#16a34a" StrokeThickness="2">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" CenterX="40" CenterY="40"/>
</Rectangle.RenderTransform>
</Rectangle>
<TextBlock Text="Rotate 45°" FontSize="12" Foreground="#64748b" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Scale -->
<StackPanel Spacing="8">
<Rectangle Width="80" Height="80" Fill="#f59e0b" Stroke="#d97706" StrokeThickness="2">
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="0.7" ScaleY="1.3" CenterX="40" CenterY="40"/>
</Rectangle.RenderTransform>
</Rectangle>
<TextBlock Text="Scale" FontSize="12" Foreground="#64748b" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Skew -->
<StackPanel Spacing="8">
<Rectangle Width="80" Height="80" Fill="#8b5cf6" Stroke="#7c3aed" StrokeThickness="2">
<Rectangle.RenderTransform>
<SkewTransform AngleX="20" AngleY="0"/>
</Rectangle.RenderTransform>
</Rectangle>
<TextBlock Text="Skew" FontSize="12" Foreground="#64748b" HorizontalAlignment="Center"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
MediaElement дозволяє відтворювати відео та аудіо файли прямо в WPF інтерфейсі.
<MediaElement x:Name="VideoPlayer"
Source="/Assets/video.mp4"
LoadedBehavior="Manual"
Width="640"
Height="360"/>
<StackPanel Orientation="Horizontal">
<Button Content="Play" Click="Play_Click"/>
<Button Content="Pause" Click="Pause_Click"/>
<Button Content="Stop" Click="Stop_Click"/>
</StackPanel>
private void Play_Click(object sender, RoutedEventArgs e)
{
VideoPlayer.Play();
}
private void Pause_Click(object sender, RoutedEventArgs e)
{
VideoPlayer.Pause();
}
private void Stop_Click(object sender, RoutedEventArgs e)
{
VideoPlayer.Stop();
}
| Властивість | Опис |
|---|---|
Source | Шлях до медіа-файлу (локальний або URL) |
LoadedBehavior | Поведінка при завантаженні (Manual, Play, Pause, Stop) |
UnloadedBehavior | Поведінка при вивантаженні |
Volume | Гучність (0.0 - 1.0) |
IsMuted | Вимкнути звук |
Position | Поточна позиція відтворення (TimeSpan) |
SpeedRatio | Швидкість відтворення (1.0 = нормальна, 2.0 = 2x) |
Stretch | Як масштабувати відео (None, Fill, Uniform, UniformToFill) |
VideoPlayer.MediaOpened += (s, e) =>
{
// Медіа завантажено, можна отримати Duration
var duration = VideoPlayer.NaturalDuration.TimeSpan;
Console.WriteLine($"Duration: {duration}");
};
VideoPlayer.MediaEnded += (s, e) =>
{
// Відтворення завершено
VideoPlayer.Position = TimeSpan.Zero; // Повернутися на початок
};
VideoPlayer.MediaFailed += (s, e) =>
{
// Помилка завантаження
MessageBox.Show($"Error: {e.ErrorException.Message}");
};
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Відео -->
<MediaElement x:Name="VideoPlayer"
Source="/Assets/video.mp4"
LoadedBehavior="Manual"
Stretch="Uniform"/>
<!-- Контроли -->
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10">
<Button Content="▶" Width="40" Click="Play_Click"/>
<Button Content="⏸" Width="40" Click="Pause_Click"/>
<Button Content="⏹" Width="40" Click="Stop_Click"/>
<Slider x:Name="PositionSlider"
Width="300"
Margin="10,0"
ValueChanged="PositionSlider_ValueChanged"/>
<TextBlock x:Name="TimeText"
Text="00:00 / 00:00"
VerticalAlignment="Center"
Margin="10,0"/>
</StackPanel>
</Grid>
private bool _isUserDraggingSlider = false;
private void VideoPlayer_MediaOpened(object sender, RoutedEventArgs e)
{
if (VideoPlayer.NaturalDuration.HasTimeSpan)
{
PositionSlider.Maximum = VideoPlayer.NaturalDuration.TimeSpan.TotalSeconds;
// Оновлення позиції кожні 100ms
var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(100) };
timer.Tick += (s, args) =>
{
if (!_isUserDraggingSlider)
{
PositionSlider.Value = VideoPlayer.Position.TotalSeconds;
UpdateTimeText();
}
};
timer.Start();
}
}
private void PositionSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (_isUserDraggingSlider)
{
VideoPlayer.Position = TimeSpan.FromSeconds(PositionSlider.Value);
}
}
private void UpdateTimeText()
{
var current = VideoPlayer.Position;
var total = VideoPlayer.NaturalDuration.HasTimeSpan
? VideoPlayer.NaturalDuration.TimeSpan
: TimeSpan.Zero;
TimeText.Text = $"{current:mm\\:ss} / {total:mm\\:ss}";
}
<MediaElement x:Name="VideoPlayer" LoadedBehavior="Manual">
<MediaElement.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<MediaTimeline Source="/Assets/video.mp4"
Storyboard.TargetName="VideoPlayer"
BeginTime="0:0:2"
Duration="0:0:10"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</MediaElement.Triggers>
</MediaElement>
MediaTimeline дозволяє контролювати відтворення через Storyboard (затримка, тривалість, повторення).
Мета: Навчитися використовувати базові Shape елементи.
Завдання:
Створіть композицію з геометричних фігур:
Критерії успіху:
Підказка:
<StackPanel Orientation="Horizontal" Spacing="20" HorizontalAlignment="Center">
<!-- Коло -->
<StackPanel Spacing="8">
<Ellipse Width="80" Height="80"
Fill="#ef4444"
Stroke="#dc2626"
StrokeThickness="2"/>
<TextBlock Text="Circle" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Квадрат -->
<StackPanel Spacing="8">
<Rectangle Width="80" Height="80"
Fill="#3b82f6"
Stroke="#1e40af"
StrokeThickness="2"/>
<TextBlock Text="Square" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Трикутник -->
<StackPanel Spacing="8">
<Polygon Points="40,0 80,80 0,80"
Fill="#22c55e"
Stroke="#16a34a"
StrokeThickness="2"/>
<TextBlock Text="Triangle" HorizontalAlignment="Center"/>
</StackPanel>
<!-- Зірка -->
<StackPanel Spacing="8">
<Polygon Points="40,0 49,28 78,28 55,45 64,73 40,56 16,73 25,45 2,28 31,28"
Fill="#f59e0b"
Stroke="#d97706"
StrokeThickness="2"/>
<TextBlock Text="Star" HorizontalAlignment="Center"/>
</StackPanel>
</StackPanel>
Мета: Навчитися створювати складні фігури через Path та PathGeometry.
Завдання:
Створіть іконку або логотип через Path:
Критерії успіху:
Підказка (іконка будинку):
<Path Width="100" Height="100" Stretch="Uniform"
Fill="#3b82f6"
Stroke="#1e40af"
StrokeThickness="2">
<Path.Data>
<!-- Дах -->
M 10,50 L 50,10 L 90,50
<!-- Стіни -->
L 90,90 L 10,90 Z
<!-- Двері -->
M 35,90 L 35,60 L 65,60 L 65,90
<!-- Вікно -->
M 25,40 L 25,25 L 40,25 L 40,40 Z
</Path.Data>
</Path>
Підказка (іконка серця):
<Path Data="M 50,20 C 50,10 40,0 30,0 C 15,0 0,15 0,30 C 0,45 15,60 50,90 C 85,60 100,45 100,30 C 100,15 85,0 70,0 C 60,0 50,10 50,20 Z"
Fill="#ef4444"
Stroke="#dc2626"
StrokeThickness="2"
Width="100"
Height="100"
Stretch="Uniform"/>
Мета: Навчитися створювати складні візуальні ефекти через Brushes.
Завдання:
Створіть складний фон для вікна або панелі:
Критерії успіху:
Підказка:
<Grid>
<!-- Базовий градієнт -->
<Grid.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#667eea" Offset="0"/>
<GradientStop Color="#764ba2" Offset="0.5"/>
<GradientStop Color="#f093fb" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<!-- VisualBrush патерн -->
<Rectangle Opacity="0.1">
<Rectangle.Fill>
<VisualBrush TileMode="Tile" Viewport="0,0,0.1,0.1">
<VisualBrush.Visual>
<Canvas Width="100" Height="100">
<Ellipse Width="40" Height="40"
Fill="White"
Canvas.Left="30"
Canvas.Top="30"/>
<Rectangle Width="20" Height="20"
Fill="White"
Canvas.Left="10"
Canvas.Top="10"/>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
<!-- Вміст -->
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="Beautiful Background"
FontSize="48"
FontWeight="Bold"
Foreground="White"
Effect="{StaticResource DropShadowEffect}"/>
</StackPanel>
</Grid>
Додатково (анімація градієнта):
// В code-behind
private void AnimateGradient()
{
var gradient = (LinearGradientBrush)MyGrid.Background;
var animation = new ColorAnimation
{
To = Colors.Orange,
Duration = TimeSpan.FromSeconds(2),
AutoReverse = true,
RepeatBehavior = RepeatBehavior.Forever
};
gradient.GradientStops[0].BeginAnimation(GradientStop.ColorProperty, animation);
}
WPF надає потужні інструменти для роботи з 2D графікою та мультимедіа. Від простих фігур до складних векторних зображень, від однотонних кольорів до радіальних градієнтів, від статичних елементів до відео — все це доступно "з коробки".
Ключові висновки:
📐 Shapes
🎨 Path
🌈 Brushes
🔀 Geometries
🔄 Transforms
🎬 MediaElement
Що далі?
Наступна стаття — Avalonia Graphics покаже відмінності в графічній системі Avalonia.