Bagikan melalui


Kuas desain komposisi

Semuanya terlihat di layar Anda di aplikasi WinUI terlihat karena dicat oleh kuas. Kuas memungkinkan Anda melukis objek antarmuka pengguna (UI) dengan konten mulai dari warna solid sederhana hingga gambar, gambar, dan rantai efek kompleks. Topik ini memperkenalkan konsep lukisan dengan KomposisiBrush.

Saat bekerja dengan aplikasi WinUI XAML, Anda dapat memilih untuk melukis UIElement dengan kuas XAML atau CompositionBrush. Biasanya, lebih mudah untuk memilih "brush" XAML jika skenario Anda sudah didukung oleh salah satu. Misalnya, menganimasikan warna tombol atau mengubah isian teks atau bentuk dengan gambar. Jika Anda membutuhkan sesuatu yang tidak didukung oleh kuas XAML, seperti masker animasi, peregangan sembilan-kisi animasi, atau rantai efek, Anda dapat menggunakan CompositionBrush untuk mewarnai UIElement melalui XamlCompositionBrushBase.

Saat bekerja dengan lapisan Visual, CompositionBrush harus digunakan untuk mengecat area SpriteVisual.

Prasyarat

Gambaran umum ini mengasumsikan bahwa Anda terbiasa dengan struktur aplikasi Komposisi dasar, seperti yang dijelaskan dalam gambaran umum lapisan Visual.

Cat dengan Kuas Komposisi

CompositionBrush "menggambar" area dengan outputnya. Kuas yang berbeda memiliki berbagai jenis output. Beberapa kuas melukis area dengan warna solid, yang lain dengan gradien, gambar, gambar kustom, atau efek. Ada juga kuas khusus yang memodifikasi perilaku kuas lain. Misalnya, masker opasitas dapat digunakan untuk mengontrol area mana yang dicat oleh CompositionBrush, atau sembilan kisi dapat digunakan untuk mengontrol peregangan yang diterapkan pada CompositionBrush saat mengecat area. KomposisiBrush bisa dari salah satu jenis berikut:

Kelas Rincian
CompositionColorBrush Mengecat area dengan warna solid
CompositionSurfaceBrush Mengecat suatu area dengan konten dari ICompositionSurface
KomposisiEffectBrush Melukis area dengan isi efek komposisi
KomposisiMaskBrush Melukis elemen visual dengan CompositionBrush dan masker transparansi
CompositionNineGridBrush Mengecat area dengan CompositionBrush menggunakan peregangan NineGrid
CompositionLinearGradientBrush Mewarnai daerah dengan gradien linier
CompositionRadialGradientBrush Mengecat area dengan gradien radial
CompositionBackdropBrush Melukis area dengan mengambil sampel piksel latar belakang dari aplikasi atau piksel tepat di belakang jendela aplikasi di desktop. Digunakan sebagai input ke CompositionBrush lain seperti CompositionEffectBrush

Warnai dengan warna solid

CompositionColorBrush mengisi suatu area dengan warna solid. Ada berbagai cara untuk menentukan warna SolidColorBrush. Misalnya, Anda dapat menentukan saluran alfa, merah, biru, dan hijau (ARGB) atau menggunakan salah satu warna yang telah ditentukan sebelumnya yang disediakan oleh kelas Warna .

Ilustrasi dan kode berikut menunjukkan pohon visual kecil untuk membuat persegi panjang yang digoreskan dengan kuas warna hitam dan dicat dengan kuas warna solid yang memiliki nilai warna 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);

Warnai dengan gradien linier

CompositionLinearGradientBrush menggambar suatu area dengan gradien linier. Gradien linier memadukan dua warna atau lebih di seluruh garis, sumbu gradien. Anda menggunakan objek GradientStop untuk menentukan warna dalam gradien dan posisinya.

Ilustrasi dan kode berikut menunjukkan SpriteVisual yang dicat dengan LinearGradientBrush dengan 2 stop menggunakan warna merah dan kuning.

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);

Warnai dengan gradien radial

CompositionRadialGradientBrush digunakan untuk melukis area dengan gradien radial. Gradien radial memadukan dua warna atau lebih dengan gradien mulai dari bagian tengah elips dan berakhir pada radius elips. Objek GradientStop digunakan untuk menentukan warna dan lokasinya dalam gradien.

