Udostępnij za pośrednictwem


Pędzle do kompozycji

Wszystko widoczne na ekranie w aplikacji WinUI jest widoczne, ponieważ zostało namalowane przez szczotkę. Pędzle umożliwiają malowanie obiektów interfejsu użytkownika z zawartością od prostych, jednolitych kolorów do obrazów, rysunków i łańcuchów złożonych efektów. W tym temacie przedstawiono koncepcje malowania za pomocą CompositionBrush.

Podczas pracy z aplikacją WinUI XAML możesz pomalować element UIElement za pomocą pędzla XAML lub CompositionBrush. Zazwyczaj łatwiej jest wybrać pędzel XAML, jeśli twój scenariusz jest już obsługiwany przez jeden. Na przykład animowanie koloru przycisku lub zmienianie wypełnienia tekstu lub kształtu obrazem. Jeśli potrzebujesz czegoś, co nie jest obsługiwane przez pędzel XAML, takiego jak animowana maska, animowane rozciąganie dziewięciosiatki lub łańcuch efektów, możesz użyć CompositionBrush do malowania UIElement za pośrednictwem XamlCompositionBrushBase.

Podczas pracy z warstwą wizualną należy użyć narzędzia CompositionBrush do malowania obszaru SpriteVisual.

Wymagania wstępne

W tym omówieniu założono, że znasz strukturę podstawowej aplikacji kompozycji, zgodnie z opisem w omówieniu warstwy wizualnej.

Malowanie za pomocą CompositionBrush

CompositionBrush "maluje" obszar wynikiem swojej pracy. Różne szczotki/prędzle mają różne rodzaje wyników. Niektóre pędzle malują obszar o stałym kolorze, inne z gradientem, obrazem, rysunkiem niestandardowym lub efektem. Istnieją również wyspecjalizowane szczotki, które modyfikują zachowanie innych pędzli. Na przykład maska krycia może służyć do kontrolowania, który obszar jest malowany przez CompositionBrush, a siatka dziewięciu części może być użyta do kontrolowania rozciągnięcia zastosowanego do pędzla CompositionBrush podczas malowania obszaru. CompositionBrush może być jednym z następujących typów.

Klasa Szczegóły
CompositionColorBrush Maluje obszar o stałym kolorze
CompositionSurfaceBrush Maluje obszar z zawartością elementu ICompositionSurface
PędzelEfektówKompozycji Maluje obszar z zawartością efektu kompozycji
Pędzel maski kompozycji Maluje element wizualny za pomocą CompositionBrush z maską przezroczystości
Kompozycja: NineGridBrush Maluje obszar za pomocą CompositionBrush z wykorzystaniem rozciągania NineGrid
CompositionLinearGradientBrush Maluje obszar z gradientem liniowym
CompositionRadialGradientBrush Maluje obszar z gradientem promieniowym
CompositionBackdropBrush Malowanie obszaru przez pobranie próbek pikseli tła z aplikacji lub z pikseli bezpośrednio znajdujących się za oknem aplikacji na pulpicie. Używane jako dane wejściowe do innego CompositionBrush, takiego jak CompositionEffectBrush.

Malowanie jednolitym kolorem

Element CompositionColorBrush maluje obszar jednolitym kolorem. Istnieje wiele sposobów definiowania koloru SolidColorBrush. Można na przykład określić kanały alfa, czerwone, niebieskie i zielone (ARGB) lub użyć jednego ze wstępnie zdefiniowanych kolorów dostarczonych przez klasę Kolory .

Na poniższej ilustracji i w kodzie przedstawiono małe drzewo wizualne umożliwiające utworzenie prostokąta, który jest obrysowany pędzlem w kolorze czarnym i wypełniany stałym kolorem o wartości 0x9ACD32.

CompositionColorBrush

Compositor _compositor;
ContainerVisual _container;
SpriteVisual _colorVisual1, _colorVisual2;
CompositionColorBrush _blackBrush, _greenBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
_container = _compositor.CreateContainerVisual();

