Desktop UI

2D Графіка та Мультимедіа у WPF

Векторна графіка через Shapes та Path. Градієнти, геометрії, трансформації. MediaElement для відео та аудіо. Створення складних візуальних ефектів.

2D Графіка та Мультимедіа у WPF

WPF — це не просто фреймворк для кнопок та текстових полів. Це потужна графічна система, побудована на DirectX, що дозволяє створювати складну векторну графіку, градієнти, трансформації та навіть відтворювати відео прямо в інтерфейсі.

Уявіть: ви можете намалювати будь-яку фігуру через Path з SVG-подібним синтаксисом, застосувати градієнтний фон з кількома кольорами, обернути елемент на 45 градусів, і все це буде масштабуватися без втрати якості, бо це вектор. Або вставити відео як фон для кнопки через MediaElement. WPF робить це природно та елегантно.

У цій статті ми детально розберемо всі графічні можливості WPF: від базових фігур (Rectangle, Ellipse) до складних Path з кривими Безьє, від простих кольорів до радіальних градієнтів, від статичних зображень до відео. Ви навчитесь створювати професійні візуальні ефекти без зовнішніх бібліотек.

Словник теми:Shape — базовий клас для геометричних фігур (Rectangle, Ellipse, Path). Path — універсальна фігура з PathGeometry. PathGeometry — опис складної фігури через команди (M, L, C, A, Z). Brush — спосіб заповнення (SolidColorBrush, LinearGradientBrush). Geometry — математичний опис форми без візуального представлення. Transform — трансформація елемента (обертання, масштабування). MediaElement — контрол для відтворення відео та аудіо. VisualBrush — Brush, що рендерить інший Visual як текстуру.

Shapes: базові геометричні фігури

WPF надає набір готових фігур через класи, що успадковуються від Shape.

Rectangle: прямокутник

<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)...

Ellipse: коло та еліпс

<!-- Коло -->
<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)...

Line: лінія

<Line X1="0" Y1="0" X2="200" Y2="100"
      Stroke="#64748b"
      StrokeThickness="2"/>

Властивості:

  • X1, Y1 — початкова точка
  • X2, Y2 — кінцева точка
  • Stroke — колір лінії
  • StrokeThickness — товщина

Polygon: багатокутник (замкнений)

<!-- Трикутник -->
<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)...

Polyline: ламана лінія (незамкнена)

<Polyline Points="0,50 50,0 100,50 150,0 200,50"
          Stroke="#3b82f6"
          StrokeThickness="3"
          Fill="Transparent"/>

Різниця з Polygon: Polyline не замикає фігуру автоматично.

StrokeDashArray: пунктирні лінії

<!-- Пунктирна лінія -->
<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: складні фігури

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>

Mini-language: компактний синтаксис

Замість багатослівного 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,yMove to (переміститися)M 10,20
L x,yLine to (лінія до)L 50,60
H xHorizontal line (горизонтальна лінія)H 100
V yVertical line (вертикальна лінія)V 80
C x1,y1 x2,y2 x,yCubic Bezier curve (кубічна крива)C 20,20 40,20 50,10
Q x1,y1 x,yQuadratic Bezier curve (квадратична крива)Q 30,30 50,10
A rx,ry angle large sweep x,yArc (дуга)A 30,30 0 0 1 50,50
ZClose 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)...

SVG → Path Data

Багато графічних редакторів (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"/>
Інструменти для конвертації: Використовуйте онлайн-конвертери SVG → XAML або плагіни для Figma/Illustrator, що експортують безпосередньо в XAML Path. Це економить час при роботі з дизайнерами.

Brushes: способи заповнення

Brush визначає, як заповнюється фігура або фон елемента. WPF підтримує кілька типів Brush.

SolidColorBrush: однотонний колір

<Rectangle Fill="#3b82f6"/>

<!-- Або через об'єкт -->
<Rectangle>
    <Rectangle.Fill>
        <SolidColorBrush Color="#3b82f6"/>
    </Rectangle.Fill>
</Rectangle>

LinearGradientBrush: лінійний градієнт

<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)...

RadialGradientBrush: радіальний градієнт

<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)...

ImageBrush: зображення як заповнення

<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: рендеринг іншого Visual

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>
Use case для VisualBrush: Створення watermark (водяних знаків), ефектів відображення (reflection), повторюваних патернів з UI-елементів, preview елементів у мініатюрі.

Geometries: математичні форми без візуалізації

Geometry — це математичний опис форми без візуального представлення. Використовується для Clip (обрізання), Data у Path, або як основа для Drawing.

RectangleGeometry, EllipseGeometry