Ilustrasi dan kode berikut menunjukkan SpriteVisual yang dilukis dengan RadialGradientBrush dengan 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);

Melukis dengan gambar

CompositionSurfaceBrush melukis sebuah area menggunakan piksel yang telah dirender ke ICompositionSurface. Misalnya, CompositionSurfaceBrush dapat digunakan untuk melukis area dengan gambar yang dirender ke ICompositionSurface dengan menggunakan LOADedImageSurface API.

Ilustrasi dan kode berikut menunjukkan SpriteVisual yang dilukis dengan bitmap licorice yang dirender ke ICompositionSurface menggunakan LoadedImageSurface. Sifat-sifat dari CompositionSurfaceBrush dapat digunakan untuk meregangkan dan menyelaraskan bitmap dalam batas visual.

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);

Lukis menggunakan gambar khusus

CompositionSurfaceBrush juga dapat digunakan untuk mewarnai area dengan piksel dari ICompositionSurface yang dirender menggunakan Win2D (atau D2D).

Kode berikut menunjukkan SpriteVisual yang dihiasi dengan rangkaian teks yang dirender pada ICompositionSurface dengan menggunakan Win2D. Untuk menggunakan Win2D dengan WinUI, instal paket NuGet Microsoft.Graphics.Win2D di proyek Anda.

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);

Demikian pula, CompositionSurfaceBrush juga dapat digunakan untuk menggambar SpriteVisual dengan SwapChain dengan menggunakan interop Win2D. Sampel ini memberikan contoh cara menggunakan Win2D untuk melukis SpriteVisual dengan swapchain.

Melukis dengan video

CompositionSurfaceBrush juga dapat digunakan untuk mengecat area dengan piksel dari ICompositionSurface yang dirender menggunakan video yang dimuat melalui kelas MediaPlayer.

Kode berikut menunjukkan SpriteVisual yang dicat dengan video yang dimuat ke 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);

Melukis dengan efek filter

CompositionEffectBrush melukis area dengan keluaran dari CompositionEffect. Efek dalam Lapisan Visual mungkin dianggap sebagai efek filter yang dapat dianimasikan yang diterapkan pada kumpulan konten sumber seperti warna, gradien, gambar, video, swapchain, wilayah UI Anda, atau pohon Visual. Konten sumber biasanya ditentukan menggunakan CompositionBrush lain.

Ilustrasi dan kode berikut ini menunjukkan "SpriteVisual" yang dilukis menggunakan gambar kucing dengan efek filter desaturasi diterapkan.

KomposisiEffectBrush

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);

Untuk informasi selengkapnya tentang membuat Efek menggunakan KomposisiBrush lihat Efek di Lapisan visual

Cat dengan Kuas Komposisi yang menggunakan masker opasitas

CompositionMaskBrush mengaplikasikan CompositionBrush pada area dengan masker transparansi yang diterapkan padanya. Sumber masker opasitas dapat berupa CompositionBrush jenis CompositionColorBrush, CompositionLinearGradientBrush, CompositionSurfaceBrush, CompositionEffectBrush, atau CompositionNineGridBrush. Masker opasitas harus ditentukan sebagai CompositionSurfaceBrush.

Ilustrasi dan kode berikut menunjukkan SpriteVisual yang dilukis dengan CompositionMaskBrush. Sumber masker adalah CompositionLinearGradientBrush yang ditutupi agar terlihat seperti lingkaran menggunakan gambar lingkaran sebagai masker.

KomposisiMaskBrush

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);

Mengecat dengan KomposisiBrush menggunakan pemuaian NineGrid

KomposisiNineGridBrush melukis area dengan KomposisiBrush yang direntangkan menggunakan metafora sembilan kisi. Metafora sembilan kisi memungkinkan Anda untuk meregangkan tepi dan sudut KomposisiBrush secara berbeda dari pusatnya. Sumber peregangan kotak sembilan dapat berupa CompositionBrush dari jenis CompositionColorBrush, CompositionSurfaceBrush, atau CompositionEffectBrush.

Kode berikut menunjukkan SpriteVisual yang digambar dengan CompositionNineGridBrush. Sumber masker adalah CompositionSurfaceBrush yang direntangkan menggunakan metode 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);