_blackBrush = _compositor.CreateColorBrush(Colors.Black);
_colorVisual1 = _compositor.CreateSpriteVisual();
_colorVisual1.Brush = _blackBrush;
_colorVisual1.Size = new Vector2(156, 156);
_colorVisual1.Offset = new Vector3(0, 0, 0);
_container.Children.InsertAtBottom(_colorVisual1);

_greenBrush = _compositor.CreateColorBrush(Color.FromArgb(0xff, 0x9A, 0xCD, 0x32));
_colorVisual2 = _compositor.CreateSpriteVisual();
_colorVisual2.Brush = _greenBrush;
_colorVisual2.Size = new Vector2(150, 150);
_colorVisual2.Offset = new Vector3(3, 3, 0);
_container.Children.InsertAtBottom(_colorVisual2);

Maluj z użyciem gradientu liniowego

CompositionLinearGradientBrush służy do malowania obszaru gradientem liniowym. Gradient liniowy łączy dwa lub więcej kolorów wzdłuż osi gradientu. Obiekty GradientStop służą do określania kolorów gradientu i ich położenia.

Na poniższej ilustracji i w kodzie przedstawiono SpriteVisual malowany przy użyciu LinearGradientBrush z 2 przystankami w kolorze czerwonym i żółtym.

CompositionLinearGradientBrush

Compositor _compositor;
SpriteVisual _gradientVisual;
CompositionLinearGradientBrush _redyellowBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

_redyellowBrush = _compositor.CreateLinearGradientBrush();
_redyellowBrush.ColorStops.Add(_compositor.CreateColorGradientStop(0, Colors.Red));
_redyellowBrush.ColorStops.Add(_compositor.CreateColorGradientStop(1, Colors.Yellow));
_gradientVisual = _compositor.CreateSpriteVisual();
_gradientVisual.Brush = _redyellowBrush;
_gradientVisual.Size = new Vector2(156, 156);

Malowanie gradientem promieniowym

CompositionRadialGradientBrush maluje obszar za pomocą gradientu promieniowego. Gradient promieniowy łączy co najmniej dwa kolory, zaczynając od środka elipsy i kończąc na jej promieniu. Obiekty GradientStop służą do definiowania kolorów i ich lokalizacji w gradientzie.

Na poniższej ilustracji i kodzie przedstawiono SpriteVisual malowany za pomocą RadialGradientBrush z 2 GradientStops.

CompositionRadialGradientBrush

Compositor _compositor;
SpriteVisual _gradientVisual;
CompositionRadialGradientBrush RGBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

RGBrush = _compositor.CreateRadialGradientBrush();
RGBrush.ColorStops.Add(_compositor.CreateColorGradientStop(0, Colors.Aquamarine));
RGBrush.ColorStops.Add(_compositor.CreateColorGradientStop(1, Colors.DeepPink));
_gradientVisual = _compositor.CreateSpriteVisual();
_gradientVisual.Brush = RGBrush;
_gradientVisual.Size = new Vector2(200, 200);

Malowanie przy użyciu obrazu

CompositionSurfaceBrush służy do malowania powierzchni pikselami renderowanymi na ICompositionSurface. Na przykład element CompositionSurfaceBrush może służyć do malowania obszaru z obrazem renderowanym na powierzchnię ICompositionSurface za pomocą API LoadedImageSurface.

Na poniższej ilustracji i w kodzie przedstawiono SpriteVisual pomalowany bitmapą z lukrecją, renderowany na ICompositionSurface, używając LoadedImageSurface. Właściwości compositionSurfaceBrush można użyć do rozciągania i wyrównania mapy bitowej w granicach wizualizacji.

CompositionSurfaceBrush

Compositor _compositor;
SpriteVisual _imageVisual;
CompositionSurfaceBrush _imageBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

