Pinceles de composición

Todo lo que está visible en la pantalla desde una aplicación para UWP es visible porque fue pintado por un pincel. Los pinceles permiten pintar objetos de interfaz de usuario (UI) con contenido que va desde colores simples y sólidos hasta imágenes o dibujos a una cadena de efectos complejos. En este tema se presentan los conceptos de pintura con CompositionBrush.

Nota, al trabajar con una aplicación para UWP XAML, puedes elegir pintar un UIElement con un pincel XAML o un CompositionBrush. Normalmente, es más fácil y aconsejable elegir un pincel XAML si el escenario es compatible con un pincel XAML. Por ejemplo, animando el color de un botón, cambiando el relleno de un texto o una forma con una imagen. Por otro lado, si estás intentando hacer algo que no sea compatible con un pincel XAML como pintar con una máscara animada o una extensión animada de nueve cuadrículas o una cadena de efectos, puedes usar compositionBrush para pintar un UIElement a través del uso de XamlCompositionBrushBase.

Al trabajar con la capa visual, se debe usar compositionBrush para pintar el área de un SpriteVisual.

Requisitos previos

En esta introducción se da por supuesto que está familiarizado con la estructura de una aplicación de composición básica, como se describe en La información general de la capa visual.

Pintar con un CompositionBrush

Un compositionBrush "pinta" un área con su salida. Distintos pinceles tienen tipos de salida diferentes. Algunos pinceles pintan un área con un color sólido, otros con un degradado, una imagen, un dibujo personalizado o un efecto. También hay pinceles especializados que modifican el comportamiento de otros pinceles. Por ejemplo, la máscara de opacidad se puede usar para controlar qué área está pintada por un CompositionBrush, o se puede usar una cuadrícula de nueve para controlar la extensión aplicada a un CompositionBrush al pintar un área. CompositionBrush puede ser de uno de los siguientes tipos:

Clase Detalles Introducido en
CompositionColorBrush Pinta un área con un color sólido Windows 10, versión 1511 (SDK 10586)
CompositionSurfaceBrush Pinta un área con el contenido de un ICompositionSurface Windows 10, versión 1511 (SDK 10586)
CompositionEffectBrush Pinta un área con el contenido de un efecto de composición Windows 10, versión 1511 (SDK 10586)
CompositionMaskBrush Pinta un objeto visual con compositionBrush con una máscara de opacidad Windows 10, versión 1607 (SDK 14393)
CompositionNineGridBrush Pinta un área con compositionBrush mediante un stretch nineGrid Windows 10, versión 1607 (SDK 14393)
CompositionLinearGradientBrush Pinta un área con un degradado lineal Windows 10, versión 1709 (SDK 16299)
CompositionRadialGradientBrush Pinta un área con un degradado radial Windows 10, versión 1903 (SDK de Insider Preview)
CompositionBackdropBrush Pinta un área mediante el muestreo de píxeles de fondo de la aplicación o píxeles directamente detrás de la ventana de la aplicación en el escritorio. Se usa como entrada para otro CompositionBrush como compositionEffectBrush Windows 10, versión 1607 (SDK 14393)

Pintar con un color sólido

Un CompositionColorBrush pinta un área con un color sólido. Hay una variedad de maneras de especificar el color de un SolidColorBrush. Por ejemplo, puede especificar sus canales alfa, rojo, azul y verde (ARGB) o usar uno de los colores predefinidos proporcionados por la clase Colors .

En la siguiente ilustración y código se muestra un pequeño árbol visual para crear un rectángulo que se trazó con un pincel de color negro y se pinta con un pincel de color sólido que tiene el valor de color de 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);

Pintar con un degradado lineal

CompositionLinearGradientBrush pinta un área con un degradado lineal. Un degradado lineal combina dos o más colores a través de una línea, el eje degradado. Los objetos GradientStop se usan para especificar los colores en el degradado y sus posiciones.

En la siguiente ilustración y código se muestra un SpriteVisual pintado con linearGradientBrush con 2 paradas usando un color rojo y amarillo.

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

Pintar con un degradado radial

Un compositionRadialGradientBrush pinta un área con un degradado radial. Un degradado radial combina dos o más colores con el degradado comenzando desde el centro de la elipse y finalizando en el radio de la elipse. Los objetos GradientStop se usan para definir los colores y su ubicación en el degradado.

En la siguiente ilustración y código se muestra un SpriteVisual pintado con un RadialGradientBrush con 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);

Pintar con una imagen

Un CompositionSurfaceBrush pinta un área con píxeles representados en un ICompositionSurface. Por ejemplo, se puede usar compositionSurfaceBrush para pintar un área con una imagen representada en una superficie ICompositionSurface mediante LoadedImageSurface API.

En la siguiente ilustración y código se muestra un SpriteVisual pintado con un mapa de bits de un regaliz representado en un ICompositionSurface mediante LoadedImageSurface. Las propiedades de CompositionSurfaceBrush se pueden usar para estirar y alinear el mapa de bits dentro de los límites del objeto visual.

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

Pintar con un dibujo personalizado

Un CompositionSurfaceBrush también se puede usar para pintar un área con píxeles de un ICompositionSurface representado mediante Win2D (o D2D).

El código siguiente muestra un SpriteVisual pintado con una ejecución de texto representada en un ICompositionSurface mediante Win2D. Tenga en cuenta que, para poder usar Win2D, debe incluir el paquete NuGet Win2D en el proyecto.

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

Del mismo modo, compositionSurfaceBrush también se puede usar para pintar un SpriteVisual con una cadena de intercambio mediante la interoperabilidad win2D. En este ejemplo se proporciona un ejemplo de cómo usar Win2D para pintar un SpriteVisual con una cadena de intercambio.