Melukis dengan piksel latar belakang

CompositionBackdropBrush membuat area dengan menggunakan konten yang berada di belakang area tersebut. CompositionBackdropBrush tidak pernah digunakan sendiri, tetapi digunakan sebagai masukan ke CompositionBrush lain seperti EffectBrush. Misalnya, dengan menggunakan KomposisiBackdropBrush sebagai input ke efek Blur, Anda dapat mencapai efek kaca beku.

Kode berikut menunjukkan pohon visual kecil untuk membuat gambar menggunakan Kuas Permukaan Komposisi dan overlay kaca buram di atas gambar tersebut. Overlay kaca beku dibuat dengan menempatkan SpriteVisual yang diisi dengan EffectBrush di atas gambar. EffectBrush menggunakan CompositionBackdropBrush sebagai input untuk efek blur.

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);

Menggabungkan CompositionBrushes

Sejumlah Kuas Komposisi menggunakan Kuas Komposisi lain sebagai masukan. Misalnya, menggunakan metode SetSourceParameter untuk mengatur CompositionBrush lain sebagai input ke CompositionEffectBrush. Tabel di bawah ini menguraikan kombinasi CompositionBrush yang didukung. Perhatikan, bahwa menggunakan kombinasi yang tidak didukung akan memberikan pengecualian.

Sikat EffectBrush.SetSourceParameter() MaskBrush.Mask MaskBrush.Source NineGridBrush.Source
CompositionColorBrush YA YA YA YA
CompositionLinear
GradienBrush
YA YA YA TIDAK
KomposisiSurfaceBrush YA YA YA YA
Kuas Efek Komposisi TIDAK TIDAK YA TIDAK
KomposisiSikatTopeng TIDAK TIDAK TIDAK TIDAK
KomposisiNineGridBrush YA YA YA TIDAK
KomposisiBackdropBrush YA TIDAK TIDAK TIDAK

Menggunakan XAML Brush vs. CompositionBrush

Tabel berikut ini menyediakan daftar skenario dan apakah XAML atau penggunaan kuas Komposisi ditentukan saat melukis UIElement atau SpriteVisual dalam aplikasi Anda.

Nota

Jika sebuah CompositionBrush disarankan untuk sebuah UIElement XAML, diasumsikan bahwa CompositionBrush tersebut dipaketkan menggunakan XamlCompositionBrushBase.

Skenario XAML UIElement Komposisi SpriteVisual
Warnai daerah dengan warna solid SolidColorBrush CompositionColorBrush
Mewarnai area dengan warna yang dianimasikan SolidColorBrush CompositionColorBrush
Melukis suatu area dengan gradien statis LinearGradientBrush CompositionLinearGradientBrush
Warnai daerah dengan berhenti gradien animasi CompositionLinearGradientBrush CompositionLinearGradientBrush
Mengecat area dengan gambar KuasaGambar CompositionSurfaceBrush
Mengisi area dengan konten halaman web WebView2 N/A
Mengecat area dengan gambar menggunakan stretch NineGrid Kontrol Gambar Komposisi NineGridBrush
Warnai area dengan menampilkan animasi peregangan NineGrid KomposisiNineGridBrush CompositionNineGridBrush
Warnai suatu area dengan swapchain SwapChainPanel CompositionSurfaceBrush dengan interop swapchain
Mengecat area dengan video MediaPlayerElement CompositionSurfaceBrush dengan interop media
Menggambar area dengan gambar 2D kustom CanvasControl dari Win2D CompositionSurfaceBrush dengan interoperabilitas Win2D
Cat bagian dengan masker tidak animasi Menggunakan bentuk XAML untuk menentukan masker CompositionMaskBrush
Warnai area menggunakan masker animasi KomposisiMaskBrush KomposisiMaskBrush
Mengecat area tertentu dengan efek animasi filter CompositionEffectBrush KomposisiEffectBrush
Mengecat area dengan efek yang sudah diterapkan pada piksel latar belakang KomposisiBackdropBrush CompositionBackdropBrush

Komposisi langsung DirectX natif dan interoperabilitas Direct2D dengan BeginDraw dan EndDraw

Interop kuas XAML dengan XamlCompositionBrushBase