_imageBrush = _compositor.CreateSurfaceBrush();

// The loadedSurface has a size of 0x0 till the image has been downloaded, decoded and loaded to the surface. We can assign the surface to the CompositionSurfaceBrush and it will show up once the image is loaded to the surface.
LoadedImageSurface _loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/licorice.jpg"));
_imageBrush.Surface = _loadedSurface;

_imageVisual = _compositor.CreateSpriteVisual();
_imageVisual.Brush = _imageBrush;
_imageVisual.Size = new Vector2(156, 156);

Maluj za pomocą własnego rysunku

Element CompositionSurfaceBrush może również służyć do malowania obszaru z pikselami z elementu ICompositionSurface renderowanego przy użyciu win2D (lub D2D).

Poniższy kod przedstawia SpriteVisual malowany z uruchomionym fragmentem tekstu renderowanym na powierzchni ICompositionSurface przy użyciu Win2D. Aby użyć win2D z winUI, zainstaluj pakiet NuGet Microsoft.Graphics.Win2D w projekcie.

Compositor _compositor;
CanvasDevice _device;
CompositionGraphicsDevice _compositionGraphicsDevice;
SpriteVisual _drawingVisual;
CompositionSurfaceBrush _drawingBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
_device = CanvasDevice.GetSharedDevice();
_compositionGraphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(_compositor, _device);

_drawingBrush = _compositor.CreateSurfaceBrush();
CompositionDrawingSurface _drawingSurface = _compositionGraphicsDevice.CreateDrawingSurface(
    new Size(256, 256),
    DirectXPixelFormat.B8G8R8A8UIntNormalized,
    DirectXAlphaMode.Premultiplied);

using (var ds = CanvasComposition.CreateDrawingSession(_drawingSurface))
{
    ds.Clear(Colors.Transparent);
    var rect = new Rect(new Point(2, 2), (_drawingSurface.Size.ToVector2() - new Vector2(4, 4)).ToSize());
    ds.FillRoundedRectangle(rect, 15, 15, Colors.LightBlue);
    ds.DrawRoundedRectangle(rect, 15, 15, Colors.Gray, 2);
    ds.DrawText("This is a composition drawing surface", rect, Colors.Black, new CanvasTextFormat()
    {
        FontFamily = "Comic Sans MS",
        FontSize = 32,
        WordWrapping = CanvasWordWrapping.WholeWord,
        VerticalAlignment = CanvasVerticalAlignment.Center,
        HorizontalAlignment = CanvasHorizontalAlignment.Center
    });
}

_drawingBrush.Surface = _drawingSurface;

_drawingVisual = _compositor.CreateSpriteVisual();
_drawingVisual.Brush = _drawingBrush;
_drawingVisual.Size = new Vector2(156, 156);

Podobnie, pędzla CompositionSurfaceBrush można użyć do malowania obiektu SpriteVisual przy użyciu SwapChain i międzyoperacyjności Win2D. Ten przykład przedstawia przykład użycia Win2D do malowania SpriteVisual za pomocą swapchain.

Malowanie za pomocą wideo

Element CompositionSurfaceBrush może również służyć do malowania obszaru z pikselami z elementu ICompositionSurface renderowanego przy użyciu wideo załadowanego za pośrednictwem klasy MediaPlayer .

Poniższy kod przedstawia SpriteVisual renderowany za pomocą wideo załadowanego do ICompositionSurface.

Compositor _compositor;
SpriteVisual _videoVisual;
CompositionSurfaceBrush _videoBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

// MediaPlayer setup with a source URI.
_mediaPlayer = new MediaPlayer();

// Get a source from a URI. This could also come from a file or a stream.
var source = MediaSource.CreateFromUri(new Uri("https://go.microsoft.com/fwlink/?LinkID=809007&clcid=0x409"));
var item = new MediaPlaybackItem(source);
_mediaPlayer.Source = item;
_mediaPlayer.IsLoopingEnabled = true;