Pintar con un vídeo

También se puede usar compositionSurfaceBrush para pintar un área con píxeles de un ICompositionSurface representado mediante un vídeo cargado a través de la clase MediaPlayer .

En el código siguiente se muestra un SpriteVisual pintado con un vídeo cargado en un 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);

Pintar con un efecto de filtro

Un CompositionEffectBrush pinta un área con la salida de un CompositionEffect. Los efectos de la capa visual pueden considerarse como efectos de filtro animables aplicados a una colección de contenido de origen, como colores, degradados, imágenes, vídeos, cadenas de intercambio, regiones de la interfaz de usuario o árboles de objetos visuales. El contenido de origen se especifica normalmente mediante otro CompositionBrush.

En la siguiente ilustración y código se muestra un SpriteVisual pintado con una imagen de un gato que tiene aplicado efecto de filtro de desaturación.

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

Para obtener más información sobre cómo crear un efecto mediante CompositionBrushes, vea Efectos en la capa visual.

Pintar con un CompositionBrush con máscara de opacidad aplicada

Un CompositionMaskBrush pinta un área con un CompositionBrush con una máscara de opacidad aplicada. La fuente de la máscara de opacidad puede ser cualquier CompositionBrush de tipo CompositionColorBrush, CompositionLinearGradientBrush, CompositionSurfaceBrush, CompositionEffectBrush o CompositionNineGridBrush. La máscara de opacidad debe especificarse como compositionSurfaceBrush.

En la siguiente ilustración y código se muestra un SpriteVisual pintado con un CompositionMaskBrush. El origen de la máscara es un compositionLinearGradientBrush que se enmascara para parecerse a un círculo con una imagen de círculo como máscara.

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

Pintar con un compositionBrush mediante nineGrid stretch

Un CompositionNineGridBrush pinta un área con un CompositionBrush que se extiende utilizando la metáfora de nueve cuadrículas. La metáfora de nueve cuadrículas te permite estirar bordes y esquinas de un CompositionBrush de forma diferente a su centro. La fuente de la extensión de nueve cuadrículas puede ser cualquier CompositionBrush de tipo CompositionColorBrush, CompositionSurfaceBrush o CompositionEffectBrush.

En el código siguiente se muestra un SpriteVisual pintado con compositionNineGridBrush. La fuente de la máscara es un CompositionSurfaceBrush que se extiende mediante una cuadrícula de Nueve.

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

Pintar con píxeles de fondo

Un compositionBackdropBrush pinta un área con el contenido detrás del área. Un CompositionBackdropBrush nunca se usa por sí mismo, sino que se usa como entrada para otro CompositionBrush como EffectBrush. Por ejemplo, mediante el uso de compositionBackdropBrush como entrada para un efecto de desenfoque, puede lograr un efecto de vidrio escarchado.

En el código siguiente se muestra un pequeño árbol visual para crear una imagen mediante CompositionSurfaceBrush y una superposición de vidrio escarchada encima de la imagen. La superposición de vidrio escarchada se crea colocando un SpriteVisual lleno con un EffectBrush encima de la imagen. EffectBrush usa compositionBackdropBrush como entrada para el efecto de desenfoque.

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

Combinar CompositionBrushes

Una serie de CompositionBrush usan otros CompositionBrushes como entradas. Por ejemplo, el uso del método SetSourceParameter se puede usar para establecer otro CompositionBrush como entrada en compositionEffectBrush. En la tabla siguiente se describen las combinaciones admitidas de CompositionBrushes. Tenga en cuenta que el uso de una combinación no admitida producirá una excepción.

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

Usar un pincel XAML frente a CompositionBrush

En la tabla siguiente se proporciona una lista de escenarios y si se prescribe el uso de pincel XAML o Composition al pintar un UIElement o un SpriteVisual en la aplicación.

Nota:

Si se sugiere un objeto CompositionBrush para un UIElement XAML, se supone que CompositionBrush se empaqueta mediante xamlCompositionBrushBase.

Escenario XAML UIElement SpriteVisual de composición
Pintar un área con color sólido SolidColorBrush CompositionColorBrush
Pintar un área con color animado SolidColorBrush CompositionColorBrush
Pintar un área con un degradado estático LinearGradientBrush CompositionLinearGradientBrush
Pintar un área con paradas de degradado animadas CompositionLinearGradientBrush CompositionLinearGradientBrush
Pintar un área con una imagen ImageBrush CompositionSurfaceBrush
Pintar un área con una página web WebViewBrush N/D
Pintar un área con una imagen mediante el stretch de NineGrid Image Control CompositionNineGridBrush
Pintar un área con la animación de NineGrid stretch CompositionNineGridBrush CompositionNineGridBrush
Pintar un área con una cadena de intercambio SwapChainPanel Interoperabilidad de la cadena de intercambio CompositionSurfaceBrush
Pintar un área con un vídeo MediaElement CompositionSurfaceBrush con interoperabilidad multimedia
Pintar un área con dibujo 2D personalizado CanvasControl desde Win2D Interoperabilidad de CompositionSurfaceBrush con Win2D
Pintar un área con máscara no animada Usar formas XAML para definir una máscara CompositionMaskBrush
Pintar un área con una máscara animada CompositionMaskBrush CompositionMaskBrush
Pintar un área con un efecto de filtro animado CompositionEffectBrush CompositionEffectBrush
Pintar un área con un efecto aplicado a píxeles de fondo CompositionBackdropBrush CompositionBackdropBrush

Interoperabilidad nativa de Composición de DirectX y Direct2D con BeginDraw y EndDraw

Interoperabilidad de pincel XAML con XamlCompositionBrushBase