Кисти композиции

Все, что отображается на экране в приложении UWP, отображается, поскольку нарисовано с помощью кисти. Кисти позволяют рисовать объекты пользовательского интерфейса с содержимым, начиная с простых сплошных цветов в изображениях и рисунках до цепочек сложных эффектов. В этом разделе представлены понятия, связанные с CompositionBrush.

Обратите внимание, что при работе с приложением XAML UWP можно закрасить UIElement с помощью кисти XAML или CompositionBrush. Как правило, проще и понятнее выбрать кисть XAML, если ваш сценарий поддерживается кистью XAML. Например, анимация цвета кнопки, изменение заливки текста или фигуры с изображением. С другой стороны, если вы пытаетесь сделать что-то, что не поддерживается кистью XAML, например рисование с анимированной маской или анимированной девятью сетками растяжение или цепочка эффектов, вы можете использовать CompositionBrush для рисования UIElement с помощью XamlCompositionBrushBase.

При работе с использованием визуального уровня необходимо использовать CompositionBrush для рисования области SpriteVisual.

Предварительные требования

Материал данного раздела предполагает, что вы знакомы со структурой базового приложения композиции, которая описана в разделе Обзор визуального уровня.

Рисование с помощью CompositionBrush

CompositionBrush заполняет пространство своими выводимыми данными. Разные кисти имеют различные типы выводимых данных. Некоторые кисти заполняют область сплошным цветом, другие — градиентом, изображением, собственным рисунком или эффектом. Существуют также специальные кисти, которые изменяют поведение других кистей. Например, маску непрозрачности можно использовать для управления тем, на какую область воздействует CompositionBrush, а сетку из девяти сегментов можно использовать для управления растягиванием, применяемым к CompositionBrush при рисовании в какой-либо области. CompositionBrush может относиться к одному из следующих типов:

Класс Сведения Представлено в
CompositionColorBrush Заполняет область сплошным цветом Windows 10 версии 1511 (пакет SDK 10586)
CompositionSurfaceBrush Заполняет область содержимым ICompositionSurface Windows 10 версии 1511 (пакет SDK 10586)
CompositionEffectBrush Заполняет область содержимым эффекта композиции Windows 10 версии 1511 (пакет SDK 10586)
CompositionMaskBrush Изображает визуальный элемент с помощью CompositionBrush с маской непрозрачности Windows 10 версии 1607 (пакет SDK 14393)
CompositionNineGridBrush Заполняет область с помощью CompositionBrush с использованием растягивания NineGrid Windows 10 версии 1607 (пакет SDK 14393)
CompositionLinearGradientBrush Заполняет область линейным градиентом Windows 10 версии 1709 (пакет SDK 16299)
CompositionRadialGradientBrush Закрашивает область радиальным градиентом Windows 10 версии 1903 (пакет SDK Insider Preview)
CompositionBackdropBrush Заполняет область, производя выборку фоновых пикселей либо из приложения, либо из пикселей непосредственно за окном приложения на рабочем столе. Используется в качестве входных данных для другого инструмента CompositionBrush, например CompositionEffectBrush Windows 10 версии 1607 (пакет SDK 14393)

Рисование сплошным цветом

CompositionColorBrush закрашивает область сплошным цветом. Существует множество способов задать цвет SolidColorBrush. Например, можно указать значения его каналов альфа, красного, синего и зеленого (ARGB) либо использовать один из предопределенных цветов, предоставляемых классом Colors.

Следующий рисунок и фрагмент кода демонстрируют небольшое визуальное дерево для создания прямоугольника, заштрихованного с помощью кисти черного цвета и заполненного с помощью кисти сплошного цвета с кодом 0x9ACD32.

CompositionColorBrush

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

_compositor = Window.Current.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);

Рисование с линейным градиентом

CompositionLinearGradientBrush закрашивает область линейным градиентом. Линейный градиент смешивает два или более цветов вдоль линии, то есть оси градиента. Объекты GradientStop используются для указания цветов в градиенте и их положения.

На иллюстрации и в коде ниже показан объект SpriteVisual, закрашенный с помощью LinearGradientBrush с 2 остановками с красным и желтым цветами.

CompositionLinearGradientBrush

Compositor _compositor;
SpriteVisual _gradientVisual;
CompositionLinearGradientBrush _redyellowBrush;

_compositor = Window.Current.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);

Рисование радиальным градиентом

CompositionRadialGradientBrush закрашивает область радиальным градиентом. Радиальный градиент смешивает два или более цвета с градиентом, начиная с центра эллипса и заканчивая радиусом эллипса. Объекты GradientStop используются для определения цветов и их расположения в градиенте.

На следующем рисунке и коде показан объект SpriteVisual, окрашенный с помощью RadialGradientBrush с 2 GradientStops.

CompositionRadialGradientBrush