// Get the surface from MediaPlayer and put it on a brush.
_videoSurface = _mediaPlayer.GetSurface(_compositor);
_videoBrush = _compositor.CreateSurfaceBrush(_videoSurface.CompositionSurface);

_videoVisual = _compositor.CreateSpriteVisual();
_videoVisual.Brush = _videoBrush;
_videoVisual.Size = new Vector2(156, 156);

Malowanie z efektem filtru

CompositionEffectBrush maluje obszar za pomocą wyniku działania CompositionEffect. Efekty w warstwie wizualnej mogą być uważane za animowane efekty filtru stosowane do kolekcji zawartości źródłowej, takiej jak kolory, gradienty, obrazy, filmy wideo, swapchainy, regiony interfejsu użytkownika lub drzewa elementów wizualnych. Zawartość źródłowa jest zwykle określana przy użyciu innego elementu CompositionBrush.

Na poniższej ilustracji i kodzie przedstawiono SpriteVisual z obrazem kota, na który nałożono efekt filtru desaturacji.

CompositionEffectBrush

Compositor _compositor;
SpriteVisual _effectVisual;
CompositionEffectBrush _effectBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

var graphicsEffect = new SaturationEffect
{
    Saturation = 0.0f,
    Source = new CompositionEffectSourceParameter("mySource")
};

var effectFactory = _compositor.CreateEffectFactory(graphicsEffect);
_effectBrush = effectFactory.CreateBrush();

CompositionSurfaceBrush surfaceBrush = _compositor.CreateSurfaceBrush();
LoadedImageSurface loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/cat.jpg"));
surfaceBrush.Surface = loadedSurface;

_effectBrush.SetSourceParameter("mySource", surfaceBrush);

_effectVisual = _compositor.CreateSpriteVisual();
_effectVisual.Brush = _effectBrush;
_effectVisual.Size = new Vector2(156, 156);

Aby uzyskać więcej informacji na temat tworzenia efektu przy użyciu pędzli kompozycji, zobacz Efekty w warstwie wizualnej

Maluj za pomocą CompositionBrush z nałożoną maską krycia

Pędzel maski kompozycyjnej maluje obszar pędzlem kompozycji ze stosowaną maską nieprzezroczystości. Źródłem maski nieprzezroczystości może być dowolny CompositionBrush typu CompositionColorBrush, CompositionLinearGradientBrush, CompositionSurfaceBrush, CompositionEffectBrush lub CompositionNineGridBrush. Maska nieprzezroczystości musi być określona jako CompositionSurfaceBrush.

Na poniższej ilustracji i w kodzie pokazano SpriteVisual pomalowany za pomocą CompositionMaskBrush. Źródłem maski jest CompositionLinearGradientBrush, który zostaje zamaskowany, aby przypominał okrąg, używając obrazu okręgu jako maski.

Pędzel maski kompozycji

Compositor _compositor;
SpriteVisual _maskVisual;
CompositionMaskBrush _maskBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

_maskBrush = _compositor.CreateMaskBrush();

CompositionLinearGradientBrush _sourceGradient = _compositor.CreateLinearGradientBrush();
_sourceGradient.ColorStops.Add(_compositor.CreateColorGradientStop(0,Colors.Red));
_sourceGradient.ColorStops.Add(_compositor.CreateColorGradientStop(1,Colors.Yellow));
_maskBrush.Source = _sourceGradient;

LoadedImageSurface loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/circle.png"), new Size(156.0, 156.0));
_maskBrush.Mask = _compositor.CreateSurfaceBrush(loadedSurface);

_maskVisual = _compositor.CreateSpriteVisual();
_maskVisual.Brush = _maskBrush;
_maskVisual.Size = new Vector2(156, 156);

Malowanie przy użyciu CompositionBrush z użyciem rozciągania NineGrid