<!-- Обрізання елемента по колу -->
<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>

CombinedGeometry: комбінування форм

<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)...

PathGeometry: складні геометрії

<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>

DrawingGroup та DrawingImage: векторні зображення

Drawing — це легковаговий спосіб створення векторної графіки без повноцінних UI-елементів. Використовується для іконок, складних векторних зображень.

GeometryDrawing

<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:

  • Легковаговіший (менше пам'яті)
  • Швидший рендеринг
  • Можна використовувати як ImageSource
  • Ідеально для іконок

Недоліки:

  • Немає інтерактивності (події, hover)
  • Немає Layout (фіксовані координати)
Коли використовувати Drawing: Для статичних іконок, логотипів, складних векторних зображень без інтерактивності. Для інтерактивних елементів використовуйте Shape або Path.

Transforms: трансформації елементів

Transforms дозволяють обертати, масштабувати, переміщувати та нахиляти елементи.

RotateTransform: обертання

<Rectangle Width="100" Height="50" Fill="#3b82f6">
    <Rectangle.RenderTransform>
        <RotateTransform Angle="45" CenterX="50" CenterY="25"/>
    </Rectangle.RenderTransform>
</Rectangle>

Властивості:

  • Angle — кут обертання в градусах
  • CenterX, CenterY — точка обертання

ScaleTransform: масштабування

<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 — точка масштабування

TranslateTransform: переміщення

<Ellipse Width="50" Height="50" Fill="#22c55e">
    <Ellipse.RenderTransform>
        <TranslateTransform X="100" Y="50"/>
    </Ellipse.RenderTransform>
</Ellipse>

Властивості:

  • X, Y — зміщення по осях

SkewTransform: нахил

<Rectangle Width="100" Height="50" Fill="#f59e0b">
    <Rectangle.RenderTransform>
        <SkewTransform AngleX="20" AngleY="0"/>
    </Rectangle.RenderTransform>
</Rectangle>

Властивості:

  • AngleX, AngleY — кут нахилу по осях

TransformGroup: комбінування

<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)...


MediaElement: відео та аудіо

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();
}

Властивості MediaElement

ВластивістьОпис
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)

Події MediaElement

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 не підтримує всі кодеки "з коробки". Підтримка залежить від встановлених кодеків у Windows. Для максимальної сумісності використовуйте MP4 (H.264) для відео та MP3 для аудіо.

MediaTimeline: анімація через Storyboard

<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 (затримка, тривалість, повторення).


Практичні завдання

Рівень 1: Набір геометричних фігур

Мета: Навчитися використовувати базові Shape елементи.

Завдання:

Створіть композицію з геометричних фігур:

  1. Фігури:
    • Коло (Ellipse) — червоне
    • Квадрат (Rectangle) — синій
    • Трикутник (Polygon) — зелений
    • Зірка (Polygon або Path) — жовта
  2. Стилізація:
    • Кожна фігура має Fill та Stroke
    • StrokeThickness = 2
    • Розташуйте фігури в Grid або StackPanel
  3. Додатково:
    • Додайте підписи під кожною фігурою
    • Використайте градієнтне заповнення для однієї з фігур
    • Додайте hover ефект (зміна кольору при наведенні)

Критерії успіху:

  • Всі 4 фігури відображаються правильно
  • Використано Fill та Stroke
  • Композиція виглядає акуратно
  • Додаткові ефекти працюють

Підказка:

<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>

Рівень 2: SVG-подібний малюнок через Path

Мета: Навчитися створювати складні фігури через Path та PathGeometry.

Завдання:

Створіть іконку або логотип через Path:

  1. Варіанти:
    • Іконка будинку
    • Іконка серця
    • Іконка хмари
    • Власний дизайн
  2. Вимоги:
    • Використайте Path з Data mini-language
    • Мінімум 5 команд (M, L, C, A, Z)
    • Fill та Stroke
    • Розмір 100x100 або більше
  3. Додатково:
    • Створіть кілька варіантів з різними кольорами
    • Додайте градієнтне заповнення
    • Додайте анімацію (обертання або пульсація)

Критерії успіху:

  • Path відображається правильно
  • Використано mini-language синтаксис
  • Фігура виглядає акуратно
  • Додаткові ефекти працюють

Підказка (іконка будинку):

<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"/>

Рівень 3: Градієнтний фон із VisualBrush ефектом

Мета: Навчитися створювати складні візуальні ефекти через Brushes.

Завдання:

Створіть складний фон для вікна або панелі:

  1. Базовий фон:
    • LinearGradientBrush або RadialGradientBrush
    • Мінімум 3 кольори
    • Плавні переходи
  2. VisualBrush патерн:
    • Створіть повторюваний патерн через VisualBrush
    • Використайте геометричні фігури або Path
    • TileMode="Tile"
    • Напівпрозорість для накладання на градієнт
  3. Додатково:
    • Додайте анімацію градієнта (зміна кольорів)
    • Створіть кілька варіантів фону (світлий/темний)
    • Додайте ефект паралакса (різна швидкість анімації для шарів)

Критерії успіху:

  • Градієнтний фон відображається правильно
  • VisualBrush патерн працює
  • Композиція виглядає професійно
  • Додаткові ефекти працюють

Підказка:

<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

Rectangle, Ellipse, Line, Polygon, Polyline для базових фігур. Fill, Stroke, StrokeThickness для стилізації.

🎨 Path

Універсальна фігура з PathGeometry. Mini-language (M, L, C, A, Z) для складних форм. SVG-сумісний синтаксис.

🌈 Brushes

SolidColorBrush, LinearGradientBrush, RadialGradientBrush, ImageBrush, VisualBrush для різних ефектів заповнення.

🔀 Geometries

RectangleGeometry, EllipseGeometry, CombinedGeometry для математичних форм. Використання в Clip та Drawing.

🔄 Transforms

RotateTransform, ScaleTransform, TranslateTransform, SkewTransform для трансформацій. TransformGroup для комбінування.

🎬 MediaElement

Відтворення відео та аудіо. Play(), Pause(), Stop() для контролю. MediaTimeline для анімацій.

Що далі?

Наступна стаття — Avalonia Graphics покаже відмінності в графічній системі Avalonia.


Словник термінів

Shape — базовий клас для геометричних фігур у WPF (Rectangle, Ellipse, Line, Polygon, Polyline, Path).Path — універсальна фігура, що може описати будь-яку форму через PathGeometry.PathGeometry — опис складної фігури через набір команд (M, L, C, A, Z).Mini-language — компактний синтаксис для опису Path через Data атрибут (M 10,20 L 50,60 Z).Fill — заповнення фігури (колір або Brush).Stroke — обведення фігури (колір або Brush).StrokeThickness — товщина обведення в пікселях.StrokeDashArray — патерн пунктирної лінії (довжина штриха та проміжку).Brush — спосіб заповнення елемента (SolidColorBrush, LinearGradientBrush, тощо).SolidColorBrush — однотонний колір.LinearGradientBrush — лінійний градієнт з кількома кольорами.RadialGradientBrush — радіальний градієнт (від центру до країв).ImageBrush — зображення як заповнення з підтримкою TileMode.VisualBrush — рендеринг іншого Visual елемента як текстури.GradientStop — колір на певній позиції в градієнті (Offset від 0 до 1).Geometry — математичний опис форми без візуального представлення.RectangleGeometry — геометрія прямокутника.EllipseGeometry — геометрія еліпса.PathGeometry — складна геометрія з кількох сегментів.CombinedGeometry — комбінування двох геометрій (Union, Intersect, Xor, Exclude).GeometryCombineMode — режим комбінування геометрій.Drawing — легковаговий спосіб створення векторної графіки без UI-елементів.GeometryDrawing — Drawing з геометрією та Brush.DrawingGroup — група Drawing елементів.DrawingImage — ImageSource з Drawing (для використання в Image).Transform — трансформація елемента (обертання, масштабування, переміщення, нахил).RotateTransform — обертання навколо точки.ScaleTransform — масштабування по осях X та Y.TranslateTransform — переміщення по осях X та Y.SkewTransform — нахил по осях X та Y.TransformGroup — група трансформацій, що застосовуються послідовно.MediaElement — контрол для відтворення відео та аудіо файлів.LoadedBehavior — поведінка MediaElement при завантаженні (Manual, Play, Pause, Stop).MediaTimeline — Timeline для контролю відтворення медіа через Storyboard.Stretch — режим масштабування (None, Fill, Uniform, UniformToFill).TileMode — режим повторення для ImageBrush та VisualBrush (None, Tile, FlipX, FlipY, FlipXY).

Додаткові ресурси

📖 WPF Graphics Docs

Офіційна документація про графіку у WPF.

🎨 Shapes and Drawing

Детальна стаття про Shapes та Drawing.

🌈 Brushes Guide

Повний гайд по Brushes у WPF.

🎬 MediaElement Tutorial

Туторіал по MediaElement.

📚 Попередня стаття: Avalonia Animations

Повернутися до Avalonia анімацій.

📚 Наступна стаття: Avalonia Graphics

Дізнатися про графіку в Avalonia.