Compositor _compositor;
SpriteVisual _gradientVisual;
CompositionRadialGradientBrush RGBrush;

_compositor = Window.Current.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);

Рисование с помощью изображения

CompositionSurfaceBrush заполняет область пикселями, отображаемыми на ICompositionSurface. Например, можно использовать CompositionSurfaceBrush для заполнения области изображением, отображаемым на поверхности ICompositionSurface surface с помощью API LoadedImageSurface.

На рисунке и в коде ниже показан объект SpriteVisual, заполненный растровым изображением лакричных конфет, отрисованным на поверхности ICompositionSurface с помощью LoadedImageSurface. Можно использовать свойства CompositionSurfaceBrush, чтобы растянуть и выровнять точечный рисунок в границах визуального объекта.

CompositionSurfaceBrush

Compositor _compositor;
SpriteVisual _imageVisual;
CompositionSurfaceBrush _imageBrush;

_compositor = Window.Current.Compositor;

_imageBrush = _compositor.CreateSurfaceBrush();

// The loadedSurface has a size of 0x0 till the image has been 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);

Рисование с помощью пользовательской отрисовки

CompositionSurfaceBrush также может использоваться для заполнения области пикселями из ICompositionSurface, отрисованными с использованием Win2D (или D2D).

В коде ниже показан объект SpriteVisual, заполненный фрагментом текста, отрисованным на ICompositionSurface с помощью Win2D. Обратите внимание, что для использования Win2D необходимо включить пакет Win2D NuGet в свой проект.

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

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

Аналогичным образом CompositionSurfaceBrush также может использоваться для рисования SpriteVisual с помощью SwapChain с использованием взаимодействия Win2D. В этом коде приведен пример того, как можно использовать Win2D для рисования SpriteVisual с помощью цепочки буферов.

Рисование с помощью видео

CompositionSurfaceBrush также может использоваться для заполнения области пикселями из ICompositionSurface, отрисованными с использованием видео, загруженного с помощью класса MediaPlayer.

В коде ниже показан объект SpriteVisual, заполненный фрагментом видео, загруженным на ICompositionSurface.

Compositor _compositor;
SpriteVisual _videoVisual;
CompositionSurfaceBrush _videoBrush;

// MediaPlayer set up with a create from URI

_mediaPlayer = new MediaPlayer();

// Get a source from a URI. This could also be from a file via a picker 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);

Рисование с использованием эффекта фильтра

CompositionEffectBrush заполняет область выводимыми данными CompositionEffect. Эффекты на визуальном уровне могут рассматриваться как анимируемые эффекты фильтров, применяемые к коллекции исходного содержимого, например цветов, градиентов, изображений, видео, цепочек буферов, областей пользовательского интерфейса или деревьев визуальных элементов. Исходное содержимое обычно указывается с помощью другой CompositionBrush.

На иллюстрации и в коде ниже показан объект SpriteVisual, заполненный изображением кошка с примененным эффектом фильтра уменьшения насыщенности.

CompositionEffectBrush

Compositor _compositor;
SpriteVisual _effectVisual;
CompositionEffectBrush _effectBrush;

_compositor = Window.Current.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);

Дополнительные сведения о создании эффектов с помощью CompositionBrushes см. в разделе Эффекты на визуальном уровне

Рисование с помощью CompositionBrush с примененной маской непрозрачности

CompositionMaskBrush заполняет область содержимым CompositionBrush с примененной к нему маской непрозрачности. Источником маски непрозрачности может быть любая CompositionBrush типа CompositionColorBrush, CompositionLinearGradientBrush, CompositionSurfaceBrush, CompositionEffectBrush или CompositionNineGridBrush. Маска непрозрачности должна быть указана как CompositionSurfaceBrush.

На иллюстрации и в коде ниже показан объект SpriteVisual, закрашенный с помощью CompositionMaskBrush. Источником маски является кисть CompositionLinearGradientBrush, которая использует маску для отображения окружности, и в качестве маски используется изображение окружности.

CompositionMaskBrush

Compositor _compositor;
SpriteVisual _maskVisual;
CompositionMaskBrush _maskBrush;

_compositor = Window.Current.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);

Рисование с помощью CompositionBrush с использованием растягивания NineGrid

CompositionNineGridBrush заполняет область с помощью кисти CompositionBrush, которая растянута с использованием модели сетки из девяти сегментов. Модель сетки из 9 сегментов позволяет растягивать края и углы изображения CompositionBrush иначе, чем его центр. Источником растягиваемой сетки из девяти сегментов может быть любая CompositionBrush типа CompositionColorBrush, CompositionSurfaceBrush или CompositionEffectBrush.

В коде ниже показан объект SpriteVisual, закрашенный с помощью CompositionNineGridBrush. Источником маски является кисть CompositionSurfaceBrush, которая растянута с помощью сетки из девяти сегментов.