CompositionNineGridBrush maluje obszar za pomocą CompositionBrush, który jest rozciągany przy użyciu metafory dziewięciosiatkowej. Metafora dziewięciu kwadratów pozwala rozciągać krawędzie i rogi CompositionBrush inaczej niż jej środek. Źródłem dziewięciosiatkowego rozciągnięcia może być dowolny CompositionBrush typu CompositionColorBrush, CompositionSurfaceBrush lub CompositionEffectBrush.

Poniższy kod przedstawia SpriteVisual pomalowany za pomocą pędzla CompositionNineGridBrush. Źródłem maski jest CompositionSurfaceBrush, który rozciągnięto za pomocą Nine-Grid.

Compositor _compositor;
SpriteVisual _nineGridVisual;
CompositionNineGridBrush _nineGridBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

_nineGridBrush = _compositor.CreateNineGridBrush();

// nineGridImage.png is 50x50 pixels; nine-grid insets, as measured relative to the actual size of the image, are: left = 1, top = 5, right = 10, bottom = 20 (in pixels)
LoadedImageSurface _imageSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/nineGridImage.png"));
CompositionSurfaceBrush sourceBrush = _compositor.CreateSurfaceBrush(_imageSurface);
_nineGridBrush.Source = sourceBrush;

// Set nine-grid insets.
_nineGridBrush.SetInsets(1, 5, 10, 20);

// Set the appropriate stretch on the SurfaceBrush for the center of the nine-grid.
sourceBrush.Stretch = CompositionStretch.Fill;

_nineGridVisual = _compositor.CreateSpriteVisual();
_nineGridVisual.Brush = _nineGridBrush;
_nineGridVisual.Size = new Vector2(100, 75);

Malowanie przy użyciu pikseli tła

CompositionBackdropBrush maluje obszar za pomocą zawartości znajdującej się za nim. KompozycjaBackdropBrush nigdy nie jest używana samodzielnie, lecz jako dane wejściowe dla innego pędzla kompozycji, takiego jak EffectBrush. Na przykład, używając elementu CompositionBackdropBrush jako danych wejściowych do efektu Blur, można osiągnąć efekt szkła matowego.

Poniższy kod przedstawia małe drzewo wizualne do utworzenia obrazu przy użyciu elementu CompositionSurfaceBrush i matowej szklanej nakładki nad obrazem. Matowa nakładka ze szkła jest tworzona przez umieszczenie SpriteVisual wypełnionego EffectBrush nad obrazem. EffectBrush używa CompositionBackdropBrush jako wejścia do efektu rozmycia.

Compositor _compositor;
ContainerVisual _containerVisual;
SpriteVisual _imageVisual;
SpriteVisual _backdropVisual;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

// Create a container visual to host the visual tree.
_containerVisual = _compositor.CreateContainerVisual();

// Create _imageVisual and add it to the bottom of the container visual.
CompositionSurfaceBrush _licoriceBrush = _compositor.CreateSurfaceBrush();
LoadedImageSurface loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/licorice.jpg"));
_licoriceBrush.Surface = loadedSurface;

_imageVisual = _compositor.CreateSpriteVisual();
_imageVisual.Brush = _licoriceBrush;
_imageVisual.Size = new Vector2(156, 156);
_imageVisual.Offset = new Vector3(0, 0, 0);
_containerVisual.Children.InsertAtBottom(_imageVisual);

// Create a SpriteVisual and add it to the top of the container visual.
// Paint the visual with an EffectBrush that applies blur to the content underneath it.
GaussianBlurEffect blurEffect = new GaussianBlurEffect()
{
    Name = "Blur",
    BlurAmount = 1.0f,
    BorderMode = EffectBorderMode.Hard,
    Source = new CompositionEffectSourceParameter("source")
};

CompositionEffectFactory blurEffectFactory = _compositor.CreateEffectFactory(blurEffect);
CompositionEffectBrush _backdropBrush = blurEffectFactory.CreateBrush();

