Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa esercitazione presenta alcune delle funzionalità di disegno di base di Win2D. Si apprenderà come:
- Aggiungere Win2D a un'app WinUI (C#).
- Disegnare testo e geometria.
- Applicare effetti di filtro.
- Anima il tuo contenuto Win2D.
- Seguire le procedure consigliate di Win2D.
Fare riferimento al pacchetto NuGet Win2D
- Creare una nuova app WinUI e aggiungere il pacchetto NuGet Microsoft.Graphics.Win2D .
Aggiungere un oggetto CanvasControl Win2D al codice XAML dell'app
- Per usare Win2D, è necessario un punto per disegnare la grafica. In un'app XAML, il modo più semplice consiste nell'aggiungere un CanvasControl alla pagina XAML.
Prima di continuare, assicurarsi che l'opzione Architettura del progetto sia impostata su x86 o x64 e non su Any CPU. Win2D viene implementato in C++, quindi i progetti che usano Win2D devono essere destinati a un'architettura di CPU specifica.
Passare a
MainWindow.xamlnel project facendo doppio clic su di esso in Solution Explorer. Verrà aperto il file. Per praticità, puoi fare doppio clic sul pulsante XAML nella scheda Progettazione; in questo modo verrà nascosta la finestra di progettazione visiva e verrà riservato tutto lo spazio per la visualizzazione codice.Prima di aggiungere il controllo, devi prima indicare a XAML dove è definito CanvasControl . Per farlo, vai alla definizione dell'elemento Window e aggiungi quindi questa direttiva:
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml". Il codice XAML dovrebbe ora essere simile al seguente:
<Window
...
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
mc:Ignorable="d">
- Aggiungere ora un nuovo
canvas:CanvasControlelemento come elemento figlio all'elemento Grid radice. Assegna un nome al controllo, ad esempio "canvas". Il codice XAML dovrebbe ora essere simile al seguente:
<Grid>
<canvas:CanvasControl x:Name="canvas"/>
</Grid>
- Definire quindi un gestore eventi per l'evento Draw.
CanvasControl genera
Drawogni volta che l'app deve disegnare o ridisegnare il contenuto. Il modo più semplice è lasciare che il completamento automatico di Visual Studio ti assista. Nella definizione CanvasControl iniziare a digitare un nuovo attributo per ilDrawgestore eventi:
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />
Disegnare il primo testo in Win2D
A questo punto, passiamo al codice sottostante C#. Apri
MainWindow.xaml.csda Esplora soluzioni.Nella parte superiore del file C# sono presenti varie definizioni di namespace. Aggiungere i namespace seguenti:
using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
- Verrà quindi visualizzato il gestore eventi vuoto seguente che è stato inserito da AutoComplete:
private void canvas_Draw(
Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}
Se il completamento automatico non è stato usato nel passaggio precedente, aggiungere ora questo codice.
- Il parametro CanvasDrawEventArgs espone un membro, DrawingSession di tipo CanvasDrawingSession. Questa classe offre la maggior parte delle funzionalità di disegno di base in Win2D: include metodi come CanvasDrawingSession.DrawRectangle, CanvasDrawingSession.DrawImage e il metodo necessario per disegnare testo, CanvasDrawingSession.DrawText.
Aggiungere al metodo canvas_Draw il codice seguente:
args.DrawingSession.DrawText("Hello, World!", 100, 100, Colors.Black);
Il primo argomento, "Hello, World!", è la stringa che si vuole visualizzare da Win2D. I due "100" indicano a Win2D di sfalsare questo testo di 100 DIP (pixel indipendenti dal dispositivo) a destra e verso il basso. Infine, Colors.Black definisce il colore del testo.
- Ora sei pronto per eseguire la tua prima app Win2D. Premere il tasto F5 per compilare e avviare. Dovrebbe essere visualizzata una finestra vuota con "Hello, world!" in nero.
Eliminare correttamente le risorse Win2D
- Prima di continuare a disegnare altri tipi di contenuto, devi prima aggiungere codice per assicurarti che l'app eviti perdite di memoria. La maggior parte delle applicazioni Win2D scritte in un linguaggio .NET e utilizzando un controllo Win2D come CanvasControl hanno bisogno di seguire i seguenti passaggi. In senso stretto, la tua semplice app "Hello, world" non è interessata, ma questa è una buona pratica da seguire in generale.
Per altre informazioni, vedere Evitare perdite di memoria.
Aprire
MainWindow.xamle trovare l'elemento XAML che contiene CanvasControl. Deve essere il primo elemento del file.Aggiungere un gestore per l'evento
Unloaded. Il codice XAML dovrebbe essere simile al seguente:
<Page
...
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
mc:Ignorable="d"
Unloaded="Page_Unloaded">
- Vai a
MainWindow.xaml.cse trova il gestore eventiPage_Unloaded. Aggiungere il codice seguente:
void Page_Unloaded(object sender, RoutedEventArgs e)
{
this.canvas.RemoveFromVisualTree();
this.canvas = null;
}
- Se la tua app contiene più controlli Win2D, devi ripetere i passaggi precedenti per ogni pagina XAML che contiene un controllo Win2D. Al momento, l'app ha solo un singolo CanvasControl, quindi hai finito.
Disegnare alcune forme
- È altrettanto semplice aggiungere geometria 2D all'app. Aggiungere il codice seguente alla fine di
canvas_Draw:
args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);
Gli argomenti di questi due metodi sono simili a DrawText. Un cerchio è definito da un punto centrale (125, 125), un raggio (100) e un colore (verde). Una linea è definita da un inizio (0, 0), una fine (50, 200) e un colore (rosso).
- Premere F5 per eseguire l'app. Verrà visualizzato "Hello, world!" insieme a un cerchio verde e a una linea rossa.
Ci si potrebbe chiedere come controllare opzioni di disegno più avanzate, ad esempio spessore linea e trattini, o opzioni di riempimento più complesse come l'uso di pennelli. Win2D offre tutte queste opzioni e altro ancora e semplifica l'uso quando vuoi. Tutti i metodi Draw(...) offrono molti overload che possono accettare parametri aggiuntivi, ad esempio CanvasTextFormat (famiglia di caratteri, dimensioni e così via) e CanvasStrokeStyle (trattini, punti, endcap e così via). È possibile esplorare l'API surface per altre informazioni su queste opzioni.
Generare dinamicamente parametri di disegno
- A questo punto, aggiungiamo un po' di varietà disegnando una serie di forme e testo con colori casuali.
Aggiungi il codice seguente all'inizio della classe MainWindow. Questa è la funzionalità helper per generare valori casuali che verranno usati durante il disegno:
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);
}
- Modificare il
canvas_Drawmetodo per disegnare usando questi parametri casuali:
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()));
}
Di seguito viene descritto come DrawText è cambiato.
"Hello, World!" rimane uguale a prima. I parametri di offset x e y sono stati sostituiti con un singolo oggetto System.Numerics.Vector2 generato da RndPosition. Infine, invece di usare un colore predefinito, Color.FromArgb consente di definire un colore usando i valori A, R, G e B. A è alfa o livello di opacità; in questo caso si dovrebbe avere opaco completo (255).
DrawCircle e DrawLine funzionano in modo analogo a DrawText.
- Infine, avvolgi il codice di disegno in un ciclo
for. Dovresti arrivare al seguente codicecanvas_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()));
}
- Eseguire di nuovo l'app. Dovrebbe essere visualizzato un intero gruppo di testo, linee e cerchi con posizioni e dimensioni casuali.
Applicare un effetto immagine al contenuto
Gli effetti immagine, noti anche come effetti filtro, sono trasformazioni grafiche applicate ai dati pixel. La saturazione, la rotazione delle tonalità e la sfocatura gaussiana sono alcuni effetti di immagine comuni. Gli effetti immagine possono essere concatenati, producendo un aspetto visivo sofisticato per un lavoro minimo.
Gli effetti immagine vengono usati fornendo un'immagine di origine (il contenuto da cui si parte), creando un effetto come GaussianBlurEffect, impostando proprietà come BlurAmount, e quindi disegnando l'output dell'effetto con DrawImage.
Per applicare un effetto immagine al testo e alle forme, è necessario prima eseguire il rendering del contenuto in un CanvasCommandList. Questo oggetto è utilizzabile come input per il tuo effetto.
- Modificare il
canvas_Drawmetodo per usare il codice seguente:
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()));
}
}
Proprio come si ottiene un CanvasDrawingSession oggetto da CanvasDrawEventArgs cui è possibile disegnare, è possibile creare un oggetto CanvasDrawingSession da un oggetto CanvasCommandList. L'unica differenza è che quando si disegna nella sessione di disegno dell'elenco comandi (clds), non si esegue direttamente il rendering in CanvasControl. L'elenco dei comandi è invece un oggetto intermedio che archivia i risultati del rendering per un uso successivo.
Potresti aver notato il blocco using che avvolge la sessione di disegno dell'elenco dei comandi. Le sessioni di disegno implementano IDisposable e devono essere eliminate al termine del rendering (il using blocco esegue questa operazione). Il CanvasDrawingSession ottenuto da CanvasDrawEventArgs automaticamente viene chiuso automaticamente, ma è necessario eliminare tutte le sessioni di disegno create in modo esplicito.
- Infine, definire
GaussianBlurEffectaggiungendo il codice seguente alla fine delcanvas_Drawmetodo :
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
- Eseguire di nuovo l'app. Dovresti vedere le righe, il testo e i cerchi con un aspetto sfocato.
Animare l'app con CanvasAnimatedControl
. Win2D ti offre la possibilità di aggiornare e animare il contenuto in tempo reale, ad esempio modificando il raggio di sfocatura del blur gaussiano con ogni fotogramma. Per farlo, userai CanvasAnimatedControl.
CanvasControl è particolarmente adatto per il contenuto grafico statico, ma genera solo l'evento Draw quando il contenuto deve essere aggiornato o ridisegnato. Se il contenuto cambia continuamente, dovresti considerare di usare CanvasAnimatedControl. I due controlli funzionano in modo molto simile, eccetto che CanvasAnimatedControl genera l'evento Draw a intervalli regolari; per impostazione predefinita viene chiamato sessanta volte al secondo.
- Per selezionare
CanvasAnimatedControl, vai aMainPage.xaml, elimina la riga CanvasControl e sostituiscila con il seguente codice XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>
Proprio come con CanvasControl, lascia che il completamento automatico crei il gestore eventi Draw per te. Per impostazione predefinita, Visual Studio denominare questo gestore canvas_Draw_1 perché canvas_Draw esiste già. In questo caso, è stato rinominato il metodo canvas_AnimatedDraw per chiarire che si tratta di un evento diverso.
Inoltre, si gestisce un nuovo evento, CreateResources. Ancora una volta, lasciare che il completamento automatico crei il gestore.
Ora che l'app verrà ridisegnata a 60 fotogrammi al secondo, è più efficiente creare le risorse visive Win2D una volta e riutilizzarle con ogni fotogramma. È inefficiente creare un oggetto CanvasCommandList e disegnare 300 elementi in esso 60 volte al secondo quando il contenuto rimane statico.
CreateResources è un evento generato solo quando Win2D determina che è necessario ricreare le risorse visive, ad esempio quando la pagina viene caricata.
- Passare nuovamente a
MainPage.xaml.cs. Trova il tuo metodocanvas_Draw, che dovrebbe apparire come segue:
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);
}
La maggior parte di questo codice di disegno esistente non deve essere eseguita con ogni fotogramma: l'elenco di comandi contenente il testo, le righe e i cerchi rimane invariato con ogni fotogramma e l'unica cosa che cambia è il raggio di sfocatura. Pertanto, è possibile spostare questo codice "statico" in CreateResources.
Per fare questo, per prima cosa taglia (CTRL+X) il contenuto intero di canvas_Draw, ad eccezione dell'ultima riga (args.DrawingSession.DrawImage(blur);). È ora possibile eliminare il resto di canvas_Draw perché non è più necessario: ricordare che CanvasAnimatedControl ha un proprio evento distinto Draw .
- Trovare il metodo generato
canvas_CreateResourcesautomaticamente:
private void canvas_CreateResources(
Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender,
Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{}
Incolla (CTRL+V) il codice che hai tagliato precedentemente in questo metodo. Spostare quindi la dichiarazione di GaussianBlurEffect all'esterno del corpo del metodo in modo che la variabile diventi un membro della classe MainPage. Il codice dovrebbe ora essere simile al seguente:
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
};
}
- Ora puoi animare la sfocatura gaussiana. Trovare il
canvas_DrawAnimatedmetodo e aggiungere il codice seguente:
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);
}
Questo rileva il tempo totale trascorso fornito da CanvasAnimatedDrawEventArgs e lo utilizza per calcolare la quantità di sfocatura desiderata; la funzione seno fornisce una variazione interessante nel corso del tempo. Infine, viene eseguito il rendering del GaussianBlurEffect.
- Avvia l'app per vedere come il contenuto sfocato cambia nel tempo.
Congratulazioni per aver completato questa esercitazione introduttiva. Speriamo di aver visto come usare Win2D per creare una scena visiva ricca e animata con poche righe di codice C# e XAML.