다음을 통해 공유


간단한 Win2D 앱 빌드

이 자습서에서는 Win2D의 몇 가지 기본 그리기 기능을 소개합니다. 이 문서에서 배울 내용은 다음과 같습니다.

  • C# XAML Windows 프로젝트에 Win2D를 추가합니다.
  • 텍스트 및 기하 도형을 그립니다.
  • 필터 효과를 적용합니다.
  • Win2D 콘텐츠에 애니메이션 효과를 줍니다.
  • Win2D 모범 사례를 준수합니다.

장치 머신 설정

필요한 모든 도구를 사용하여 컴퓨터를 설정해야 합니다.

새 Win2D 프로젝트 생성

Win2D "Hello, World!" 빠른 시작의 단계에 따라 Win2D를 사용하여 새 프로젝트를 만들고 Win2D NuGet 패키지에 대한 참조를 추가합니다. WinUI 3(Windows 앱 SDK) 또는 UWP(유니버설 Windows 플랫폼)를 사용할 수 있습니다.

앱의 XAML에 Win2D CanvasControl 추가

  1. Win2D를 사용하려면 그래픽을 그릴 곳이 필요합니다. XAML 앱에서 이 작업을 수행하는 가장 간단한 방법은 XAML 페이지에 CanvasControl을 추가하는 것입니다.

계속하기 전에 먼저 프로젝트의 아키텍처 옵션이 x86 또는 x64 아닌 Any CPU로 설정되었는지 여부를 확인합니다. Win2D는 C++에서 구현되므로 Win2D를 사용하는 프로젝트는 특정 CPU 아키텍처를 대상으로 해야 합니다.

  1. 솔루션 탐색기 두 번 클릭하여 프로젝트의 MainPage.xaml로 이동합니다. 그러면 파일이 열립니다. 편의를 위해 디자이너 탭에서 XAML 단추를 두 번 클릭할 수 있습니다. 그러면 비주얼 디자이너가 숨겨지고 코드 뷰에 대한 모든 공간이 예약됩니다.

  2. 컨트롤을 추가하기 전에 먼저 CanvasControl이 정의된 위치를 XAML에 알려야 합니다. 이렇게 하려면 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">
  1. 이제 루트 Grid 요소에 자식 요소로 새 canvas:CanvasControl를 추가합니다. 컨트롤에 이름(예: "canvas")을 지정합니다. 이제 XAML이 다음과 같이 표시되어야 합니다.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasControl x:Name="canvas"/>
</Grid>
  1. 다음은, Draw 이벤트에 대한 이벤트 처리기를 정의합니다. CanvasControl 은 앱이 Draw 콘텐츠를 그리거나 다시 그려야 할 때마다 발생합니다. 가장 쉬운 방법은 Visual Studio 자동 완성을 지원하는 것입니다. CanvasControl 정의에서 Draw 이벤트 처리기에 대한 새 특성을 입력하기 시작합니다.
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

참고 항목

Draw="에 입력한 후에는 Visual Studio에서 이벤트 처리기에 대한 올바른 정의를 자동으로 채울 수 있도록 하는 상자를 팝업으로 표시해야 합니다. Tab 키를 눌러 Visual Studio의 기본 이벤트 처리기를 수락합니다. 또한 코드 숨김('MainPage.xaml.cs')에 올바른 형식의 이벤트 처리기 메서드가 자동으로 추가됩니다. 자동 완성을 사용하지 않은 경우 걱정하지 마세요. 다음 단계에서 이벤트 처리기 메서드를 수동으로 추가할 수 있습니다.

Win2D에서 첫 번째 텍스트 그리기

  1. 이제 뒤에 있는 C# 코드로 이동해 보겠습니다. 솔루션 탐색기에서 MainPage.xaml.cs를 엽니다.

  2. C# 파일의 맨 위에는 다양한 네임스페이스 정의가 있습니다. 다음 네임스페이스를 추가합니다.

using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
  1. 다음으로 자동 완성에 의해 삽입된 다음 빈 이벤트 처리기가 표시됩니다.
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}

(이전 단계에서 자동 완성을 사용하지 않은 경우 지금 이 코드를 추가합니다.)

  1. 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 DIP(디바이스 독립적 픽셀)로 오프셋하도록 지시합니다. 마지막으로 Colors.Black는 텍스트의 색을 정의합니다.

  1. 이제 첫 번째 Win2D 앱을 실행할 준비가 되었습니다. F5 키를 눌러 컴파일하고 시작합니다. "Hello, world!"가 검은색으로 표시된 빈 창이 표시됩니다.