// Create a BackdropBrush and bind it to the EffectSourceParameter source.
_backdropBrush.SetSourceParameter("source", _compositor.CreateBackdropBrush());

_backdropVisual = _compositor.CreateSpriteVisual();
_backdropVisual.Brush = _backdropBrush;
_backdropVisual.Size = new Vector2(78, 78);
_backdropVisual.Offset = new Vector3(39, 39, 0);
_containerVisual.Children.InsertAtTop(_backdropVisual);

Łączenie kompozycjiBrushes

Wiele pędzli kompozycji używa innych pędzli kompozycji jako danych wejściowych. Na przykład za pomocą metody SetSourceParameter można ustawić inny element CompositionBrush jako dane wejściowe elementu CompositionEffectBrush. Poniższa tabela przedstawia obsługiwane kombinacje CompositionBrushes. Należy pamiętać, że użycie nieobsługiwanej kombinacji spowoduje zgłoszenie wyjątku.

Pędzel EffectBrush.SetSourceParameter() MaskBrush.Mask MaskBrush.Source NineGridBrush.Source
CompositionColorBrush TAK TAK TAK TAK
Kompozycja liniowa
GradientBrush
TAK TAK TAK NIE
CompositionSurfaceBrush TAK TAK TAK TAK
CompositionEffectBrush NIE NIE TAK NIE
Pędzel maski kompozycji NIE NIE NIE NIE
Kompozycja NineGridBrush TAK TAK TAK NIE
KompozycjaBackdropBrush TAK NIE NIE NIE

Używanie pędzla XAML kontra CompositionBrush

Poniższa tabela zawiera listę scenariuszy i określa, czy zaleca się użycie pędzla XAML lub pędzla Kompozycji podczas malowania komponentu UIElement lub SpriteVisual w aplikacji.

Uwaga / Notatka

Jeśli sugerowany jest CompositionBrush dla elementu UIElement XAML, zakłada się, że CompositionBrush jest spakowany za pomocą XamlCompositionBrushBase.

Scenario Element interfejsu użytkownika XAML Kompozycja SpriteVisual
Malowanie obszaru o stałym kolorze SolidColorBrush CompositionColorBrush
Malowanie obszaru z animowanym kolorem SolidColorBrush CompositionColorBrush
Malowanie obszaru ze statycznym gradientem LinearGradientBrush CompositionLinearGradientBrush
Pomaluj obszar z animowanymi punktami gradientu CompositionLinearGradientBrush CompositionLinearGradientBrush
Malowanie obszaru z obrazem Imagebrush CompositionSurfaceBrush
Malowanie obszaru za pomocą strony internetowej WebView2 N/A
Malowanie obszaru z obrazem przy użyciu odcinka NineGrid Kontrolka obrazu KompozycjaNineGridBrush
Malowanie obszaru animowanym odcinkiem NineGrid CompositionNineGridBrush Kompozycja NineGridBrush
Malowanie obszaru przy użyciu swapchainu SwapChainPanel CompositionSurfaceBrush w/ swapchain interop
Malowanie obszaru za pomocą wideo MediaPlayerElement CompositionSurfaceBrush z współpracą mediów
Malowanie obszaru za pomocą niestandardowego rysunku 2D CanvasControl z win2D CompositionSurfaceBrush z interoperacyjnością Win2D
Malowanie obszaru bez animowanej maski Definiowanie maski przy użyciu kształtów XAML Pędzel maski kompozycji
Malowanie obszaru z animowaną maską Pędzel maski kompozycji Pędzel maski kompozycji
Malowanie obszaru z animowanym efektem filtru PędzelEfektówKompozycji PędzelEfektówKompozycji
Pomalowanie obszaru z efektem na pikselach tła CompositionBackdropBrush CompositionBackdropBrush

Natywna kompozycja interop DirectX i Direct2D z BeginDraw i EndDraw

Wzajemne działanie pędzla XAML z XamlCompositionBrushBase