Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Visuella sammansättningsobjekt utgör den visuella trädstruktur som alla andra funktioner i API:et Microsoft.UI.Composition använder och bygger vidare på. MED API:et kan utvecklare definiera och skapa ett eller flera visuella objekt, som var och en representerar en enskild nod i ett visuellt träd.
Bildmaterial
Det finns flera typer av visuella komponenter som utgör trädstrukturens visuella del, plus en baspenselklass med flera underklasser som påverkar det visuella innehållet.
- Visual – basobjekt, de flesta egenskaperna finns här och ärvs av de andra visuella objekten.
-
ContainerVisual – härleds från Visual och ger förmågan att skapa barnobjekt.
- SpriteVisual – härleds från ContainerVisual. Har möjlighet att koppla en pensel så att den visuella enheten kan återge bildpunkter, inklusive bilder, effekter eller en helfärg.
- LayerVisual – härleds från ContainerVisual. Barnobjekt i det visuella elementet plattas ut till ett enda lager.
- ShapeVisual – härleds från ContainerVisual. En visuell trädnod som är roten för en CompositionShape.
- RedirectVisual – härleds från ContainerVisual. Det visuella objektet hämtar sitt innehåll från ett annat visuellt objekt.
- SceneVisual – härleds från ContainerVisual. Ett visuellt containerobjekt för noderna i en 3D-scen.
Du kan använda innehåll och effekter på SpriteVisuals med hjälp av CompositionBrush och dess underklasser, inklusive CompositionColorBrush, CompositionSurfaceBrush och CompositionEffectBrush. Mer information om penslar finns i Översikt över CompositionBrush.
"Exemplet med CompositionVisual"
Här tittar vi på lite WinUI 3-exempelkod som visar de tre olika visuella typerna som angavs tidigare. Även om det här exemplet inte omfattar begrepp som animeringar eller mer komplexa effekter, innehåller det de byggstenar som alla dessa system använder. (Den fullständiga exempelkoden visas i slutet av den här artikeln.)
I exemplet finns ett antal fyrkanter i enfärgad färg som kan klickas på och dras om skärmen. När en fyrkant klickas på kommer den framifrån, roterar 45 grader och blir ogenomskinlig när den dras omkring.
Detta visar ett antal grundläggande begrepp för att arbeta med API:et, bland annat:
- Skapa en compositor
- Skapa en SpriteVisual med en CompositionColorBrush
- Klippning av det visuella
- Rotera det visuella objektet
- Ställ in opacitet
- Ändra det visuella objektets position i samlingen.
Skapa en compositor
Att skapa en Compositor och lagra den i en variabel för användning som en fabrik är en enkel uppgift. I en WinUI-app hämtar du vanligtvis compositorn från ett XAML-element som redan är anslutet till det visuella trädet:
Compositor compositor = ElementCompositionPreview.GetElementVisual(MyHost).Compositor;
Om du behöver en compositor och inte har något UIElement tillgängligt kan du använda CompositionTarget.GetCompositorForCurrentThread() i stället.
Skapa en SpriteVisual och en färgpensel
Med Compositor är det enkelt att skapa objekt när du behöver dem, till exempel en SpriteVisual och en CompositionColorBrush:
var visual = _compositor.CreateSpriteVisual();
visual.Brush = _compositor.CreateColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF));
Även om detta bara är några rader kod, visar det ett kraftfullt koncept: SpriteVisual-objekt är kärnan i effektsystemet. SpriteVisual möjliggör stor flexibilitet och samspel i färg, bild och effektskapande. SpriteVisual är en enda visuell typ som kan fylla en 2D-rektangel med en pensel, i det här fallet en solid färg.
Klippning av ett visuellt objekt
Compositor kan också användas för att skapa klipp till ett visuellt objekt. Nedan visas ett exempel från exemplet på hur du använder InsetClip för att trimma varje sida av det visuella objektet:
var clip = _compositor.CreateInsetClip();
clip.LeftInset = 1.0f;
clip.RightInset = 1.0f;
clip.TopInset = 1.0f;
clip.BottomInset = 1.0f;
_currentVisual.Clip = clip;
Precis som andra objekt i API:et kan InsetClip ha animeringar som tillämpas på dess egenskaper.
Rotera ett klipp
Ett visuellt objekt kan omvandlas med en rotation. Observera att RotationAngle stöder både radianer och grader. Den är standard för radianer, men det är enkelt att ange grader enligt följande kodfragment:
child.RotationAngleInDegrees = 45.0f;
Rotation är bara ett exempel på en uppsättning transformeringskomponenter som tillhandahålls av API:et för att göra dessa uppgifter enklare. Andra inkluderar Offset, Scale, Orientation, RotationAxis och 4x4 TransformMatrix.
Ställ in opacitet
Att ange opaciteten för ett visuellt objekt är en enkel åtgärd med hjälp av ett flyttalvärde. I exemplet börjar till exempel alla rutor vid .8 ogenomskinlighet:
visual.Opacity = 0.8f;
Precis som rotation kan opacity-egenskapen animerads.
Ändra det visuella objektets position i samlingen
Kompositions-API:t gör det möjligt att ändra positionen för ett visuellt objekt i en VisualCollection på flera olika sätt. Den kan placeras ovanför ett annat visuellt objekt med InsertAbove, som placeras nedan med InsertBelow, flyttas till toppen med InsertAtTop eller längst ned med InsertAtBottom.
I exemplet sorteras ett visuellt objekt som har klickats längst upp:
parent.Children.InsertAtTop(_currentVisual);
Fullständigt exempel
I det fullständiga WinUI-exemplet används alla begrepp ovan tillsammans för att konstruera och gå i ett enkelt träd med visuella objekt för att ändra opacitet utan anpassad DirectX-återgivning. Exemplet använder ett WinUI Grid för pekarindata och är värd för kompositionsträdet med ElementCompositionPreview.
<Page
x:Class="CompositionVisualSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid
x:Name="MyHost"
Background="Transparent"
PointerPressed="OnPointerPressed"
PointerMoved="OnPointerMoved"
PointerReleased="OnPointerReleased" />
</Page>
using System;
using System.Numerics;
using Microsoft.UI.Composition;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Hosting;
using Microsoft.UI.Xaml.Input;
using Windows.Foundation;
using Windows.UI;
namespace CompositionVisualSample
{
public sealed partial class MainPage : Page
{
private readonly Random _random = new();
private Compositor _compositor;
private ContainerVisual _root;
private ContainerVisual _currentVisual;
private Vector2 _offsetBias;
private bool _dragging;
public MainPage()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (_root != null)
{
return;
}
_compositor = ElementCompositionPreview.GetElementVisual(MyHost).Compositor;
_root = _compositor.CreateContainerVisual();
ElementCompositionPreview.SetElementChildVisual(MyHost, _root);
for (int index = 0; index < 20; index++)
{
_root.Children.InsertAtTop(CreateChildElement());
}
}
private ContainerVisual CreateChildElement()
{
var element = _compositor.CreateContainerVisual();
element.Size = new Vector2(100.0f, 100.0f);
var maxX = (float)Math.Max(MyHost.ActualWidth - element.Size.X, 0.0);
var maxY = (float)Math.Max(MyHost.ActualHeight - element.Size.Y, 0.0);
element.Offset = new Vector3(
(float)(_random.NextDouble() * maxX),
(float)(_random.NextDouble() * maxY),
0.0f);
var outer = _compositor.CreateSpriteVisual();
outer.Size = new Vector2(100.0f, 100.0f);
outer.Brush = _compositor.CreateColorBrush(Colors.White);
element.Children.InsertAtTop(outer);
var inner = _compositor.CreateSpriteVisual();
inner.Offset = new Vector3(3.0f, 3.0f, 0.0f);
inner.Size = new Vector2(94.0f, 94.0f);
byte red = (byte)(0xFF * (0.2f + (_random.NextDouble() / 0.8f)));
byte green = (byte)(0xFF * (0.2f + (_random.NextDouble() / 0.8f)));
byte blue = (byte)(0xFF * (0.2f + (_random.NextDouble() / 0.8f)));
inner.Brush = _compositor.CreateColorBrush(Color.FromArgb(0xFF, red, green, blue));
outer.Children.InsertAtTop(inner);
element.Opacity = 0.8f;
return element;
}
private void OnPointerPressed(object sender, PointerRoutedEventArgs e)
{
Point position = e.GetCurrentPoint(MyHost).Position;
_currentVisual = null;
foreach (var child in _root.Children)
{
Vector3 offset = child.Offset;
Vector2 size = child.Size;
if ((position.X >= offset.X) &&
(position.X < offset.X + size.X) &&
(position.Y >= offset.Y) &&
(position.Y < offset.Y + size.Y))
{
_currentVisual = child as ContainerVisual;
_offsetBias = new Vector2(
(float)(offset.X - position.X),
(float)(offset.Y - position.Y));
}
}
if (_currentVisual != null)
{
ContainerVisual parent = (ContainerVisual)_currentVisual.Parent;
parent.Children.Remove(_currentVisual);
parent.Children.InsertAtTop(_currentVisual);
}
}
private void OnPointerMoved(object sender, PointerRoutedEventArgs e)
{
if (_currentVisual == null)
{
return;
}
if (!_dragging)
{
_currentVisual.Opacity = 1.0f;
foreach (var child in _currentVisual.Children)
{
child.RotationAngleInDegrees = 45.0f;
child.CenterPoint = new Vector3(_currentVisual.Size.X / 2, _currentVisual.Size.Y / 2, 0.0f);
break;
}
var clip = _compositor.CreateInsetClip();
clip.LeftInset = 1.0f;
clip.RightInset = 1.0f;
clip.TopInset = 1.0f;
clip.BottomInset = 1.0f;
_currentVisual.Clip = clip;
_dragging = true;
}
Point position = e.GetCurrentPoint(MyHost).Position;
_currentVisual.Offset = new Vector3(
(float)(position.X + _offsetBias.X),
(float)(position.Y + _offsetBias.Y),
0.0f);
}
private void OnPointerReleased(object sender, PointerRoutedEventArgs e)
{
if (_currentVisual == null)
{
return;
}
if (_dragging)
{
foreach (var child in _currentVisual.Children)
{
child.RotationAngle = 0.0f;
child.CenterPoint = new Vector3(0.0f, 0.0f, 0.0f);
break;
}
_currentVisual.Opacity = 0.8f;
_currentVisual.Clip = null;
_dragging = false;
}
_currentVisual = null;
}
}
}
Om du behöver initiera en compositor innan du har ett XAML-värdeelement, använder du CompositionTarget.GetCompositorForCurrentThread() och kopplar sedan de visuella elementen till användargränssnittet när ett värdelement blir tillgängligt.
Windows developer