Создание простого приложения Win2D
В этом руководстве представлены некоторые основные возможности рисования Win2D. Вы изучите следующие темы:
- Добавьте Win2D в проект XAML XAML C#.
- Рисование текста и геометрии.
- Применение эффектов фильтра.
- Анимируйте содержимое Win2D.
- Следуйте рекомендациям Win2D.
Настройка компьютера разработки
Обязательно настройте компьютер со всеми необходимыми средствами:
- Установка Visual Studio
- Включите пакет SDK UWP или Windows (в зависимости от ваших потребностей), 17763+
- При использовании UWP убедитесь, что также включен режим разработчика
Создание проекта Win2D
Выполните действия, описанные в кратком руководстве по Win2D "Hello, World!", чтобы создать проект с помощью Win2D и добавить ссылку на пакет NuGet Win2D. Вы можете использовать WinUI 3 (пакет SDK для приложений Windows) или универсальная платформа Windows (UWP).
Добавление Win2D CanvasControl в XAML приложения
- Чтобы использовать Win2D, вам нужно где-то нарисовать графику. В приложении XAML самый простой способ сделать это — добавить CanvasControl на страницу XAML.
Прежде чем продолжить, сначала убедитесь, что для параметра архитектуры проекта задано x86
значение или x64
нетAny CPU
. Win2D реализован в C++, поэтому проекты, использующие Win2D, должны быть ориентированы на определенную архитектуру ЦП.
MainPage.xaml
Перейдите в проект, дважды щелкнув его в Обозреватель решений. Откроется файл. Для удобства можно дважды нажать кнопку XAML на вкладке конструктора; Это позволит скрыть визуальный конструктор и зарезервировать все пространство для представления кода.Перед добавлением элемента управления сначала необходимо указать XAML, где определен CanvasControl . Для этого перейдите к определению элемента Page и добавьте следующую директиву:
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
Теперь xaml должен выглядеть следующим образом:
<Page
...
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
mc:Ignorable="d">
- Теперь добавьте новый элемент
canvas:CanvasControl
в качестве дочернего элемента в корневой элемент Grid . Присвойте элементу управления имя, например "canvas". Теперь xaml должен выглядеть следующим образом:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<canvas:CanvasControl x:Name="canvas"/>
</Grid>
- Затем определите обработчик событий для события Draw . CanvasControl вызывает
Draw
всякий раз, когда приложению требуется рисование или перерисовка содержимого. Проще всего позволить Visual Studio AutoComplete помочь вам. В определении CanvasControl начните вводить новый атрибут для обработчикаDraw
событий:
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />
Примечание.
После ввода Draw="
в Visual Studio должен появиться окно с запросом на автоматическое заполнение правильного определения обработчика событий. Нажмите клавишу TAB, чтобы принять обработчик событий Visual Studio по умолчанию. Это также автоматически добавит правильный форматированный метод обработчика событий в коде позади ('MainPage.xaml.cs'' ). Не беспокойтесь, если вы не использовали автозавершение; Вы можете вручную добавить метод обработчика событий на следующем шаге.
Рисование первого текста в Win2D
Теперь давайте перейдем к коду C#. Откройте
MainPage.xaml.cs
из Обозреватель решений.В верхней части файла C# находятся различные определения пространства имен. Добавьте приведенные ниже пространства имен.
using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
- Затем вы увидите следующий пустой обработчик событий, который был вставлен автозавершением:
private void canvas_Draw(
Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}
(Если вы не использовали автозавершение на предыдущем шаге, добавьте этот код сейчас.)
- Параметр CanvasDrawEventArgs предоставляет элемент, DrawingSession, который является типом CanvasDrawingSession. Этот класс предоставляет большую часть основных функций рисования в Win2D: он имеет такие методы, как CanvasDrawingSession.DrawRectangle, CanvasDrawingSession.DrawImage, и метод, который необходимо нарисовать текст, CanvasDrawingSession.DrawText.
Добавьте следующий код в метод canvas_Draw
:
args.DrawingSession.DrawText("Hello, World!", 100, 100, Colors.Black);
Первый аргумент — это строка, "Hello, World!"
которую требуется отобразить Win2D. Два "100" сообщают Win2D, чтобы смещать этот текст на 100 ДИП (независимых от устройства пикселей) справа и вниз. Наконец, Colors.Black
определяет цвет текста.
- Теперь вы готовы запустить свое первое приложение Win2D. Нажмите клавишу F5 для компиляции и запуска. Вы должны увидеть пустое окно с "Hello, world!" в черном.
Правильное удаление ресурсов Win2D
- Прежде чем продолжить рисование других типов содержимого, сначала следует добавить код, чтобы убедиться, что приложение избегает утечки памяти. Большинство приложений Win2D, написанных на языке .NET и используя элемент управления Win2D, например CanvasControl , необходимо выполнить следующие действия. Строго говоря, простое приложение Hello, world не влияет, но это хорошая практика, чтобы следовать в целом.
Дополнительные сведения см. в разделе "Избегание утечки памяти".
Откройте
MainPage.xaml
и найдите элемент XAML страницы , содержащий элемент CanvasControl. Он должен быть первым элементом в файле.Добавьте обработчик для события
Unloaded
. Код XAML должен выглядеть следующим образом:
<Page
...
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
mc:Ignorable="d"
Unloaded="Page_Unloaded">
MainPage.xaml.cs
Перейдите к обработчику событий и найдите егоPage_Unloaded
. Добавьте следующий код:
void Page_Unloaded(object sender, RoutedEventArgs e)
{
this.canvas.RemoveFromVisualTree();
this.canvas = null;
}
- Если приложение содержит несколько элементов управления Win2D, необходимо повторить описанные выше действия для каждой страницы XAML, содержащей элемент управления Win2D. В настоящее время приложение имеет только один CanvasControl , поэтому все готово.
Рисование некоторых фигур
- Так же легко добавить 2D-геометрию в приложение. Добавьте следующий код в конец
canvas_Draw
:
args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);
Аргументы этих двух методов похожи DrawText
на . Круг определяется точкой центра (125, 125), радиусом (100) и цветом (зеленым). Строка определяется началом (0, 0), концом (50, 200) и цветом (красным).
- Теперь нажмите клавишу F5, чтобы запустить приложение. Вы должны увидеть "Привет, мир!" вместе с зеленым кругом и красной линией.
Возможно, вам интересно, как управлять более сложными параметрами рисования, такими как толщина линии и дефисы, или более сложные варианты заливки, такие как использование кистей. Win2D предоставляет все эти параметры и многое другое и упрощает их использование при необходимости. Draw(...)
Все методы предлагают множество перегрузок, которые могут принимать дополнительные параметры, такие как CanvasTextFormat (семейство шрифтов, размер и т. д.) и CanvasStrokeStyle (дефисы, точки, конечные капки и т. д.). Чтобы узнать больше об этих вариантах, вы можете изучить область API.
Динамическое создание параметров рисования
- Теперь добавим несколько различных, рисуя кучу фигур и текста со случайными цветами.
Добавьте следующий код в верхнюю часть MainPage
класса. Это вспомогательные функции для создания случайных значений, которые будут использоваться при рисовании:
Random rnd = new Random();
private Vector2 RndPosition()
{
double x = rnd.NextDouble() * 500f;
double y = rnd.NextDouble() * 500f;
return new Vector2((float)x, (float)y);
}
private float RndRadius()
{
return (float)rnd.NextDouble() * 150f;
}
private byte RndByte()
{
return (byte)rnd.Next(256);
}
canvas_Draw
Измените метод для рисования с помощью этих случайных параметров:
private void canvas_Draw(
Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
args.DrawingSession.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
args.DrawingSession.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
args.DrawingSession.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}
Давайте разберем, как DrawText
изменилось. "Hello, World!"
остается таким же, как и раньше. Параметры смещения x и y были заменены одним элементом System.Numerics.Vector2 , созданным RndPosition
. Наконец, вместо использования предопределенного цвета можно определить цвет Color.FromArgb
с помощью значений A, R, G и B. A — альфа- или уровень непрозрачности; В этом случае всегда требуется полностью непрозрачный (255).
DrawCircle
и DrawLine
работает аналогично DrawText
.
- Наконец, заключите код рисования в
for
цикл. В конечном итоге вам потребуется следующийcanvas_Draw
код:
for (int i = 0; i < 100; i++)
{
args.DrawingSession.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
args.DrawingSession.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
args.DrawingSession.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}
- Снова запустите приложение. Вы должны увидеть целый ряд текста, линий и кругов со случайными позициями и размерами.
Применение эффекта изображения к содержимому
Эффекты изображения, также известные как эффекты фильтра, — это графические преобразования, применяемые к данным пикселей. Насыщенность, оттенок поворота и размытие Гауссиана являются некоторыми общими эффектами изображения. Эффекты изображения можно объединить, создавая сложный визуальный вид для минимальной работы.
Эффекты изображения используются путем предоставления исходного изображения (содержимого, с которым вы начинаете), создания эффекта, например GaussianBlurEffect, задания свойств, таких как BlurAmount, а затем рисование выходных данных эффекта.DrawImage
Чтобы применить эффект изображения к тексту и фигурам, необходимо сначала отобразить это содержимое в CanvasCommandList. Этот объект можно использовать как входные данные для вашего эффекта.
- Измените
canvas_Draw
метод, чтобы использовать следующий код:
CanvasCommandList cl = new CanvasCommandList(sender);
using (CanvasDrawingSession clds = cl.CreateDrawingSession())
{
for (int i = 0; i < 100; i++)
{
clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}
}
Точно так же, как вы получаете CanvasDrawingSession
, из CanvasDrawEventArgs
которого можно рисовать, вы можете создать из CanvasDrawingSession
нее CanvasCommandList
. Единственное различие заключается в том, что при рисовании в сеансе рисования списка команд (clds), вы не выполняете прямую отрисовку в CanvasControl. Вместо этого список команд — это промежуточный объект, в который хранятся результаты отрисовки для последующего использования.
Возможно, вы заметили using
блок, который упаковывает сеанс рисования списка команд. Сеансы рисования реализуют IDisposable и должны быть удалены при завершении отрисовки ( using
блок делает это). Полученное CanvasDrawingSession
автоматически закрыто для CanvasDrawEventArgs
вас, но необходимо удалить все сеансы рисования, созданные явным образом.
- Наконец, определите
GaussianBlurEffect
, добавив следующий код в конецcanvas_Draw
метода:
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
- Снова запустите приложение. Вы должны видеть строки, текст и круги с размытым внешним видом.
Анимация приложения с помощью CanvasAnimatedControl
. Win2D позволяет обновлять и анимировать содержимое в режиме реального времени, например изменяя радиус размытия размытия размывателя с каждым кадром. Для этого вы будете использовать CanvasAnimatedControl.
CanvasControl лучше всего подходит для в основном статического графического содержимого. Оно вызывает Draw
событие только в том случае, если содержимое должно быть обновлено или перезабрано. Если у вас постоянно меняющееся содержимое, вместо этого следует рассмотреть возможность использования CanvasAnimatedControl
. Два элемента управления работают очень аналогично, за исключением CanvasAnimatedControl
периодического вызова Draw
события; по умолчанию он вызывается 60 раз в секунду.
- Чтобы переключиться
CanvasAnimatedControl
на , перейдитеMainPage.xaml
к разделу , удалите строку CanvasControl и замените ее следующим кодом XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>
Как и в CanvasControl, пусть автозавершение создает Draw
обработчик событий для вас. По умолчанию Visual Studio будет называть этот обработчик canvas_Draw_1
, так как canvas_Draw
уже существует. Здесь мы переименовали метод canvas_AnimatedDraw
, чтобы убедиться, что это другое событие.
Кроме того, вы также обрабатываете новое событие CreateResources. Еще раз позвольте автозавершения создать обработчик.
Теперь, когда приложение будет перерисовывать по 60 кадров в секунду, более эффективно создавать визуальные ресурсы Win2D один раз и повторно использовать их с каждым кадром. Это неэффективно для создания CanvasCommandList
и рисования 300 элементов в него 60 раз в секунду, когда содержимое остается статическим. CreateResources
— это событие, которое запускается только в том случае, если Win2D определяет необходимость повторного создания визуальных ресурсов, например при загрузке страницы.
- Переключитесь обратно
MainPage.xaml.cs
на .canvas_Draw
Найдите метод, который должен выглядеть следующим образом:
private void canvas_Draw(
Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
CanvasCommandList cl = new CanvasCommandList(sender);
using (CanvasDrawingSession clds = cl.CreateDrawingSession())
{
for (int i = 0; i < 100; i++)
{
clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}
}
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
}
Подавляющее большинство существующего кода рисования не требуется выполнять с каждым кадром: список команд, содержащий текст, строки и круги, остается одинаковым с каждым кадром, и единственное, что изменяет радиус размытия. Поэтому этот статический код можно переместить в CreateResources
.
Для этого сначала вырезать (CTRL+X) все содержимое canvas_Draw
, за исключением самой последней строки (args.DrawingSession.DrawImage(blur);
). Теперь вы можете удалить оставшуюся часть canvas_Draw
, так как она больше не нужна: отзыв, имеющий CanvasAnimatedControl
собственное отдельное Draw
событие.
- Найдите автоматически созданный
canvas_CreateResources
метод:
private void canvas_CreateResources(
Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender,
Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{}
Вставьте (CTRL+V) ранее вырезанный код в этот метод. Затем переместите объявление GaussianBlurEffect
вне текста метода, чтобы переменная стала членом класса MainPage. Теперь код должен выглядеть так, как показано ниже.
GaussianBlurEffect blur;
private void canvas_CreateResources(
Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender,
Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{
CanvasCommandList cl = new CanvasCommandList(sender);
using (CanvasDrawingSession clds = cl.CreateDrawingSession())
{
for (int i = 0; i < 100; i++)
{
clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}
}
blur = new GaussianBlurEffect()
{
Source = cl,
BlurAmount = 10.0f
};
}
- Теперь вы можете анимировать размытие Гауссиана.
canvas_DrawAnimated
Найдите метод и добавьте следующий код:
private void canvas_DrawAnimated(
Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender,
Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
{
float radius = (float)(1 + Math.Sin(args.Timing.TotalTime.TotalSeconds)) * 10f;
blur.BlurAmount = radius;
args.DrawingSession.DrawImage(blur);
}
Это считывает общее истекшее время, предоставленное CanvasAnimatedDrawEventArgs , и использует это для вычисления требуемой суммы размытия; функция синуса предоставляет интересный вариант с течением времени. Наконец, GaussianBlurEffect
отрисовывается.
- Запустите приложение, чтобы увидеть размытое содержимое с течением времени.
Поздравляем с завершением этого краткого руководства по началу работы! Надеюсь, вы узнали, как можно использовать Win2D для создания богатой анимированной визуальной сцены с несколькими строками кода C# и XAML.
Windows developer