Win2D 리소스를 올바르게 삭제합니다.

  1. 다른 종류의 콘텐츠를 계속 그리기 전에 먼저 일부 코드를 추가하여 앱에서 메모리 누수를 방지해야 합니다. .NET 언어로 작성되고 CanvasControl과 같은 Win2D 컨트롤을 사용하는 대부분의 Win2D 애플리케이션은 아래 단계를 따라야 합니다. 엄밀히 말하면 간단한 "Hello, world" 앱은 영향을 받지 않지만 일반적으로 따르는 것이 좋습니다.

자세한 내용은 메모리 누수 방지를 참조하세요.

  1. MainPage.xaml을 열고 CanvasControl이 포함된 Page XAML 요소를 찾습니다. 파일의 첫 번째 요소여야 합니다.

  2. 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">
  1. MainPage.xaml.cs로 이동하여 Page_Unloaded 이벤트 처리기를 찾습니다. 다음 코드를 추가합니다.
void Page_Unloaded(object sender, RoutedEventArgs e)
{
    this.canvas.RemoveFromVisualTree();
    this.canvas = null;
}
  1. 앱에 여러 Win2D 컨트롤이 포함된 경우 Win2D 컨트롤이 포함된 각 XAML 페이지에 대해 위의 단계를 반복해야 합니다. 앱에는 현재 단일 CanvasControl만 있으므로 모두 완료됩니다.

일부 도형 그리기

  1. 앱에 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) 및 색(빨강)으로 정의됩니다.

  1. 이제, F5 키를 눌러 앱을 실행합니다. 녹색 원과 빨간색 선과 함께 "Hello, world!"가 표시됩니다.

선 두께 및 대시와 같은 고급 그리기 옵션 또는 브러시 사용과 같은 더 복잡한 채우기 옵션을 제어하는 방법을 궁금할 수 있습니다. Win2D는 이러한 옵션 등을 모두 제공하므로 원하는 경우 쉽게 사용할 수 있습니다. 모든 Draw(...) 메서드는 CanvasTextFormat(글꼴 패밀리, 크기 등) 및 CanvasStrokeStyle (대시, 점, 엔드캡 등)과 같은 추가 매개 변수를 허용할 수 있는 많은 오버로드를 제공합니다. 이러한 옵션에 대해 자세히 알아보려면 API 화면을 자유롭게 탐색하세요.

동적으로 그리기 매개 변수 생성

  1. 이제 임의 색으로 다양한 도형과 텍스트를 그려서 몇 가지 다양성을 추가해 보겠습니다.

다음 코드를 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);
}
  1. 다음과 같은 임의 매개 변수를 사용하여 그리도록 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 오프셋 매개 변수는 RndPosition에 의해 생성되는 단일 System.Numerics.Vector2로 대체되었습니다. 마지막으로 미리 정의된 색을 사용하는 대신 A, R, G 및 B 값을 사용하여 Color.FromArgb은 색을 정의할 수 있습니다. A는 알파이거나 불투명도 수준입니다. 이 경우 항상 완전히 불투명합니다(255).

DrawCircleDrawLineDrawText와 유사하게 작동합니다.

  1. 마지막으로 그리기 코드를 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()));
}
  1. 앱을 다시 실행합니다. 임의의 위치와 크기를 가진 텍스트, 선 및 원의 전체 무리가 표시됩니다.

콘텐츠에 이미지 효과 적용

필터 효과라고도 하는 이미지 효과는 픽셀 데이터에 적용되는 그래픽 변환입니다. 채도, 색조 회전 및 가우스 흐림 효과가 일반적인 이미지 효과입니다. 이미지 효과를 함께 연결하여 최소한의 노력으로 정교한 시각적 모양을 생성할 수 있습니다.

원본 이미지(시작 중인 콘텐츠)를 제공하고, GaussianBlurEffect와 같은 효과를 만들고, BlurAmount와 같은 속성을 설정한 다음, DrawImage와 함께 효과의 출력을 그립니다.

텍스트 및 도형에 이미지 효과를 적용하려면 먼저 해당 콘텐츠를 CanvasCommandList에 렌더링해야 합니다. 이 개체는 효과에 대한 입력으로 사용할 수 있습니다.

  1. 다음 코드를 사용하도록 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()));
    }
}