Compositor _compositor;
SpriteVisual _nineGridVisual;
CompositionNineGridBrush _nineGridBrush;

_compositor = Window.Current.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"));
_nineGridBrush.Source = _compositor.CreateSurfaceBrush(_imageSurface);

// set Nine-Grid Insets

_ninegridBrush.SetInsets(1, 5, 10, 20);

// set appropriate Stretch on SurfaceBrush for Center of Nine-Grid

sourceBrush.Stretch = CompositionStretch.Fill;

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

Рисование с помощью фоновых пикселей

CompositionBackdropBrush закрашивает область с ее содержимым. CompositionBackdropBrush никогда не используется самостоятельно, но вместо этого используется в качестве входных данных для другой CompositionBrush, например EffectBrush. Например, используя CompositionBackdropBrush в качестве входных данных для эффекта размытия, можно добиться эффекта матированного стекла.

В следующем коде показано небольшое дерева визуальных объектов для создания изображения с использованием CompositionSurfaceBrush и слоя матированного стекла над изображением. Слой матированного стекла создается путем размещения объекта SpriteVisual, заполненного с использованием EffectBrush, над изображением. EffectBrush использует CompositionBackdropBrush в качестве входных данных для эффекта размытия.

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

_compositor = Window.Current.Compositor;

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

// Create _imageVisual and add it to the bottom of the container visual.
// Paint the visual with an image.

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 containerVisual.
// Paint the visual with an EffectBrush that applies blur to the content
// underneath the Visual to create a frosted glass effect.

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 = _licoriceBrush;
_backdropVisual.Size = new Vector2(78, 78);
_backdropVisual.Offset = new Vector3(39, 39, 0);
_containerVisual.Children.InsertAtTop(_backdropVisual);

Объединение CompositionBrushes

Ряд кистей CompositionBrushes может использовать другие CompositionBrushes в качестве входных данных. Например, с помощью метода SetSourceParameter можно задать другую кисть CompositionBrush в качестве входных данных для CompositionEffectBrush. В таблице ниже описаны поддерживаемые сочетания CompositionBrushes. Обратите внимание, что при использовании неподдерживаемого сочетания будет вызвано исключение.

Brush EffectBrush.SetSourceParameter() MaskBrush.Mask MaskBrush.Source NineGridBrush.Source
CompositionColorBrush YES YES YES YES
CompositionLinear
GradientBrush
YES YES YES NO
CompositionSurfaceBrush YES YES YES YES
CompositionEffectBrush NO NO YES NO
CompositionMaskBrush NO NO NO NO
CompositionNineGridBrush YES YES YES NO
CompositionBackdropBrush YES NO NO NO

Сравнение CompositionBrush с кистью XAML

Ниже приводится список сценариев и указано, какую из двух кистей — XAML или Composition — рекомендуется использовать для рисования UIElement или SpriteVisual в приложении.

Примечание

Если CompositionBrush предлагается для UIElement на XAML, предполагается, что CompositionBrush упакована с помощью XamlCompositionBrushBase.

Сценарий UIElement на XAML Composition SpriteVisual
Заполнение области сплошным цветом SolidColorBrush; CompositionColorBrush
Заполнение области анимированным цветом SolidColorBrush; CompositionColorBrush
Заполнение области статичным градиентом LinearGradientBrush; CompositionLinearGradientBrush
Заполнение области анимированными ограничениями градиента CompositionLinearGradientBrush CompositionLinearGradientBrush
Заполнение области изображением ImageBrush; CompositionSurfaceBrush
Заполнение области веб-страницей WebViewBrush Н/Д
Заполнение области изображением с использованием растягивания NineGrid Image Control CompositionNineGridBrush
Заполнение области анимацией с использованием растягивания NineGrid CompositionNineGridBrush CompositionNineGridBrush
Заполнение области цепочкой буферов SwapChainPanel CompositionSurfaceBrush со взаимодействием с цепочкой буферов
Заполнение области видеосодержимым MediaElement CompositionSurfaceBrush со взаимодействием с медиа
Заполнение области пользовательским двумерным рисунком CanvasControl из Win2D CompositionSurfaceBrush со взаимодействием с Win2D
Заполнение области неанимированной маской Используйте фигуры XAML для определения маски CompositionMaskBrush
Заполнение области анимированной маской CompositionMaskBrush CompositionMaskBrush
Заполнение области анимированным эффектом фильтра CompositionEffectBrush CompositionEffectBrush
Заполнение области эффектом, примененным к фоновым пикселям CompositionBackdropBrush CompositionBackdropBrush

Собственное взаимодействие DirectX и Direct2D композиции с BeginDraw и EndDraw

Взаимодействие кисти XAML с XamlCompositionBrushBase