CanvasDrawEventArgs에서 CanvasDrawingSession를 얻어 그림을 그릴 수 있는 것처럼, CanvasCommandList에서 CanvasDrawingSession를 만들 수 있습니다. 유일한 차이점은 명령 목록의 그리기 세션(clds)에 그릴 때 CanvasControl에 직접 렌더링되지 않는다는 것입니다. 대신 명령 목록은 나중에 사용할 렌더링 결과를 저장하는 중간 개체입니다.

명령 목록의 그리기 세션을 래핑하는 using 블록을 발견했을 수 있습니다. 그리기 세션은 IDisposable을 구현하며 렌더링을 완료하면 삭제해야 합니다(using 블록에서 이 작업을 수행). CanvasDrawEventArgs에서 자동으로 가져오는 CanvasDrawingSession은 자동으로 닫히지만 명시적으로 만든 모든 그리기 세션을 삭제해야 합니다.

  1. 결국, 다음 코드를 canvas_Draw 메서드의 끝에 추가하여 GaussianBlurEffect를 정의합니다.
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
  1. 앱을 다시 실행합니다. 선, 텍스트 및 원 모양이 흐리게 표시됩니다.

CanvasAnimatedControl을 사용하여 앱에 애니메이션 효과 적용

. Win2D를 사용하면 가우스 흐림 효과의 흐림 반경을 모든 프레임으로 변경하는 등 실시간으로 콘텐츠를 업데이트하고 애니메이션 효과를 줄 수 있습니다. 이렇게 하려면 CanvasAnimatedControl를 사용합니다.

CanvasControl은 주로 정적 그래픽 콘텐츠에 가장 적합합니다. 콘텐츠를 업데이트하거나 다시 그려야 하는 경우에만 Draw 이벤트가 발생합니다. 콘텐츠를 지속적으로 변경하는 경우 대신 CanvasAnimatedControl을 사용하는 것이 좋습니다. 두 컨트롤은 Draw 이벤트를 주기적으로 발생시켜 CanvasAnimatedControl 제외하고 기본적으로 초당 60번 호출을 매우 유사하게 작동합니다.

  1. CanvasAnimatedControl로 전환하려면 MainPage.xaml로 이동하고, CanvasControl줄을 삭제하고 다음 XAML로 대체합니다.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>

CanvasControl과 마찬가지로 AutoComplete에서 e Draw 이벤트 처리기를 만들 수 있습니다. 기본적으로 canvas_Draw는 이미 존재하기 때문에 이 처리기의 이름을 canvas_Draw_1로 지정합니다. 여기서는 다른 이벤트임을 분명히 하기 위해 메서드 canvas_AnimatedDraw의 이름을 변경했습니다.

또한 새 이벤트인 CreateResources도 처리합니다. 다시 한번 자동 완성에서 처리기를 만들도록 합니다.

이제 앱이 초당 60프레임으로 다시 그리기 때문에 Win2D 시각적 리소스를 한 번 만들고 모든 프레임에서 다시 사용하는 것이 더 효율적입니다. 콘텐츠가 정적이면 CanvasCommandList를 만들어 초당 60번씩 300개의 요소를 만들고 그리는 것은 비효율적입니다. CreateResources은 페이지가 로드될 때와 같이 시각적 리소스를 다시 만들어야 한다고 Win2D에서 결정할 때만 발생하는 이벤트입니다.

  1. 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로 이동할 수 있습니다.

이렇게 하려면 마지막 줄(args.DrawingSession.DrawImage(blur);)을 제외하고 먼저 canvas_Draw의 전체 내용을 잘라내기(Ctrl+X)합니다. 이제 더 이상 필요하지 않으므로 나머지 canvas_Draw를 삭제할 수 있습니다. CanvasAnimatedControl에는 고유한 Draw 이벤트가 있다는 점을 기억하세요.

  1. 자동으로 생성된 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
    };
}
  1. 이제 가우시안 흐림 효과에 애니메이션 효과를 줍니다. 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이 렌더링됩니다.

  1. 앱을 실행하여 시간이 지남에 따라 흐리게 표시된 콘텐츠 변경을 확인합니다.

이 빠른 시작 튜토리얼을 완료하신 것을 축하드립니다! Win2D를 사용하여 몇 줄의 C# 및 XAML 코드로 풍부한 애니메이션 시각적 장면을 만드는 방법을 살펴보았으면 합니다.