0% encontró este documento útil (0 votos)
2K vistas869 páginas

WPF

Este documento proporciona una introducción general a la representación de gráficos y multimedia en WPF, incluyendo información sobre pinceles, dibujos, geometrías, imágenes, formas, transformaciones, animaciones, gráficos 3D, programación de capas visuales y multimedia. Contiene enlaces a temas específicos de "Cómo..." que proporcionan instrucciones paso a paso para llevar a cabo tareas comunes.

Cargado por

John Forero
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
2K vistas869 páginas

WPF

Este documento proporciona una introducción general a la representación de gráficos y multimedia en WPF, incluyendo información sobre pinceles, dibujos, geometrías, imágenes, formas, transformaciones, animaciones, gráficos 3D, programación de capas visuales y multimedia. Contiene enlaces a temas específicos de "Cómo..." que proporcionan instrucciones paso a paso para llevar a cabo tareas comunes.

Cargado por

John Forero
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 869

Contents

Gráficos y multimedia
Información general sobre la representación de gráficos en WPF
Gráficos
Efectos de imagen
Información general sobre efectos de imagen
Pinceles
Información general sobre pinceles de WPF
Información general sobre la transformación de pinceles
Información general sobre las máscaras de opacidad
Información general sobre el dibujo con colores sólidos y degradados
Pintar con imágenes, dibujos y elementos visuales
Información general sobre objetos TileBrush
Temas "Cómo..."
Animar el color o la opacidad de un objeto SolidColorBrush
Animar la posición o color de un delimitador de degradado
Crear una reflexión
Crear patrones de mosaico diferentes con un objeto TileBrush
Definir un lápiz
Pintar un área con un dibujo
Pintar un área con una imagen
Pintar un área con un degradado lineal
Pintar un área con un degradado radial
Pintar un área con un color sólido
Pintar un área con un pincel del sistema
Pintar un área con un vídeo
Pintar un área con un objeto visual
Conservar la relación de aspecto de una imagen usada como fondo
Establecer la alineación horizontal y vertical de un TileBrush
Establecer el tamaño del mosaico de un TileBrush
Transformar un pincel
Usar colores del sistema en un degradado
Dibujos
Información general sobre objetos Drawing
Temas "Cómo..."
Aplicar un objeto GuidelineSet a un dibujo
Crear un dibujo compuesto
Crear un objeto GeometryDrawing
Dibujar una imagen mediante un objeto ImageDrawing
Reproducir elementos multimedia con un objeto VideoDrawing
Usar un dibujo como el origen de una imagen
Geometrías
Sintaxis de marcado de trazados
Información general sobre geometría
Temas "Cómo..."
Animar un objeto EllipseGeometry
Animar el tamaño de un objeto ArcSegment
Controlar el relleno de una forma compuesta
Crear una geometría combinada
Crear una forma compuesta
Crear una curva Bézier cúbica
Crear una línea mediante la clase LineGeometry
Crear un LineSegment en una clase PathGeometry
Crear una forma mediante una clase PathGeometry
Crear una forma mediante un objeto StreamGeometry
Crear una curva Bézier cuadrática
Crear un arco elíptico
Crear varios subtrazados en un objeto PathGeometry
Definir un rectángulo mediante una clase RectangleGeometry
Redondear las esquinas de un RectangleGeometry
Imágenes
Información general sobre imágenes
Temas "Cómo..."
Usar BitmapImage en XAML
Cargar una imagen como una miniatura
Aplicar una transformación a una imagen de mapa de bits
Crear un mapa de bits desde un objeto visual
Codificar un objeto visual en un archivo de imagen
Crear un objeto BitmapSource
Encadenar objetos BitmapSource
Convertir un elemento BitmapSource a un formato de píxeles diferente
Convertir un elemento BitmapSource a un formato de píxeles indexado
Codificar y descodificar una imagen JPEG
Codificar y descodificar una imagen BMP
Codificar y descodificar una imagen PNG
Codificar y descodificar una imagen WDP
Codificar y descodificar una imagen GIF
Codificar y descodificar una imagen TIFF
Escribir metadatos en un mapa de bits
Leer metadatos de un mapa de bits
Formas
Información general sobre formas y dibujo básico en WPF
Temas "Cómo..."
Dibujar una forma cerrada mediante el elemento Polygon
Dibujar una elipse o un círculo
Dibujar una línea
Dibujar una Polilínea mediante el uso del elemento Polyline
Dibujar un rectángulo
Modificar el extremo en el final de una línea o segmento
Transformaciones
Información general sobre transformaciones
Temas "Cómo..."
Aplicar una transformación a un elemento cuando se produce un evento
Aplicar varias transformaciones a un objeto
Hacer que un elemento gire en su posición
Girar un objeto
Ajustar la escala de un elemento
Sesgar un elemento
Especificar el origen de una transformación mediante valores relativos
Trasladar un elemento
Usar un objeto MatrixTransform para crear transformaciones personalizadas
Configuración del Registro en la representación de gráficos
Temas "Cómo..."
Animar un rectángulo
Animar la posición de un objeto mediante PointAnimation
Transformar puntos y vectores
Ampliar el marco de vidrio en una aplicación de WPF
Procedimiento para mejorar el rendimiento de la representación mediante el
almacenamiento en caché de un elemento
Procedimiento para usar un elemento almacenado en caché como pincel
Información general sobre gráficos 3D
Información general sobre transformaciones de modelos 3D
Maximizar el rendimiento de representación 3D en WPF
Temas "Cómo..."
Crear una escena 3D
Aplicar un dibujo a un modelo 3D
Aplicar material a la parte anterior y posterior de un objeto 3D
Aplicar material emisor a un objeto 3D
Transformar la escala de un modelo 3D
Aplicar varias transformaciones a un modelo 3D
Animar traslaciones 3D
Animar un giro 3D mediante Storyboards
Animar un giro 3D mediante Rotation3DAnimation
Animar un giro 3D mediante cuaterniones
Animar un giro 3D mediante fotogramas clave
(Rotation3DAnimationUsingKeyFrames)
Animar un giro 3D mediante fotogramas clave
(QuaternionAnimationUsingKeyFrames)
Animar la posición y la dirección de una cámara en una escena 3D
Animar la posición y la dirección de una cámara mediante fotogramas clave
Animar propiedades de material en una escena 3D
Hacer una prueba de posicionamiento en Viewport3D
Comprobar la igualdad y la desigualdad de estructuras Point4D
Información general sobre animaciones
Información general sobre sistemas de temporización y animación
Sugerencias y trucos para animaciones
Información general sobre animaciones personalizadas
Información general sobre animaciones From/To/By
Información general sobre animaciones de fotogramas clave
Funciones de aceleración
Información general sobre animaciones en trazados
Información general sobre técnicas de animación de propiedades
Información general sobre objetos Storyboard
Información general sobre comportamientos de control de tiempo
Información general sobre eventos de control de tiempo
Temas "Cómo..."
Aumentar o reducir la velocidad de una animación
Acumular valores de animaciones durante la repetición de ciclos
Agregar un valor de salida de animación a un valor inicial de animación
Animar una propiedad mediante un guión gráfico
Animar una propiedad sin usar un guión gráfico
Animar en un ControlTemplate
Animar en un estilo
Animar la opacidad de un elemento o pincel
Cambiar la velocidad de un reloj sin cambiar la velocidad de su escala de tiempo
Controlar un guión gráfico una vez iniciado mediante métodos interactivos
Controlar una animación mediante From, To y By
Definir un ámbito de nombres
Recibir una notificación cuando cambia el estado de un reloj
Repetir una animación
Buscar un guión gráfico
Buscar guiones gráficos de forma sincrónica
Definir una duración para una animación
Establecer una propiedad después de animarla con un guión gráfico
Simplificar las animaciones mediante escalas de tiempo secundarias
Especificar HandoffBehavior entre animaciones de guión gráfico
Especificar el comportamiento de relleno de una escala de tiempo que ha llegado
al final de su período de actividad
Especificar si una escala de tiempo se invierte automáticamente
Activar una animación al cambiar el valor de una propiedad
Usar desencadenadores de eventos para controlar un guión gráfico después de su
inicio
Temas "Cómo..." de relojes
Animar una propiedad mediante un objeto AnimationClock
Controlar interactivamente un reloj
Buscar un reloj de forma sincrónica
Temas de procedimientos de fotogramas clave
Animar un objeto mediante fotogramas clave
Animar un objeto Boolean mediante fotogramas clave
Animar un objeto Double mediante fotogramas clave
Animar un objeto Matrix mediante fotogramas clave
Animar un punto mediante fotogramas clave
Animar la geometría de un rectángulo mediante fotogramas clave
Animar un objeto String mediante fotogramas clave
Animar un color mediante fotogramas clave
Animar los cambios de tamaño mediante fotogramas clave
Animar el grosor de un borde mediante fotogramas clave
Controlar la temporización de animaciones de fotogramas clave
Temas "Cómo..." de animación de trazado
Animación de un objeto a lo largo de un trazado (animación doble)
Animación de un objeto a lo largo de un trazado (animación en punto)
Animación de un objeto a lo largo de un trazado (animación de matriz)
Animar un objeto a lo largo de un trazado (animación en matriz con acumulación
de desplazamiento)
Girar un objeto mediante un trazado geométrico (animación en matriz)
Girar un objeto mediante un trazado geométrico
Información general sobre multimedia
Temas "Cómo..."
Controlar un control MediaElement (Reproducir, Pausar, Detener, Volumen y
Velocidad)
Controlar un control MediaElement mediante un guión gráfico
Desencadenar la reproducción de medios con un evento de usuario
Repetir la reproducción de elementos multimedia
Reproducir elementos multimedia con animaciones
Usar transformaciones en un control MediaElement
Programación de capas visuales
Realizar pruebas de posicionamiento en la capa visual
Usar objetos DrawingVisual
Tutorial: Hospedar objetos visuales en una aplicación Win32
Temas "Cómo..."
Obtener el desplazamiento de un objeto visual
Enumerar el contenido de un dibujo de un objeto visual
Geometría de una prueba de posicionamiento en un objeto visual
Realizar una prueba de posicionamiento mediante el uso de Geometry como
parámetro
Realizar pruebas de posicionamiento mediante un contenedor host Win32
Representar un intervalo para cada fotograma mediante CompositionTarget
Gráficos y multimedia
08/01/2020 • 10 minutes to read • Edit Online

Windows Presentation Foundation (WPF ) proporciona compatibilidad con multimedia, gráficos vectoriales,
animación y composición de contenido, lo que facilita a los desarrolladores la creación de interfaces de usuario
y contenido interesantes. Con Visual Studio, puede crear gráficos vectoriales o animaciones complejas e
integrar los elementos multimedia en las aplicaciones.
En este tema se presentan las características de gráficos, animaciones y elementos multimedia de WPF, que le
permiten agregar gráficos, efectos de transición, sonido y vídeo a las aplicaciones.

NOTE
Se recomienda encarecidamente no usar los tipos WPF en un servicio de Windows. Si intenta usar tipos WPF en un
servicio de Windows, puede que el servicio no funcione como se espera.

Novedades de gráficos y multimedia en WPF 4


Se han efectuado varios cambios relacionados con los gráficos y animaciones.
Redondeo del diseño
Cuando el borde de un objeto queda en medio de un dispositivo de píxeles, el sistema de gráficos
independiente de los ppp puede crear artefactos de representación tales como bordes borrosos o
semitransparentes. Versiones anteriores de WPF incluían el ajuste de píxeles para ayudar a controlar
este caso. Silverlight 2 introdujo el redondeo del diseño, que es otra manera de mover elementos para
que los bordes queden dentro de límites de píxeles enteros. WPF admite ahora el redondeo del diseño
con la UseLayoutRounding propiedad adjunta en FrameworkElement.
Composición almacenada en caché
Mediante el uso de las nuevas clases BitmapCache y BitmapCacheBrush, puede almacenar en caché una
parte compleja del árbol visual como un mapa de bits y mejorar considerablemente el tiempo de
representación. El mapa de bits sigue respondiendo a la entrada del usuario, como clics del mouse, y se
puede pintar en otros elementos, exactamente igual que cualquier pincel.
Compatibilidad con el sombreador de píxeles 3
WPF 4 se basa en la compatibilidad de ShaderEffect introducida en WPF 3,5 SP1 al permitir que las
aplicaciones escriban efectos mediante el sombreador de píxeles (PS ) versión 3,0. El modelo de
sombreador PS 3.0 es más sofisticado que el PS 2.0, lo que permite incluso crear más efectos en
hardware compatible.
Funciones de aceleración
Puede mejorar las animaciones con funciones de aceleración que proporcionan mayor control sobre el
comportamiento de las animaciones. Por ejemplo, puede aplicar una ElasticEase a una animación para
dar un comportamiento elástico a la animación. Para obtener más información, vea los tipos de
aceleración en el espacio de nombres System.Windows.Media.Animation.

Gráficos y representación
WPF incluye compatibilidad con gráficos 2D de alta calidad. La funcionalidad incluye pinceles, geometrías,
imágenes, formas y transformaciones. Para más información, consulte Graphics (Gráficos). La representación
de elementos gráficos se basa en la clase Visual. La estructura de objetos visuales en la pantalla se describe en
el árbol visual. Para más información, consulte Información general sobre la representación de gráficos en
WPF.
Formas 2D
WPF proporciona una biblioteca de formas bidimensionales de uso frecuente, como rectángulos y elipses, que
se muestra en la siguiente ilustración.

Estas formas intrínsecas de WPF no son solo formas: son elementos programables que implementan muchas
de las características que se esperan de los controles más comunes, entre los que se incluyen la entrada del
mouse y del teclado. En el ejemplo siguiente se muestra cómo controlar el evento de MouseUp que se produce
al hacer clic en un elemento Ellipse.

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Window1" >
<Ellipse Fill="LightBlue" MouseUp="ellipseButton_MouseUp" />
</Window>

public partial class Window1 : Window


{
void ellipseButton_MouseUp(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("You clicked the ellipse!");
}
}

Partial Public Class Window1


Inherits Window
Private Sub ellipseButton_MouseUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
MessageBox.Show("You clicked the ellipse!")
End Sub
End Class

En la ilustración siguiente se muestra el resultado del anterior marcado y código XAML subyacente.
Para obtener más información, consulte Información general sobre formas y dibujo básico en WPF. Para
obtener un ejemplo introductorio, vea Shape Elements Sample (Ejemplo de elementos de forma).
Geometrías 2D
Cuando las formas 2D que proporciona WPF no son suficientes, puede usar la compatibilidad de WPF con las
geometrías y las rutas de acceso para crear las suyas propias. En la ilustración siguiente se muestra cómo
puede utilizar las geometrías para crear formas, como un pincel de dibujo, y para recortar otros elementos de
WPF.

Para más información, consulte Información general sobre geometría. Para obtener un ejemplo introductorio,
vea Ejemplo de geometrías.
Efectos 2D
WPF proporciona una biblioteca de clases 2D que puede usar para crear una variedad de efectos. La capacidad
de representación en 2D de WPF proporciona la capacidad de pintar IU elementos que tienen degradados,
mapas de bits, dibujos y vídeos; y para manipularlos mediante la rotación, el escalado y el sesgo. En la
ilustración siguiente se proporciona un ejemplo de los muchos efectos que puede lograr mediante el uso de
pinceles de WPF.

Para obtener más información, consulte Información general sobre pinceles de WPF. Para obtener un ejemplo
introductorio, vea Ejemplo de pinceles.
Representación 3D
WPF proporciona un conjunto de capacidades de representación 3D que se integran con la compatibilidad con
gráficos 2D en WPF para que pueda crear un diseño, un IUy una visualización de datos más interesantes. En un
extremo del espectro, WPF permite representar imágenes 2D en las superficies de las formas 3D, que se
muestran en la siguiente ilustración.

Para obtener más información, consulte Información general sobre gráficos 3D. Para obtener un ejemplo
introductorio, vea 3-D Solids Sample (Ejemplo de sólidos 3D ).

Animación
Use la animación para hacer que los controles y elementos crezcan, vibren, giren o se desvanezcan, crear
atractivas transiciones de página y mucho más. Dado que WPF permite animar la mayoría de las propiedades,
no solo puede animar la mayoría de los objetos de WPF, sino que también puede usar WPF para animar
objetos personalizados que cree.

Para obtener más información, consulte Información general sobre animaciones. Para obtener un ejemplo
introductorio, vea Animation Example Gallery (Galería de ejemplos de animación).

Medios
Las imágenes, el vídeo y el audio son maneras de ofrecer experiencias de usuario e información con mucho
contenido multimedia.
Imágenes
Las imágenes, que incluyen iconos, fondos e incluso partes de animaciones, constituyen una pieza esencial de la
mayoría de las aplicaciones. Como a menudo necesita usar imágenes, WPF expone la capacidad de trabajar con
ellas de varias maneras. En la ilustración siguiente se muestra tan solo una de esas maneras.

Para obtener más información, consulte Información general sobre imágenes.


Vídeo y audio
Una característica fundamental de las capacidades de gráficos de WPF es proporcionar compatibilidad nativa
para trabajar con multimedia, que incluye vídeo y audio. En el siguiente ejemplo se muestra cómo insertar un
reproductor multimedia en una aplicación.

<MediaElement Source="media\numbers.wmv" Width="450" Height="250" />

MediaElement es capaz de reproducir vídeo y audio, y es lo suficientemente extensible como para permitir la
creación sencilla de interfaces de IU personalizadas.
Para más información, consulte Información general sobre multimedia.

Vea también
System.Windows.Media
System.Windows.Media.Animation
System.Windows.Media.Media3D
Imágenes y gráficos 2D
Información general sobre formas y dibujo básico en WPF
Información general sobre el dibujo con colores sólidos y degradados
Pintar con imágenes, dibujos y elementos visuales
Temas de procedimientos de animación y control de tiempo
Información general sobre gráficos 3D
Información general sobre multimedia
Información general sobre la representación de
gráficos en WPF
03/02/2020 • 36 minutes to read • Edit Online

En este tema se ofrece información de la capa de objeto visual de WPF. Se centra en el rol de la clase Visual
para la compatibilidad de representación en el modelo de WPF.

Rol del objeto visual


La clase Visual es la abstracción básica desde la que se derivan todos los objetos FrameworkElement. También
sirve como punto de entrada para escribir controles nuevos en WPF, y en muchos sentidos se puede considerar
el identificador de ventana (HWND ) del modelo de aplicación de Win32.
El objeto Visual es un objeto de WPF básico, cuyo rol principal es proporcionar compatibilidad con la
representación. Los controles de interfaz de usuario, como Button y TextBox, derivan de la clase Visual y lo usan
para conservar los datos de representación. El objeto Visual proporciona compatibilidad con:
Presentación de salida: representación persistente, serializa el contenido de dibujo de un objeto visual.
Transformaciones: realizar transformaciones en un objeto visual.
Recorte: proporcionar soporte para una zona de recorte de un objeto visual.
Pruebas de posicionamiento: determinar si una coordenada o geometría está dentro de los límites de un
objeto visual.
Cálculos de rectángulo de selección: determinar el rectángulo delimitador de un objeto visual.
Sin embargo, el objeto Visual no incluye compatibilidad con las características que no son de representación,
como:
Control de eventos
Diseño
Estilos
Enlace de datos
Globalización
Visual se expone como una clase abstracta pública desde la que se deben derivar las clases secundarias. La
siguiente ilustración muestra la jerarquía de los objetos visuales que se exponen en WPF.

Clase DrawingVisual
El DrawingVisual es una clase de dibujo ligera que se utiliza para representar formas, imágenes o texto. Esta
clase se considera ligera porque no proporciona control de diseño ni control de eventos, lo que mejora su
rendimiento en tiempo de ejecución. Por esta razón, los dibujos son ideales para fondos e imágenes
prediseñadas. El DrawingVisual se puede usar para crear un objeto visual personalizado. Para obtener más
información, consulte Usar objetos DrawingVisual.
Clase Viewport3DVisual
El Viewport3DVisual proporciona un puente entre los objetos 2D Visual y Visual3D. La clase Visual3D es la
clase base para todos los elementos visuales 3D. El Viewport3DVisual requiere que defina un valor Camera y
un valor Viewport. La cámara permite ver la escena. La ventanilla establece el lugar en que se asigna la
proyección a la superficie 2D. Para más información acerca de 3D en WPF, consulte Información general sobre
gráficos 3D.
Clase ContainerVisual
La clase ContainerVisual se utiliza como contenedor para una colección de objetos Visual. La clase
DrawingVisual se deriva de la clase ContainerVisual, lo que permite que contenga una colección de objetos
visuales.
Dibujo de contenido en objetos visuales
Un objeto Visual almacena sus datos de representación como una lista de instrucciones de gráficos
vectoriales. Cada elemento de la lista de instrucciones representa un conjunto de bajo nivel de datos gráficos y
recursos asociados en un formato serializado. Hay cuatro tipos diferentes de datos de representación que
pueden incluir contenido de dibujo.

TIPO DE CONTENIDO DE DIBUJO DESCRIPCIÓN

Gráficos vectoriales Representa los datos de gráficos vectoriales y cualquier


Brush y Pen información asociada.

Imagen Representa una imagen dentro de una región definida por


una Rect.

Glifo Representa un dibujo que representa un GlyphRun, que es


una secuencia de glifos de un recurso de fuente especificado.
Así es como se representa el texto.

Vídeo Representa un dibujo que representa vídeo.

El DrawingContext le permite rellenar un Visual con contenido visual. Cuando se usa el comando Draw de un
objeto DrawingContext, en realidad se almacena un conjunto de datos de representación que se usará más
adelante en el sistema de gráficos. no está dibujando en la pantalla en tiempo real.
Cuando se crea un control de WPF, como un Button, el control genera implícitamente los datos de
representación para dibujarse. Por ejemplo, al establecer la propiedad Content de la Button, el control almacena
una representación de representación de un glifo.
Un Visual describe su contenido como uno o varios objetos Drawing incluidos dentro de un DrawingGroup.
Una DrawingGroup también describe las máscaras de opacidad, las transformaciones, los efectos de imagen y
otras operaciones que se aplican a su contenido. DrawingGroup operaciones se aplican en el siguiente orden
cuando se representa el contenido: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSety, a
continuación, Transform.
En la ilustración siguiente se muestra el orden en que se aplican las operaciones de DrawingGroup durante la
secuencia de representación.
Orden de operaciones de DrawingGroup
Para más información, consulte Información general sobre objetos Drawing.
Contenido de dibujo en la capa de Visual
Nunca se crean instancias de un DrawingContextdirectamente; sin embargo, puede adquirir un contexto de
dibujo de determinados métodos, como DrawingGroup.Open y DrawingVisual.RenderOpen. En el ejemplo
siguiente se recupera una DrawingContext de un DrawingVisual y se usa para dibujar un rectángulo.

// Create a DrawingVisual that contains a rectangle.


private DrawingVisual CreateDrawingVisualRectangle()
{
DrawingVisual drawingVisual = new DrawingVisual();

// Retrieve the DrawingContext in order to create new drawing content.


DrawingContext drawingContext = drawingVisual.RenderOpen();

// Create a rectangle and draw it in the DrawingContext.


Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));
drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null,
rect);

// Persist the drawing content.


drawingContext.Close();

return drawingVisual;
}
' Create a DrawingVisual that contains a rectangle.
Private Function CreateDrawingVisualRectangle() As DrawingVisual
Dim drawingVisual As New DrawingVisual()

' Retrieve the DrawingContext in order to create new drawing content.


Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()

' Create a rectangle and draw it in the DrawingContext.


Dim rect As New Rect(New Point(160, 100), New Size(320, 80))
drawingContext.DrawRectangle(Brushes.LightBlue, CType(Nothing, Pen), rect)

' Persist the drawing content.


drawingContext.Close()

Return drawingVisual
End Function

Enumeración de contenido de dibujo en la capa de Visual


Además de sus otros usos, los objetos Drawing también proporcionan un modelo de objetos para enumerar el
contenido de un Visual.

NOTE
Cuando se enumera el contenido del objeto visual, se recuperan Drawing objetos y no la representación subyacente de
los datos de representación como una lista de instrucciones de gráficos vectoriales.

En el ejemplo siguiente se usa el método GetDrawing para recuperar el valor DrawingGroup de un Visual y
enumerarlo.
public void RetrieveDrawing(Visual v)
{
DrawingGroup drawingGroup = VisualTreeHelper.GetDrawing(v);
EnumDrawingGroup(drawingGroup);
}

// Enumerate the drawings in the DrawingGroup.


public void EnumDrawingGroup(DrawingGroup drawingGroup)
{
DrawingCollection dc = drawingGroup.Children;

// Enumerate the drawings in the DrawingCollection.


foreach (Drawing drawing in dc)
{
// If the drawing is a DrawingGroup, call the function recursively.
if (drawing is DrawingGroup group)
{
EnumDrawingGroup(group);
}
else if (drawing is GeometryDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is ImageDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is GlyphRunDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is VideoDrawing)
{
// Perform action based on drawing type.
}
}
}

Uso de los objetos visuales para compilar controles


Muchos de los objetos de WPF están formados por otros objetos visuales, lo que significa que pueden contener
diversas jerarquías de objetos descendientes. Muchos de los elementos de la interfaz de usuario de WPF, como
los controles, constan de varios objetos visuales, que representan diferentes tipos de representación de
elementos. Por ejemplo, el control Button puede contener varios objetos, como ClassicBorderDecorator,
ContentPresentery TextBlock.
En el código siguiente se muestra un control de Button definido en el marcado.

<Button Click="OnClick">OK</Button>

Si tuviera que enumerar los objetos visuales que componen el control Button predeterminado, encontraría la
jerarquía de objetos visuales que se ilustra a continuación:
El control Button contiene un elemento ClassicBorderDecorator que, a su vez, contiene un elemento
ContentPresenter. El elemento ClassicBorderDecorator es responsable de dibujar un borde y un fondo para la
Button. El elemento ContentPresenter es responsable de mostrar el contenido de la Button. En este caso, puesto
que se muestra texto, el elemento ContentPresenter contiene un elemento TextBlock. El hecho de que el control
Button use un ContentPresenter significa que el contenido podría estar representado por otros elementos,
como un Image o una geometría, como un EllipseGeometry.
Plantillas de control
La clave para la expansión de un control en una jerarquía de controles es la ControlTemplate. Una plantilla de
control especifica la jerarquía visual predeterminada de un control. Al hacer referencia explícitamente a un
control, implícitamente también se hace referencia a su jerarquía visual. Puede reemplazar los valores
predeterminados de una plantilla de control para crear una apariencia visual personalizada para un control. Por
ejemplo, puede modificar el valor de color de fondo del control Button para que use un valor de color de
degradado lineal en lugar de un valor de color sólido. Para más información, consulte Button ControlTemplate
Example (Ejemplo de ControlTemplate de Button).
Un elemento de la interfaz de usuario, como un control Button, contiene varias listas de instrucciones de
gráficos vectoriales que describen toda la definición de representación de un control. En el código siguiente se
muestra un control de Button definido en el marcado.

<Button Click="OnClick">
<Image Source="images\greenlight.jpg"></Image>
</Button>

Si tuviera que enumerar los objetos visuales y las listas de instrucciones de gráficos vectoriales que componen
el control Button, encontraría la jerarquía de objetos que se ilustra a continuación:

El control Button contiene un elemento ClassicBorderDecorator que, a su vez, contiene un elemento


ContentPresenter. El elemento ClassicBorderDecorator es responsable de dibujar todos los elementos gráficos
discretos que componen el borde y el fondo de un botón. El elemento ContentPresenter es responsable de
mostrar el contenido de la Button. En este caso, como se muestra una imagen, el elemento ContentPresenter
contiene un elemento Image.
Hay que tener en cuenta varios aspectos de la jerarquía de objetos visuales y las listas de instrucciones de
gráficos vectoriales:
El orden de la jerarquía representa el orden de procesamiento de la información de dibujo. Desde el
elemento del objeto visual raíz, se atraviesa a los elementos secundarios de izquierda a derecha y de
arriba a abajo. Si un elemento tiene elementos visuales secundarios, se atraviesan antes que los
relacionados del elemento.
Los elementos de nodo no hoja de la jerarquía, como ContentPresenter, se usan para contener
elementos secundarios; no contienen listas de instrucciones.
Si un elemento visual contiene una lista de instrucciones de gráficos vectoriales y elementos secundarios
visuales, la lista de instrucciones del elemento visual primario se representa antes que los dibujos en
cualquiera de los objetos visuales secundarios.
Los elementos de la lista de instrucciones de gráficos vectoriales se representan de izquierda a derecha.

Árbol visual
El árbol visual contiene todos los elementos visuales que se usan en la interfaz de usuario de una aplicación.
Puesto que un elemento visual contiene información guardada del dibujo, el árbol visual se puede considerar
un gráfico de la escena, que contiene toda la información de representación necesaria para componer la salida
de la pantalla. Este árbol es la acumulación de todos los elementos visuales creados directamente por la
aplicación, ya sea a través de código o de marcación. El árbol visual también contiene todos los elementos
visuales que ha creado la expansión de la plantilla de elementos, como controles y objetos de datos.
En el código siguiente se muestra un elemento StackPanel definido en el marcado.

<StackPanel>
<Label>User name:</Label>
<TextBox />
<Button Click="OnClick">OK</Button>
</StackPanel>

Si tuviera que enumerar los objetos visuales que componen el elemento StackPanel en el ejemplo de
marcación, encontraría la jerarquía de objetos visuales que se ilustra a continuación:
Orden de representación
El árbol visual determina el orden de representación de objetos visuales y de dibujo de WPF. El orden del
recorrido comienza con el objeto visual raíz, que es el nodo de nivel superior del árbol visual. A continuación, se
atraviesan los elementos secundarios del objeto visual raíz, de izquierda a derecha. Si un objeto visual tiene
elementos secundarios, estos se atraviesan antes que los elementos del mismo nivel del objeto visual. Esto
significa que el contenido de un objeto visual secundario se representa delante del contenido propio del objeto
visual.

Objeto visual raíz


El objeto visual raíz es el elemento de nivel superior de una jerarquía de árbol visual. En la mayoría de las
aplicaciones, la clase base del visual raíz es Window o NavigationWindow. Sin embargo, si se hospedaran
objetos visuales en una aplicación Win32, el objeto visual raíz sería el objeto visual de nivel superior que se
hospeda en la ventana de Win32. Para más información, consulte Tutorial: Hosting Visual Objects in a Win32
Application (Tutorial: hospedar objetos visuales en una aplicación Win32).
Relación con el árbol lógico
El árbol lógico de WPF representa los elementos de una aplicación en tiempo de ejecución. Aunque no
manipula directamente este árbol, esta vista de la aplicación es útil para entender la herencia de propiedades y
el enrutamiento de eventos. A diferencia del árbol visual, el árbol lógico puede representar objetos de datos no
visuales, como ListItem. En muchos casos, el árbol lógico se asigna muy estrechamente con las definiciones de
marcación de una aplicación. En el código siguiente se muestra un elemento DockPanel definido en el marcado.

<DockPanel>
<ListBox>
<ListBoxItem>Dog</ListBoxItem>
<ListBoxItem>Cat</ListBoxItem>
<ListBoxItem>Fish</ListBoxItem>
</ListBox>
<Button Click="OnClick">OK</Button>
</DockPanel>

Si tuviera que enumerar los objetos lógicos que componen el elemento DockPanel en el ejemplo de marcación,
encontraría la jerarquía de objetos lógicos que se ilustra a continuación:
Diagrama de árbol lógico
El árbol visual y el árbol lógico se sincronizan con el conjunto actual de elementos de la aplicación, que refleja
cualquier adición, eliminación o modificación de elementos. Sin embargo, los árboles presentan distintas vistas
de la aplicación. A diferencia del árbol visual, el árbol lógico no expande el elemento ContentPresenter de un
control. Esto significa que no hay una correspondencia uno a uno directa entre un árbol lógico y un árbol visual
del mismo conjunto de objetos. De hecho, al invocar el método GetChildren del objeto LogicalTreeHelper y el
método GetChild del objeto VisualTreeHelper con el mismo elemento que un parámetro, se generan
resultados diferentes.
Para más información acerca del árbol lógico, consulte Árboles en WPF.
Visualización del árbol visual con XamlPad
La herramienta de WPF, XamlPad, proporciona una opción para ver y explorar el árbol visual que corresponde
al contenido XAML definido actualmente. Haga clic en el botón Show Visual Tree (Mostrar árbol visual) de la
barra de menús para mostrar el árbol visual. A continuación se muestra la expansión de contenido XAML en
nodos de árbol visual en el panel del Explorador de árbol visual de XamlPad:

Observe cómo los controles Label, TextBoxy Button muestran una jerarquía de objetos visuales independiente
en el panel del Explorador de árbol visual de XamlPad. Esto se debe a que los controles WPF tienen un
ControlTemplate que contiene el árbol visual de ese control. Al hacer referencia explícitamente a un control,
implícitamente también se hace referencia a su jerarquía visual.
Generación de perfiles de rendimiento visual
WPF ofrece un conjunto de herramientas de generación de perfiles de rendimiento que le permiten analizar el
comportamiento en tiempo de ejecución de la aplicación y determinar los tipos de optimizaciones de
rendimiento que puede aplicar. La herramienta Generador de perfiles visuales proporciona una vista gráfica
completa de los datos de rendimiento mediante la asignación al árbol visual de la aplicación. En esta captura de
pantalla, la sección Uso de CPU del generador de perfiles visuales proporciona un desglose preciso del uso
que un objeto realiza de los servicios de WPF, como la representación y el diseño.

Resultados del generador de perfiles visuales

Comportamiento de la representación visual


WPF presenta varias características que afectan al comportamiento de la representación de los objetos visuales:
gráficos en modo retenido, gráficos vectoriales y gráficos independientes del dispositivo.
Gráficos en modo retenido
Una de las claves para conocer el rol del objeto visual es conocer la diferencia entre los sistemas de gráficos del
modo inmediato y del modo retenido. Una aplicación Win32 estándar basada en GDI o GDI + utiliza un
sistema de gráficos de modo inmediato. Esto significa que la aplicación es responsable de volver a dibujar la
parte del área de cliente que se ha invalidado, debido a una acción, como el cambio de tamaño de una ventana
o al cambio de la apariencia visual de un objeto.

En cambio, WPF utiliza un sistema de modo retenido. Esto significa que los objetos de la aplicación que tienen
una apariencia visual definen un conjunto de datos de dibujo serializados. Una vez que se definen los datos de
dibujo, el sistema es responsable de responder a todas las solicitudes de repetición del dibujo para representar
los objetos de la aplicación. Incluso en tiempo de ejecución, puede modificar o crear objetos de la aplicación y
seguir confiando en que el sistema responderá a las solicitudes de dibujo. La eficacia de un sistema de gráficos
en modo retenido es que la aplicación guarda siempre la información de dibujo en un estado serializado, pero
la responsabilidad de la representación se deja al sistema. El siguiente diagrama muestra la forma en que la
aplicación usa WPF para responder a las solicitudes de dibujo.
Volver a dibujar de forma inteligente
Una de las mayores ventajas de utilizar gráficos en modo retenido es que WPF puede optimizar eficazmente lo
que hay que volver a dibujar en la aplicación. Aunque tenga una escena compleja con diferentes niveles de
opacidad, por lo general no es preciso escribir código especial para optimizar el redibujado. Compárelo esto
con la programación de Win32, en la que se puede dedicar mucho esfuerzo a optimizar la aplicación mediante
la minimización de la cantidad de redibujado que se realiza en la región de actualización. Consulte Redrawing in
the Update Region (Redibujado en la región de actualización) para obtener un ejemplo del tipo de complejidad
implicado en la optimización del redibujado en las aplicaciones de Win32.
Gráficos vectoriales
WPF usa gráficos vectoriales como formato de los datos de representación. Los gráficos vectoriales, que
incluyen Scalable Vector Graphics (SVG ), metarchivos de Windows (.wmf) y fuentes TrueType, almacenan datos
de representación y los transmiten como una lista de instrucciones que describen cómo volver a crear una
imagen mediante primitivas de gráficos. Por ejemplo, las fuentes TrueType son fuentes de esquema que
describen un conjunto de líneas, curvas y comandos, en lugar de una matriz de píxeles. Una de las ventajas
principales de los gráficos vectoriales es su capacidad para escalar a cualquier tamaño y resolución.
A diferencia de los gráficos vectoriales, los gráficos de mapa de bits almacenan los datos de representación
como una representación píxel a píxel de una imagen, previamente representada para una resolución específica.
Una de las principales diferencias entre los formatos de gráficos vectoriales y de mapa de bits es la fidelidad
con la imagen original. Por ejemplo, cuando se modifica el tamaño de una imagen de origen, los sistemas de
gráficos de mapa de bits ajustan la imagen, mientras que los sistemas de gráficos vectoriales la escalan, lo que
mantiene su fidelidad.
La ilustración siguiente muestra una imagen de origen cuyo tamaño se ha cambiado en un 300 %. Observe las
distorsiones que aparecen cuando la imagen de origen es un gráfico de mapa de bits y se ajusta, en lugar de
escalarse como imagen de gráfico vectorial.
El marcado siguiente muestra dos elementos Path definidos. El segundo elemento usa un ScaleTransform para
cambiar el tamaño de las instrucciones de dibujo del primer elemento en un 300%. Observe que las
instrucciones de dibujo de los elementos de la Path permanecen sin cambios.

<Path
Data="M10,100 C 60,0 100,200 150,100 z"
Fill="{StaticResource linearGradientBackground}"
Stroke="Black"
StrokeThickness="2" />

<Path
Data="M10,100 C 60,0 100,200 150,100 z"
Fill="{StaticResource linearGradientBackground}"
Stroke="Black"
StrokeThickness="2" >
<Path.RenderTransform>
<ScaleTransform ScaleX="3.0" ScaleY="3.0" />
</Path.RenderTransform>
</Path>

Acerca de los gráficos independientes de la resolución y del dispositivo


Hay dos factores del sistema que determinan el tamaño tanto del texto como de los gráficos en la pantalla: la
resolución y los puntos por pulgada. La resolución describe el número de píxeles que aparecen en la pantalla. A
medida que aumenta la resolución, disminuye el tamaño de los píxeles, lo que provoca que tanto los gráficos
como el texto parezcan menores. Un gráfico que se muestre en un monitor cuya resolución se haya configurado
en 1024 x 768 píxeles parecerá mucho más pequeño cuando dicha resolución se cambie a 1600 x 1200.
La otra configuración del sistema, los puntos por pulgada (ppp), describe el tamaño de una pulgada de pantalla,
en píxeles. La mayoría de los sistemas de Windows tienen un PPP de 96, lo que significa que una pulgada de
pantalla es de 96 píxeles. El aumento de la configuración de PPP aumenta el tamaño de la pulgada de la
pantalla; mientras que su disminución lo reduce, lo que significa que una pulgada de la pantalla no es el mismo
tamaño que una pulgada real; en la mayoría de los sistemas, es probable que no lo sea. A medida que se
aumente el valor de PPP, tanto el texto como los gráficos con reconocimiento de PPP serán mayores, ya que se
ha incrementado el tamaño de la pulgada de pantalla. El aumento del valor de PPP puede facilitar la lectura del
texto, especialmente en resoluciones altas.
No todas las aplicaciones reconocen el PPP: algunas utilizan los píxeles de hardware como unidad de medida
principal; por consiguiente, el cambio de los PPP del sistema no tiene ningún efecto en dichas aplicaciones.
Muchas otras aplicaciones utilizan unidades con reconocimiento de PPP para describir los tamaños de fuente,
pero usan píxeles para describir todo lo demás. Un valor de PPP es demasiado pequeño o demasiado grande
puede provocar problemas de diseño en estas aplicaciones, ya que el texto de las aplicaciones se escala con la
configuración de PPP del sistema, mientras que su interfaz de usuario no lo hace. Este problema se ha
eliminado en las aplicaciones desarrolladas mediante WPF.
WPF admite el escalado automático mediante el uso del píxel independiente del dispositivo como unidad de
medida principal, en lugar de los píxeles de hardware; tanto el texto como los gráficos se escalan correctamente
sin que el desarrollador de la aplicación tenga que realizar ningún trabajo adicional. La siguiente ilustración
muestra un ejemplo de cómo aparecen tanto el texto como los gráficos de WPF con diferentes configuraciones
de PPP.

Gráficos y texto con diferentes configuraciones de PPP

Clase VisualTreeHelper
La clase VisualTreeHelper es una clase auxiliar estática que proporciona funcionalidad de bajo nivel para
programar en el nivel de objeto visual, lo que resulta útil en escenarios muy concretos, como el desarrollo de
controles personalizados de alto rendimiento. En la mayoría de los casos, los objetos de marco de WPF de nivel
superior, como Canvas y TextBlock, ofrecen mayor flexibilidad y facilidad de uso.
Pruebas de posicionamiento
La clase VisualTreeHelper proporciona métodos para realizar pruebas de posicionamiento en objetos visuales
cuando la compatibilidad con la prueba de posicionamiento predeterminada no satisface sus necesidades.
Puede usar los métodos HitTest de la clase VisualTreeHelper para determinar si un valor de coordenadas de
geometría o punto está dentro del límite de un objeto determinado, como un control o un elemento gráfico. Por
ejemplo, las pruebas de posicionamiento se pueden utilizar para determinar si un clic del mouse dentro del
rectángulo delimitador de un objeto pertenece a la geometría de un círculo. También puede elegir invalidar la
implementación predeterminada de las pruebas de posicionamiento para realizar sus propios cálculos de las
pruebas de posicionamiento.
Para más información acerca de las pruebas de posicionamiento, consulte Hit Testing in the Visual Layer
(Pruebas de posicionamiento en la capa visual).
Enumeración del árbol visual
La clase VisualTreeHelper proporciona funcionalidad para enumerar los miembros de un árbol visual. Para
recuperar un elemento primario, llame al método GetParent. Para recuperar un elemento secundario o un
descendiente directo de un objeto visual, llame al método GetChild. Este método devuelve un Visual secundario
del elemento primario en el índice especificado.
En el ejemplo siguiente se muestra cómo enumerar todos los descendientes de un objeto visual, que es una
técnica que se puede utilizar si se desea serializar toda la información de representación de una jerarquía de
objetos visuales.

// Enumerate all the descendants of the visual object.


static public void EnumVisual(Visual myVisual)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
{
// Retrieve child visual at specified index value.
Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);

// Do processing of the child visual object.

// Enumerate children of the child visual object.


EnumVisual(childVisual);
}
}

' Enumerate all the descendants of the visual object.


Public Shared Sub EnumVisual(ByVal myVisual As Visual)
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(myVisual) - 1
' Retrieve child visual at specified index value.
Dim childVisual As Visual = CType(VisualTreeHelper.GetChild(myVisual, i), Visual)

' Do processing of the child visual object.

' Enumerate children of the child visual object.


EnumVisual(childVisual)
Next i
End Sub

En la mayoría de los casos, el árbol lógico es una representación más útil de los elementos de una aplicación de
WPF. Aunque no se modifique directamente el árbol lógico, esta vista de la aplicación es útil para entender la
herencia de propiedades y el enrutamiento de eventos. A diferencia del árbol visual, el árbol lógico puede
representar objetos de datos no visuales, como ListItem. Para más información acerca del árbol lógico, consulte
Árboles en WPF.
La clase VisualTreeHelper proporciona métodos para devolver el rectángulo delimitador de objetos visuales.
Puede devolver el rectángulo delimitador de un objeto visual llamando a GetContentBounds. Puede devolver el
rectángulo delimitador de todos los descendientes de un objeto visual, incluido el propio objeto visual,
llamando a GetDescendantBounds. El código siguiente muestra cómo se calcularía el rectángulo delimitador de
un objeto visual y todos sus descendientes.

// Return the bounding rectangle of the parent visual object and all of its descendants.
Rect rectBounds = VisualTreeHelper.GetDescendantBounds(parentVisual);
' Return the bounding rectangle of the parent visual object and all of its descendants.
Dim rectBounds As Rect = VisualTreeHelper.GetDescendantBounds(parentVisual)

Consulte también
Visual
VisualTreeHelper
DrawingVisual
Imágenes y gráficos 2D
Realizar pruebas de posicionamiento en la capa visual
Usar objetos DrawingVisual
Tutorial: Hospedar objetos visuales en una aplicación Win32
Optimizar el rendimiento de la aplicación WPF
Gráficos
23/10/2019 • 2 minutes to read • Edit Online

Windows Presentation Foundation (WPF ) ofrece compatibilidad integrada para multimedia, gráficos vectoriales,
animaciones y creación de contenido, lo que facilita a los desarrolladores crear interfaces de usuario y el contenido
interesante.

En esta sección
Efectos de imagen
Pinceles
Dibujos
Geometrías
Imágenes
Formas
Transformaciones
Configuración del Registro en la representación de gráficos
Temas "Cómo..."

Vea también
Shape
Transform
BitmapImage
Geometry
Drawing
Brush
BitmapEffect
Imágenes y gráficos 2D
Gráficos y multimedia
Información general sobre la representación de gráficos en WPF
Efectos de imagen
23/10/2019 • 2 minutes to read • Edit Online

En los temas de esta sección se describe cómo aplicar efectos visuales a las imágenes Windows Presentation
Foundation (WPF )de mapa de bits mediante.

IMPORTANT
En el .NET Framework 4 o posterior, la BitmapEffect clase está obsoleta. Si intenta utilizar la BitmapEffect clase, obtendrá una
excepción obsoleta. La alternativa no obsoleta a la BitmapEffect clase es la Effect clase. En la mayoría de los Effect casos, la
clase es significativamente más rápida.

En esta sección
Información general sobre efectos de imagen

Referencia
BitmapEffect
System.Windows.Media.Effects

Secciones relacionadas
Gráficos y multimedia
Información general sobre imágenes
Información general sobre efectos de imagen
08/01/2020 • 6 minutes to read • Edit Online

Los efectos de imagen permiten a los diseñadores y desarrolladores aplicar efectos visuales a contenido
representado Windows Presentation Foundation (WPF ). Por ejemplo, los efectos de imagen permiten aplicar
fácilmente un efecto de DropShadowBitmapEffect o un efecto de desenfoque a una imagen o un botón.

IMPORTANT
En el .NET Framework 4 o posterior, la clase BitmapEffect está obsoleta. Si intenta utilizar la clase BitmapEffect, obtendrá una
excepción obsoleta. La alternativa no obsoleta a la clase BitmapEffect es la clase Effect. En la mayoría de los casos, la clase
Effect es significativamente más rápida.

Efectos de imagen de WPF


Los efectos de imagen (objetoBitmapEffect) son operaciones de procesamiento de píxeles simples. Un efecto de
mapa de bits toma un BitmapSource como entrada y genera un nuevo BitmapSource después de aplicar el efecto,
como un desenfoque o una sombra paralela. Cada efecto de imagen expone propiedades que pueden controlar las
propiedades de filtrado, como Radius de BlurBitmapEffect.
Como caso especial, en WPF, los efectos pueden establecerse como propiedades de objetos Visual activos, como
un Button o TextBox. El procesamiento de píxeles se aplica y se representa en tiempo de ejecución. En este caso, en
el momento de la representación, un Visual se convierte automáticamente a su BitmapSource equivalente y se
introduce como entrada para el BitmapEffect. La salida reemplaza el comportamiento de representación
predeterminado del objeto Visual. Este es el motivo por el que BitmapEffect objetos hacen que los objetos visuales
se representen solo en el software, es decir, no hay aceleración de hardware en objetos visuales cuando se aplican
efectos.
BlurBitmapEffect simula un objeto que aparece como desenfocado.
OuterGlowBitmapEffect crea un halo de color alrededor del perímetro de un objeto.
DropShadowBitmapEffect crea una sombra detrás de un objeto.
BevelBitmapEffect crea un bisel que eleva la superficie de una imagen según una curva especificada.
EmbossBitmapEffect crea una asignación de rugosidad de un Visual para dar la impresión de profundidad y
textura de una fuente de luz artificial.

NOTE
Los efectos de imagen de WPF se representan en modo de software. Cualquier objeto que aplique un efecto también se
representará en software. El rendimiento disminuye al máximo al usar los efectos de imagen en objetos visuales grandes o al
animar las propiedades de un efecto de imagen. Esto no quiere decir que no se deben usar efectos de imagen de esta
manera en absoluto, pero hay que tener cuidado y probarlos exhaustivamente para asegurarse de que los usuarios obtengan
la experiencia esperada.
NOTE
Los efectos de imagen de WPF no admiten la ejecución de confianza parcial. Una aplicación debe tener permisos de plena
confianza para usar efectos de imagen.

Cómo aplicar un efecto


BitmapEffect es una propiedad de Visual. Por lo tanto, aplicar efectos a objetos visuales, como un Button, Image,
DrawingVisualo UIElement, es tan sencillo como establecer una propiedad. BitmapEffect se puede establecer en un
objeto de BitmapEffect único o se pueden encadenar varios efectos mediante el objeto BitmapEffectGroup.
En el ejemplo siguiente se muestra cómo aplicar un BitmapEffect en Lenguaje XAML (Extensible Application
Markup Language).

<Button Width="200">You Can't Read This!


<Button.BitmapEffect>

<!-- <BitmapEffectGroup> would go here if you wanted to apply more


then one effect to the Button. However, in this example only
one effect is being applied so BitmapEffectGroup does not need
to be included. -->

<!-- The larger the Radius, the more blurring. The default range is 20.
In addition, the KernelType is set to a box kernel. A box kernel
creates less disruption (less blur) then the default Gaussian kernel. -->
<BlurBitmapEffect Radius="10" KernelType="Box" />

</Button.BitmapEffect>
</Button>

En el ejemplo siguiente se muestra cómo aplicar un BitmapEffect en el código.

// Get a reference to the Button.


Button myButton = (Button)sender;

// Initialize a new BlurBitmapEffect that will be applied


// to the Button.
BlurBitmapEffect myBlurEffect = new BlurBitmapEffect();

// Set the Radius property of the blur. This determines how


// blurry the effect will be. The larger the radius, the more
// blurring.
myBlurEffect.Radius = 10;

// Set the KernelType property of the blur. A KernalType of "Box"


// creates less blur than the Gaussian kernal type.
myBlurEffect.KernelType = KernelType.Box;

// Apply the bitmap effect to the Button.


myButton.BitmapEffect = myBlurEffect;

NOTE
Cuando se aplica un BitmapEffect a un contenedor de diseño, como DockPanel o Canvas, el efecto se aplica al árbol visual del
elemento u objetos visuales, incluidos todos sus elementos secundarios.

Crear efectos personalizados


WPF también proporciona interfaces no administradas para crear efectos personalizados que se pueden usar en
aplicaciones WPF administradas. Para obtener material de referencia adicional para crear efectos de imagen
personalizados, consulte la documentación de Unmanaged WPF Bitmap Effect (Efecto de imagen de WPF no
administrado).

Vea también
BitmapEffectGroup
BitmapEffectInput
BitmapEffectCollection
Efecto de imagen de WPF no administrado
Información general sobre imágenes
Seguridad
Información general sobre la representación de gráficos en WPF
Imágenes y gráficos 2D
Pinceles
23/10/2019 • 2 minutes to read • Edit Online

Los temas siguientes describen cómo usar Windows Presentation Foundation (WPF ) pinceles que "pintar"
contenido en la pantalla

En esta sección
Información general sobre pinceles de WPF
Información general sobre la transformación de pinceles
Información general sobre las máscaras de opacidad
Información general sobre el dibujo con colores sólidos y degradados
Pintar con imágenes, dibujos y elementos visuales
Información general sobre objetos TileBrush
Temas "Cómo..."

Referencia
Brush
SolidColorBrush
LinearGradientBrush
RadialGradientBrush
DrawingBrush
VisualBrush

Secciones relacionadas
Gráficos y multimedia
Información general sobre la representación de gráficos en WPF
Información general sobre pinceles de WPF
03/02/2020 • 14 minutes to read • Edit Online

Todo lo que está visible en la pantalla es visible porque lo ha pintado un pincel. Por ejemplo, se usa un pincel para
describir el fondo de un botón, el primer plano del texto y el relleno de una forma. En este tema se presentan los
conceptos del dibujo con pinceles de Windows Presentation Foundation (WPF ) y se proporcionan ejemplos. Los
pinceles permiten pintar objetos interfaz de usuario (UI) con cualquier cosa, desde colores simples y sólidos hasta
conjuntos complejos de patrones e imágenes.

Pintar con un pincel


Un Brush "pinta" un área con su salida. Los distintos pinceles tienen distintos tipos de resultados. Algunos
pinceles pintan un área con un color sólido, otros con un degradado, un patrón, una imagen o un dibujo. En la
ilustración siguiente se muestran ejemplos de cada uno de los distintos tipos de Brush.

Ejemplos de pincel
La mayoría de los objetos visuales le permiten especificar cómo se dibujan. En la tabla siguiente se enumeran
algunos objetos y propiedades comunes con los que puede usar un Brush.

CLASE PROPIEDADES DE PINCEL

Border BorderBrush, Background

Control Background, Foreground

Panel Background

Pen Brush

Shape Fill, Stroke

TextBlock Background

En las secciones siguientes se describen los distintos tipos de Brush y se proporciona un ejemplo de cada uno.
Pintar con un color sólido
Un SolidColorBrush pinta un área con un Colorsólido. Hay varias maneras de especificar el Color de un
SolidColorBrush: por ejemplo, puede especificar sus canales alfa, rojo, azul y verde, o bien usar uno de los colores
predefinidos proporcionados por la clase Colors.
En el ejemplo siguiente se utiliza un SolidColorBrush para pintar el Fill de una Rectangle. En la ilustración
siguiente se muestra el rectángulo pintado.

Rectángulo pintado mediante SolidColorBrush

Rectangle exampleRectangle = new Rectangle();


exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a SolidColorBrush and use it to


// paint the rectangle.
SolidColorBrush myBrush = new SolidColorBrush(Colors.Red);
exampleRectangle.Fill = myBrush;

Dim exampleRectangle As New Rectangle()


exampleRectangle.Width = 75
exampleRectangle.Height = 75

' Create a SolidColorBrush and use it to


' paint the rectangle.
Dim myBrush As New SolidColorBrush(Colors.Red)
exampleRectangle.Fill = myBrush

<Rectangle Width="75" Height="75">


<Rectangle.Fill>
<SolidColorBrush Color="Red" />
</Rectangle.Fill>
</Rectangle>

Para obtener más información sobre la clase SolidColorBrush, consulte la información general sobre el dibujo
con colores sólidos y degradados.

Pintar con un degradado lineal


LinearGradientBrush pinta un área con un degradado lineal. Un degradado lineal combina dos o más colores en
una línea, el eje de degradado. Los objetos GradientStop se usan para especificar los colores del degradado y sus
posiciones.
En el ejemplo siguiente se utiliza un LinearGradientBrush para pintar el Fill de una Rectangle. En la ilustración
siguiente se muestra el rectángulo pintado.

Rectángulo pintado mediante LinearGradientBrush


Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a LinearGradientBrush and use it to


// paint the rectangle.
LinearGradientBrush myBrush = new LinearGradientBrush();
myBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myBrush.GradientStops.Add(new GradientStop(Colors.Orange, 0.5));
myBrush.GradientStops.Add(new GradientStop(Colors.Red, 1.0));

exampleRectangle.Fill = myBrush;

Dim exampleRectangle As New Rectangle()


exampleRectangle.Width = 75
exampleRectangle.Height = 75

' Create a LinearGradientBrush and use it to


' paint the rectangle.
Dim myBrush As New LinearGradientBrush()
myBrush.GradientStops.Add(New GradientStop(Colors.Yellow, 0.0))
myBrush.GradientStops.Add(New GradientStop(Colors.Orange, 0.5))
myBrush.GradientStops.Add(New GradientStop(Colors.Red, 1.0))

exampleRectangle.Fill = myBrush

<Rectangle Width="75" Height="75">


<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Red" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

Para obtener más información sobre la clase LinearGradientBrush, consulte la información general sobre el
dibujo con colores sólidos y degradados.

Pintar con un degradado radial


RadialGradientBrush pinta un área con un degradado radial. Un degradado radial combina dos o más colores en
un círculo. Al igual que con la clase LinearGradientBrush, se usan GradientStop objetos para especificar los
colores del degradado y sus posiciones.
En el ejemplo siguiente se utiliza un RadialGradientBrush para pintar el Fill de una Rectangle. En la ilustración
siguiente se muestra el rectángulo pintado.

Rectángulo pintado mediante RadialGradientBrush


Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a RadialGradientBrush and use it to


// paint the rectangle.
RadialGradientBrush myBrush = new RadialGradientBrush();
myBrush.GradientOrigin = new Point(0.75, 0.25);
myBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myBrush.GradientStops.Add(new GradientStop(Colors.Orange, 0.5));
myBrush.GradientStops.Add(new GradientStop(Colors.Red, 1.0));

exampleRectangle.Fill = myBrush;

Dim exampleRectangle As New Rectangle()


exampleRectangle.Width = 75
exampleRectangle.Height = 75

' Create a RadialGradientBrush and use it to


' paint the rectangle.
Dim myBrush As New RadialGradientBrush()
myBrush.GradientOrigin = New Point(0.75, 0.25)
myBrush.GradientStops.Add(New GradientStop(Colors.Yellow, 0.0))
myBrush.GradientStops.Add(New GradientStop(Colors.Orange, 0.5))
myBrush.GradientStops.Add(New GradientStop(Colors.Red, 1.0))

exampleRectangle.Fill = myBrush

<Rectangle Width="75" Height="75">


<Rectangle.Fill>
<RadialGradientBrush GradientOrigin="0.75,0.25">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Red" Offset="1.0" />
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>

Para obtener más información sobre la clase RadialGradientBrush, consulte la información general sobre el
dibujo con colores sólidos y degradados.

Pintar con una imagen


Un ImageBrush pinta un área con un ImageSource.
En el ejemplo siguiente se utiliza un ImageBrush para pintar el Fill de una Rectangle. En la ilustración siguiente se
muestra el rectángulo pintado.

Rectángulo pintado mediante una imagen


Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create an ImageBrush and use it to


// paint the rectangle.
ImageBrush myBrush = new ImageBrush();
myBrush.ImageSource =
new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative));

exampleRectangle.Fill = myBrush;

Dim exampleRectangle As New Rectangle()


exampleRectangle.Width = 75
exampleRectangle.Height = 75

' Create an ImageBrush and use it to


' paint the rectangle.
Dim myBrush As New ImageBrush()
myBrush.ImageSource = New BitmapImage(New Uri("sampleImages\pinkcherries.jpg", UriKind.Relative))

exampleRectangle.Fill = myBrush

<Rectangle Width="75" Height="75">


<Rectangle.Fill>
<ImageBrush ImageSource="sampleImages\pinkcherries.jpg" />
</Rectangle.Fill>
</Rectangle>

Para obtener más información sobre la clase ImageBrush, vea pintar con imágenes, dibujos y objetos visuales.

Pintar con un dibujo


DrawingBrush pinta un área con un Drawing. Un Drawing puede contener formas, imágenes, texto y elementos
multimedia.
En el ejemplo siguiente se utiliza un DrawingBrush para pintar el Fill de una Rectangle. En la ilustración siguiente
se muestra el rectángulo pintado.

Rectángulo pintado mediante DrawingBrush


Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a DrawingBrush and use it to


// paint the rectangle.
DrawingBrush myBrush = new DrawingBrush();

GeometryDrawing backgroundSquare =
new GeometryDrawing(
Brushes.White,
null,
new RectangleGeometry(new Rect(0, 0, 100, 100)));

GeometryGroup aGeometryGroup = new GeometryGroup();


aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 50, 50)));
aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(50, 50, 50, 50)));

LinearGradientBrush checkerBrush = new LinearGradientBrush();


checkerBrush.GradientStops.Add(new GradientStop(Colors.Black, 0.0));
checkerBrush.GradientStops.Add(new GradientStop(Colors.Gray, 1.0));

GeometryDrawing checkers = new GeometryDrawing(checkerBrush, null, aGeometryGroup);

DrawingGroup checkersDrawingGroup = new DrawingGroup();


checkersDrawingGroup.Children.Add(backgroundSquare);
checkersDrawingGroup.Children.Add(checkers);

myBrush.Drawing = checkersDrawingGroup;
myBrush.Viewport = new Rect(0, 0, 0.25, 0.25);
myBrush.TileMode = TileMode.Tile;

exampleRectangle.Fill = myBrush;

Dim exampleRectangle As New Rectangle()


exampleRectangle.Width = 75
exampleRectangle.Height = 75

' Create a DrawingBrush and use it to


' paint the rectangle.
Dim myBrush As New DrawingBrush()

Dim backgroundSquare As New GeometryDrawing(Brushes.White, Nothing, New RectangleGeometry(New Rect(0, 0, 100,


100)))

Dim aGeometryGroup As New GeometryGroup()


aGeometryGroup.Children.Add(New RectangleGeometry(New Rect(0, 0, 50, 50)))
aGeometryGroup.Children.Add(New RectangleGeometry(New Rect(50, 50, 50, 50)))

Dim checkerBrush As New LinearGradientBrush()


checkerBrush.GradientStops.Add(New GradientStop(Colors.Black, 0.0))
checkerBrush.GradientStops.Add(New GradientStop(Colors.Gray, 1.0))

Dim checkers As New GeometryDrawing(checkerBrush, Nothing, aGeometryGroup)

Dim checkersDrawingGroup As New DrawingGroup()


checkersDrawingGroup.Children.Add(backgroundSquare)
checkersDrawingGroup.Children.Add(checkers)

myBrush.Drawing = checkersDrawingGroup
myBrush.Viewport = New Rect(0, 0, 0.25, 0.25)
myBrush.TileMode = TileMode.Tile

exampleRectangle.Fill = myBrush
<Rectangle Width="75" Height="75">
<Rectangle.Fill>
<DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,100,100" />
</GeometryDrawing.Geometry>
</GeometryDrawing>

<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50" />
<RectangleGeometry Rect="50,50,50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Black" />
<GradientStop Offset="1.0" Color="Gray" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>

Para obtener más información sobre la clase DrawingBrush, vea pintar con imágenes, dibujos y objetos visuales.

Pintar con un visual


VisualBrush pinta un área con un objeto Visual. Entre los ejemplos de objetos visuales se incluyen Button, Pagey
MediaElement. Un VisualBrush también permite proyectar el contenido de una parte de la aplicación en otra área;
resulta muy útil para crear efectos de reflexión y ampliar partes de la pantalla.
En el ejemplo siguiente se utiliza un VisualBrush para pintar el Fill de una Rectangle. En la ilustración siguiente se
muestra el rectángulo pintado.

Rectángulo pintado mediante VisualBrush


Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a VisualBrush and use it


// to paint the rectangle.
VisualBrush myBrush = new VisualBrush();

//
// Create the brush's contents.
//
StackPanel aPanel = new StackPanel();

// Create a DrawingBrush and use it to


// paint the panel.
DrawingBrush myDrawingBrushBrush = new DrawingBrush();
GeometryGroup aGeometryGroup = new GeometryGroup();
aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 50, 50)));
aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(50, 50, 50, 50)));
RadialGradientBrush checkerBrush = new RadialGradientBrush();
checkerBrush.GradientStops.Add(new GradientStop(Colors.MediumBlue, 0.0));
checkerBrush.GradientStops.Add(new GradientStop(Colors.White, 1.0));
GeometryDrawing checkers = new GeometryDrawing(checkerBrush, null, aGeometryGroup);
myDrawingBrushBrush.Drawing = checkers;
aPanel.Background = myDrawingBrushBrush;

// Create some text.


TextBlock someText = new TextBlock();
someText.Text = "Hello, World";
FontSizeConverter fSizeConverter = new FontSizeConverter();
someText.FontSize = (double)fSizeConverter.ConvertFromString("10pt");
someText.Margin = new Thickness(10);

aPanel.Children.Add(someText);

myBrush.Visual = aPanel;
exampleRectangle.Fill = myBrush;
Dim exampleRectangle As New Rectangle()
exampleRectangle.Width = 75
exampleRectangle.Height = 75

' Create a VisualBrush and use it


' to paint the rectangle.
Dim myBrush As New VisualBrush()

'
' Create the brush's contents.
'
Dim aPanel As New StackPanel()

' Create a DrawingBrush and use it to


' paint the panel.
Dim myDrawingBrushBrush As New DrawingBrush()
Dim aGeometryGroup As New GeometryGroup()
aGeometryGroup.Children.Add(New RectangleGeometry(New Rect(0, 0, 50, 50)))
aGeometryGroup.Children.Add(New RectangleGeometry(New Rect(50, 50, 50, 50)))
Dim checkerBrush As New RadialGradientBrush()
checkerBrush.GradientStops.Add(New GradientStop(Colors.MediumBlue, 0.0))
checkerBrush.GradientStops.Add(New GradientStop(Colors.White, 1.0))
Dim checkers As New GeometryDrawing(checkerBrush, Nothing, aGeometryGroup)
myDrawingBrushBrush.Drawing = checkers
aPanel.Background = myDrawingBrushBrush

' Create some text.


Dim someText As New TextBlock()
someText.Text = "Hello, World"
Dim fSizeConverter As New FontSizeConverter()
someText.FontSize = CDbl(fSizeConverter.ConvertFromString("10pt"))
someText.Margin = New Thickness(10)

aPanel.Children.Add(someText)

myBrush.Visual = aPanel
exampleRectangle.Fill = myBrush
<Rectangle Width="75" Height="75">
<Rectangle.Fill>
<VisualBrush TileMode="Tile">
<VisualBrush.Visual>
<StackPanel>
<StackPanel.Background>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Brush>
<RadialGradientBrush>
<GradientStop Color="MediumBlue" Offset="0.0" />
<GradientStop Color="White" Offset="1.0" />
</RadialGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50" />
<RectangleGeometry Rect="50,50,50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</StackPanel.Background>
<TextBlock FontSize="10pt" Margin="10">Hello, World!</TextBlock>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>

Para obtener más información sobre la clase VisualBrush, vea pintar con imágenes, dibujos y objetos visuales.

Pintar usando predefinidos y pinceles del sistema


Para mayor comodidad, Windows Presentation Foundation (WPF ) proporciona un conjunto de pinceles de
sistema y predefinidos que puede usar para pintar objetos.
Para obtener una lista de los pinceles predefinidos disponibles, vea la clase Brushes. Para ver un ejemplo
en el que se muestra cómo usar un pincel predefinido, vea pintar un área con un color sólido.
Para obtener una lista de los pinceles del sistema disponibles, vea la clase SystemColors. Para obtener un
ejemplo, vea pintar un área con un pincel del sistema.

Características comunes de los pinceles


los objetos Brush proporcionan una propiedad Opacity que se puede utilizar para hacer que un pincel sea
transparente o parcialmente transparente. Un valor Opacity de 0 hace que un pincel sea completamente
transparente, mientras que un valor Opacity de 1 hace que un pincel sea completamente opaco. En el ejemplo
siguiente se usa la propiedad Opacity para convertir un SolidColorBrush en un 25 por ciento opaco.

<Rectangle Width="100" Height="100">


<Rectangle.Fill>
<SolidColorBrush Color="Blue" Opacity="0.25" />
</Rectangle.Fill>
</Rectangle>
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 100;
myRectangle.Height = 100;
SolidColorBrush partiallyTransparentSolidColorBrush
= new SolidColorBrush(Colors.Blue);
partiallyTransparentSolidColorBrush.Opacity = 0.25;
myRectangle.Fill = partiallyTransparentSolidColorBrush;

Si el pincel contiene colores que son parcialmente transparentes, el valor de opacidad del color se combina a
través de la multiplicación con el valor de opacidad del pincel. Por ejemplo, si un pincel tiene un valor de opacidad
de 0,5 y un color usado en el pincel también tiene un valor de opacidad de 0,5, el color de salida tiene un valor de
opacidad de 0,25.

NOTE
Es más eficaz cambiar el valor de opacidad de un pincel que cambiar la opacidad de un elemento completo mediante su
UIElement.Opacity propiedad.

Puede girar, escalar, sesgar y trasladar el contenido de un pincel mediante sus propiedades Transform o
RelativeTransform. Para obtener más información, vea información general sobre la transformación Brush.
Dado que se Animatable objetos, se pueden animar Brush objetos. Para obtener más información, consulte
Información general sobre animaciones.
Características de los objetos Freezable
Dado que hereda de la clase Freezable, la clase Brush proporciona varias características especiales: los objetos
Brush se pueden declarar como recursos, compartirse entre varios objetos y clonados. Además, todos los tipos de
Brush excepto VisualBrush se pueden convertir en de solo lectura para mejorar el rendimiento y hacerlos seguros
para subprocesos.
Para obtener más información sobre las distintas características proporcionadas por Freezable objetos, vea
información general sobre objetos Freezable.
Para obtener más información sobre por qué no se pueden inmovilizar VisualBrush objetos, vea la página tipo de
VisualBrush.

Consulte también
Brush
Brushes
Información general sobre el dibujo con colores sólidos y degradados
Pintar con imágenes, dibujos y elementos visuales
Información general sobre objetos Freezable
Ejemplo de pinceles
Ejemplo de ImageBrush
Ejemplo de VisualBrush
Temas "Cómo..."
Otras recomendaciones de rendimiento
Información general sobre la transformación de
pinceles
20/02/2020 • 8 minutes to read • Edit Online

La clase Brush proporciona dos propiedades de transformación: Transform y RelativeTransform. Las propiedades
permiten girar, escalar, sesgar y trasladar el contenido de un pincel. En este tema se describen las diferencias entre
estas dos propiedades y proporciona ejemplos de su uso.

Prerequisites
Para entender este tema, debe entender las características del pincel que se va a transformar. Para obtener
LinearGradientBrush y RadialGradientBrush, consulte la información general sobre el dibujo con colores sólidos y
degradados. Por ImageBrush, DrawingBrusho VisualBrush, vea pintar con imágenes, dibujos y objetos visuales.
También debe estar familiarizado con las transformaciones 2D descritas en Información general sobre
transformaciones.

Diferencias entre las propiedades Transform y RelativeTransform


Al aplicar una transformación a la propiedad Transform de un pincel, debe conocer el tamaño del área pintada si
desea transformar el contenido del pincel sobre su centro. Supongamos que el área pintada tiene 200 píxeles
independientes del dispositivo de ancho y 150 de alto. Si ha usado una RotateTransform para rotar la salida del
pincel 45 grados sobre su centro, deberá asignar a la RotateTransform un CenterX de 100 y un CenterY de 75.
Al aplicar una transformación a la propiedad RelativeTransform de un pincel, esa transformación se aplica al
pincel antes de que su salida se asigne al área pintada. En la lista siguiente se describe el orden en el que se
procesan y transforman los contenidos de un pincel.
1. Procese el contenido del pincel. Para un GradientBrush, esto significa determinar el área de degradado.
Para un TileBrush, el Viewbox se asigna a la Viewport. Esto se convierte en la salida del pincel.
2. Proyecte la salida del pincel en el rectángulo de transformación de 1 x 1.
3. Aplique el RelativeTransformdel pincel, si lo tiene.
4. Proyecte la salida transformada en el área que se va a pintar.
5. Aplique el Transformdel pincel, si lo tiene.
Dado que el RelativeTransform se aplica mientras la salida del pincel está asignada a un rectángulo de 1 x 1, los
valores del centro de transformación y del desplazamiento parecen ser relativos. Por ejemplo, si ha usado una
RotateTransform para girar la salida del pincel 45 grados sobre su centro, deberá asignar a la RotateTransform un
CenterX de 0,5 y un CenterY de 0,5.
En la ilustración siguiente se muestra la salida de varios pinceles que se han girado en 45 grados mediante las
propiedades RelativeTransform y Transform.
Utilizar RelativeTransform con un objeto TileBrush
Dado que los pinceles de mosaico son más complejos que otros pinceles, aplicar un RelativeTransform a uno
podría producir resultados inesperados. Por ejemplo, veamos la imagen siguiente.

En el ejemplo siguiente se usa un ImageBrush para pintar un área rectangular con la imagen anterior. Aplica un
RotateTransform a la propiedad RelativeTransform del objeto ImageBrush y establece su propiedad Stretch en
UniformToFill, que debe conservar la relación de aspecto de la imagen cuando se ajusta para rellenar
completamente el rectángulo.

<Rectangle Width="200" Height="100" Stroke="Black" StrokeThickness="1">


<Rectangle.Fill>
<ImageBrush Stretch="UniformToFill">
<ImageBrush.ImageSource>
<BitmapImage UriSource="sampleImages\square.jpg" />
</ImageBrush.ImageSource>
<ImageBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="90" />
</ImageBrush.RelativeTransform>
</ImageBrush>
</Rectangle.Fill>
</Rectangle>

En este ejemplo se produce la siguiente salida:

Observe que la imagen está distorsionada, aunque el Stretch del pincel se haya establecido en UniformToFill. Esto
se debe a que la transformación relativa se aplica después de que la Viewbox del pincel se asigna a su Viewport.
La lista siguiente describe cada paso del proceso:
1. Proyectar el contenido del pincel (Viewbox) en su mosaico base (Viewport) mediante el valor Stretch del
pincel.
2. Proyecte el icono base del rectángulo de transformación de 1 x 1.

3. Aplique el RotateTransform.

4. Proyecte el icono base transformado en el área que se va a pintar.

Ejemplo: Girar un objeto ImageBrush 45 grados


En el ejemplo siguiente se aplica un RotateTransform a la propiedad RelativeTransform de una ImageBrush. Las
propiedades CenterX y CenterY del objeto RotateTransform se establecen en 0,5, las coordenadas relativas del
punto central del contenido. Como resultado, el contenido del pincel se gira sobre su centro.

//
// Create an ImageBrush with a relative transform and
// use it to paint a rectangle.
//
ImageBrush relativeTransformImageBrush = new ImageBrush();
relativeTransformImageBrush.ImageSource =
new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative));

// Create a 45 rotate transform about the brush's center


// and apply it to the brush's RelativeTransform property.
RotateTransform aRotateTransform = new RotateTransform();
aRotateTransform.CenterX = 0.5;
aRotateTransform.CenterY = 0.5;
aRotateTransform.Angle = 45;
relativeTransformImageBrush.RelativeTransform = aRotateTransform;

// Use the brush to paint a rectangle.


Rectangle relativeTransformImageBrushRectangle = new Rectangle();
relativeTransformImageBrushRectangle.Width = 175;
relativeTransformImageBrushRectangle.Height = 90;
relativeTransformImageBrushRectangle.Stroke = Brushes.Black;
relativeTransformImageBrushRectangle.Fill = relativeTransformImageBrush;
'
' Create an ImageBrush with a relative transform and
' use it to paint a rectangle.
'
Dim relativeTransformImageBrush As New ImageBrush()
relativeTransformImageBrush.ImageSource = New BitmapImage(New Uri("sampleImages\pinkcherries.jpg",
UriKind.Relative))

' Create a 45 rotate transform about the brush's center


' and apply it to the brush's RelativeTransform property.
Dim aRotateTransform As New RotateTransform()
aRotateTransform.CenterX = 0.5
aRotateTransform.CenterY = 0.5
aRotateTransform.Angle = 45
relativeTransformImageBrush.RelativeTransform = aRotateTransform

' Use the brush to paint a rectangle.


Dim relativeTransformImageBrushRectangle As New Rectangle()
relativeTransformImageBrushRectangle.Width = 175
relativeTransformImageBrushRectangle.Height = 90
relativeTransformImageBrushRectangle.Stroke = Brushes.Black
relativeTransformImageBrushRectangle.Fill = relativeTransformImageBrush

<Rectangle Width="175" Height="90" Stroke="Black">


<Rectangle.Fill>
<ImageBrush ImageSource="sampleImages\pinkcherries.jpg">
<ImageBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="45" />
</ImageBrush.RelativeTransform>
</ImageBrush>
</Rectangle.Fill>
</Rectangle>

En el ejemplo siguiente también se aplica un RotateTransform a un ImageBrush, pero se usa la propiedad


Transform en lugar de la propiedad RelativeTransform. Para girar el pincel sobre su centro, los CenterX y CenterY
del objeto de la RotateTransform deben establecerse en coordenadas absolutas. Como el rectángulo pintado por
el pincel es 175 por 90 píxeles, su punto central es (87,5, 45).

//
// Create an ImageBrush with a transform and
// use it to paint a rectangle.
//
ImageBrush transformImageBrush = new ImageBrush();
transformImageBrush.ImageSource =
new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative));

// Create a 45 rotate transform about the brush's center


// and apply it to the brush's Transform property.
RotateTransform anotherRotateTransform = new RotateTransform();
anotherRotateTransform.CenterX = 87.5;
anotherRotateTransform.CenterY = 45;
anotherRotateTransform.Angle = 45;
transformImageBrush.Transform = anotherRotateTransform;

// Use the brush to paint a rectangle.


Rectangle transformImageBrushRectangle = new Rectangle();
transformImageBrushRectangle.Width = 175;
transformImageBrushRectangle.Height = 90;
transformImageBrushRectangle.Stroke = Brushes.Black;
transformImageBrushRectangle.Fill = transformImageBrush;
'
' Create an ImageBrush with a transform and
' use it to paint a rectangle.
'
Dim transformImageBrush As New ImageBrush()
transformImageBrush.ImageSource = New BitmapImage(New Uri("sampleImages\pinkcherries.jpg", UriKind.Relative))

' Create a 45 rotate transform about the brush's center


' and apply it to the brush's Transform property.
Dim anotherRotateTransform As New RotateTransform()
anotherRotateTransform.CenterX = 87.5
anotherRotateTransform.CenterY = 45
anotherRotateTransform.Angle = 45
transformImageBrush.Transform = anotherRotateTransform

' Use the brush to paint a rectangle.


Dim transformImageBrushRectangle As New Rectangle()
transformImageBrushRectangle.Width = 175
transformImageBrushRectangle.Height = 90
transformImageBrushRectangle.Stroke = Brushes.Black
transformImageBrushRectangle.Fill = transformImageBrush

<Rectangle Width="175" Height="90" Stroke="Black">


<Rectangle.Fill>
<ImageBrush ImageSource="sampleImages\pinkcherries.jpg">
<ImageBrush.Transform>
<RotateTransform CenterX="87.5" CenterY="45" Angle="45" />
</ImageBrush.Transform>
</ImageBrush>
</Rectangle.Fill>
</Rectangle>

En la ilustración siguiente se muestra el pincel sin una transformación, con la transformación aplicada a la
propiedad RelativeTransform y con la transformación aplicada a la propiedad Transform.

Este ejemplo forma parte de un ejemplo mayor. Para ver el ejemplo completo, consulte el ejemplo de pinceles.
Para más información, consulte Información general sobre pinceles de WPF.

Consulte también
Transform
RelativeTransform
Transform
Brush
Información general sobre el dibujo con colores sólidos y degradados
Pintar con imágenes, dibujos y elementos visuales
Información general sobre transformaciones
Información general sobre las máscaras de opacidad
23/10/2019 • 12 minutes to read • Edit Online

Las máscaras de opacidad permiten hacer que partes de un elemento o un objeto visual sea total o parcialmente
transparentes. Para crear una máscara de opacidad, aplique Brush a la OpacityMask propiedad de un elemento o
Visual. El pincel se asigna al elemento o al objeto visual, y el valor de opacidad de cada píxel del pincel se usa para
determinar la opacidad resultante de cada píxel correspondiente del elemento o objeto visual.

Requisitos previos
En esta información general se supone que está Brush familiarizado con los objetos. Para una introducción sobre
el uso de los pinceles, consulte Información general sobre el dibujo con colores sólidos y degradados. Para obtener
información ImageBrush sobre DrawingBrushy, vea pintar con imágenes, dibujos y objetos visuales.

Creación de efectos visuales con máscaras de opacidad


Una máscara de opacidad funciona asignado su contenido al elemento o al objeto visual. Luego, el canal alfa de
cada uno de los píxeles del pincel se usa para determinar la opacidad resultante de los píxeles correspondientes del
elemento o el objeto visual y se omite el color real del pincel. Si una parte determinada del pincel es transparente,
la parte correspondiente del elemento o del objeto visual se vuelve transparente. Si una parte determinada del
pincel es opaca, no se modifica la parte correspondiente del elemento o del objeto visual. La opacidad que la
máscara de opacidad especifica se combina con cualquier ajuste de opacidad existente en el elemento o el objeto
visual. Por ejemplo, si un elemento es opaco en un 25 por ciento y se le aplica una máscara de opacidad que realiza
la transición desde totalmente opaco a totalmente transparente, el resultado es un elemento que hace una
transición desde el 25 por ciento de opacidad a totalmente transparente.

NOTE
Aunque en los ejemplos de esta información general se muestra el uso de las máscaras de opacidad en los elementos de
imagen, una máscara de Visualopacidad se puede aplicar a cualquier elemento o, incluidos los paneles y controles.

Las máscaras de opacidad se usan para crear efectos visuales interesantes, como crear imágenes o botones que se
desvanecen mediante un fundido, agregar texturas a los elementos o combinar degradados para generar
superficies cristalinas. En la ilustración siguiente se muestra el uso de una máscara de opacidad. Se usa un fondo
de cuadros para mostrar los elementos transparentes de la máscara.
Ejemplo de máscara de opacidad

Creación de una máscara de opacidad


Para crear una máscara de opacidad, cree un Brush y aplíquelo a la OpacityMask propiedad de un elemento u
objetos visuales. Puede usar cualquier tipo de Brush como máscara de opacidad.
LinearGradientBrush, RadialGradientBrush: Se usa para hacer que un elemento o visual se atenúe de la
vista.
En la imagen siguiente se LinearGradientBrush muestra una usada como máscara de opacidad.

Ejemplo de máscara de opacidad LinearGradientBrush


ImageBrush: Se usa para crear texturas y efectos de borde automáticos o inversos.
En la imagen siguiente se ImageBrush muestra una usada como máscara de opacidad.

Ejemplo de máscara de opacidad LinearGradientBrush


DrawingBrush: Se usa para crear máscaras de opacidad complejas a partir de patrones de formas,
imágenes y degradados.
En la imagen siguiente se DrawingBrush muestra una usada como máscara de opacidad.

Ejemplo de máscara de opacidad DrawingBrush


Los pinceles deLinearGradientBrush degradado (y RadialGradientBrush) son especialmente adecuados para su
uso como máscara de opacidad. Dado que SolidColorBrush un rellena un área con un color uniforme, las
máscaras de opacidad son deficientes; SolidColorBrush el uso de es equivalente al establecimiento de la
OpacityMask propiedad del elemento u objetos visuales.

Uso de degradado como máscara de opacidad


Para crear un relleno de degradado, se especifican dos o más delimitadores de degradado. Cada delimitador de
degradado contiene un color y una posición (consulte Información general sobre el dibujo con colores sólidos y
degradados para más información sobre cómo crear y usar degradados). El proceso es el mismo cuando se usa un
degradado como máscara de opacidad, con la excepción de que, en lugar de combinar los colores, el degradado de
la máscara de opacidad combina los valores del canal alfa. Por lo tanto, no importa el color real del contenido del
degradado; solo importa el canal alfa, u opacidad, de cada color. A continuación se muestra un ejemplo.

<!--With the opacity mask:-->


<Image
Width="200" Height="150"
Source="sampleImages\Waterlilies.jpg"
Margin="10"
HorizontalAlignment="Left"
Grid.Column="2" Grid.Row="3">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0.1,0.1" EndPoint="0.75,0.75">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black"/>
<GradientStop Offset="1" Color="Transparent"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Image.OpacityMask>
</Image>

Especificación de delimitadores de degradado para una máscara de


opacidad
En el ejemplo anterior, el color Black definido por el sistema se usa como color inicial del degradado. Dado que
todos los colores de la Colors clase, excepto Transparent, son totalmente opacos, se pueden usar para definir
simplemente un color de inicio para una máscara de opacidad de degradado.
Para tener un mayor control sobre los valores alfa al definir una máscara de opacidad, puede especificar el canal
alfa de los colores mediante la notación hexadecimal ARGB Color.FromScRgb en el marcado o mediante el
método.
Especificación de la opacidad del color en "XAML"
En Lenguaje XAML (Extensible Application Markup Language), se usa la notación hexadecimal ARGB para
especificar la opacidad de los colores individuales. La notación hexadecimal ARGB utiliza la sintaxis siguiente:
# aa rrggbb
El valor aa de la línea anterior representa un valor hexadecimal de dos dígitos que se usa para especificar la
opacidad del color. Cada uno de los valores rr, gg y bb representa un valor hexadecimal de dos dígitos que se usa
para especificar la cantidad de rojo, verde y azul en el color. Cada dígito hexadecimal debe tener un valor entre 0 t
9 y entre A y F. 0 es el valor menor y F, el mayor. Un valor alfa de 00 especifica un color completamente
transparente, mientras que un valor alfa de FF crea un color completamente opaco. En el ejemplo siguiente, la
notación ARGB hexadecimal se usa para especificar dos colores. El primero es completamente opaco, mientras que
el segundo, completamente transparente.
<Canvas.OpacityMask>
<RadialGradientBrush>
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#FF000000"/>
<GradientStop Offset="1" Color="#00000000"/>
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Canvas.OpacityMask>

Uso de imagen como máscara de opacidad


También se pueden usar imágenes como máscara de opacidad. En la imagen siguiente se muestra un ejemplo. Se
usa un fondo de cuadros para mostrar los elementos transparentes de la máscara.

Ejemplo de máscara de opacidad


Para usar una imagen como una máscara de opacidad, use ImageBrush para que contenga la imagen. Al crear una
imagen para usarla como máscara de opacidad, guarde la imagen en un formato que admita varios niveles de
transparencia, como Portable Network Graphics (PNG ). En el ejemplo siguiente se muestra el código que se usó
para crear la ilustración anterior.

<!-- With the Opacity Mask-->


<Image
Height="150"
Width="200"
Source="sampleImages/Waterlilies.jpg"
HorizontalAlignment="Left"
Margin="10"
Grid.Column="2" Grid.Row="1">
<Image.OpacityMask>
<ImageBrush ImageSource="sampleImages/tornedges.png"/>
</Image.OpacityMask>
</Image>

Uso de imagen en mosaico como máscara de opacidad


En el ejemplo siguiente, se usa la misma imagen con otra ImageBrush, pero las características de mosaico del
pincel se usan para generar mosaicos de la imagen 50 píxeles cuadrados.
<!-- With the Opacity Mask -->
<Image
Height="150"
Width="200"
Source="sampleImages/Waterlilies.jpg"
HorizontalAlignment="Left"
Margin="10"
Grid.Column="2" Grid.Row="2">

<Image.OpacityMask>
<ImageBrush
Viewport="0,0,50,50"
ViewportUnits="Absolute"
TileMode="Tile"
ImageSource="sampleImages/tornedges.png"/>
</Image.OpacityMask>
</Image>

Creación de una máscara de opacidad a partir de un dibujo


Se pueden usar dibujos como máscara de opacidad. Las formas contenidas en el dibujo se pueden rellenar con
degradados, colores sólidos, imágenes e, incluso, otros dibujos. La imagen siguiente muestra un ejemplo de un
dibujo que se usa como máscara de opacidad. Se usa un fondo de cuadros para mostrar los elementos
transparentes de la máscara.

Ejemplo de máscara de opacidad DrawingBrush


Para usar un dibujo como máscara de opacidad, use un DrawingBrush para que contenga el dibujo. En el ejemplo
siguiente se muestra el código que se usó para crear la ilustración anterior:
<!-- With the Opacity Mask-->
<Image
Grid.Row="4" Grid.Column="5"
Height="150"
Width="200"
Source="sampleImages/Waterlilies.jpg">
<Image.OpacityMask>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Brush>
<RadialGradientBrush>
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset="1" Color="Transparent" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0.05,0.05 0.9,0.9" />
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="0.1" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Image.OpacityMask>
</Image>

Uso de dibujo en mosaico como máscara de opacidad


Al igual que DrawingBrush ,sepuedehacerqueelImageBrushdibujo en mosaico. En el ejemplo siguiente, se usa un
pincel con dibujo para crear una máscara de opacidad en mosaico.
<!-- With the Opacity Mask-->
<Button
Grid.Row="8" Grid.Column="5"
Height="100"
Width="200"
FontFamily="MS Gothic"
FontSize="16">
A Button
<Button.OpacityMask>
<DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Brush>
<RadialGradientBrush>
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset="1" Color="Transparent" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0.05,0.05 0.9,0.9" />
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="0.1" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Button.OpacityMask>
</Button>

Vea también
Pintar con imágenes, dibujos y elementos visuales
Información general sobre el dibujo con colores sólidos y degradados
Información general sobre el dibujo con colores
sólidos y degradados
23/10/2019 • 22 minutes to read • Edit Online

En este tema se describe cómo SolidColorBrushusar LinearGradientBrushlos objetos RadialGradientBrush ,


y para pintar con colores sólidos, degradados lineales y degradados radiales.

Pintar un área con un color sólido


Una de las operaciones más comunes en cualquier plataforma es pintar un área con un sólido Color. Para
realizar esta tarea, Windows Presentation Foundation (WPF ) proporciona la SolidColorBrush clase. En las
secciones siguientes se describen las distintas formas de pintar SolidColorBrushcon un.
Usar SolidColorBrush en "XAML"
Para pintar un área con un color sólido en XAML, use una de las opciones siguientes.
Seleccione un pincel de color sólido predefinido por su nombre. Por ejemplo, puede establecer un
botón Background en "red" o "MediumBlue". Para obtener una lista de otros pinceles de color sólido
predefinidos, vea las Brushes propiedades estáticas de la clase. A continuación se muestra un ejemplo.

<!-- This button's background is painted with a red SolidColorBrush,


described using a named color. -->
<Button Background="Red">A Button</Button>

Elija un color en la paleta de colores de 32 bits; para ello, especifique las cantidades de rojo, verde y
azul que se combinarán en un color sólido. El formato para especificar un color de la paleta de 32 bits
es " #rrggbb", donde rr es un número hexadecimal de dos dígitos que especifica la cantidad relativa de
rojo, gg especifica la cantidad de verde y bb especifica la cantidad de azul. Además, el color se puede
especificar como "#aarrggbb", donde aa especifica el valor alfa, o la transparencia, del color. Este
enfoque le permite crear colores que sean parcialmente transparentes. En el ejemplo siguiente, el
Background Button de se establece en rojo totalmente opaco mediante la notación hexadecimal.

<!-- This button's background is painted with a red SolidColorBrush,


described using hexadecimal notation. -->
<Button Background="#FFFF0000">A Button</Button>

Use la sintaxis de etiquetas de propiedad SolidColorBrushpara describir un. Esta sintaxis es más
detallada y le permite especificar una configuración adicional, como la opacidad del pincel. En el
ejemplo siguiente, las Background propiedades de dos Button elementos se establecen en rojo
completamente opaco. El color del primer pincel se describe con un nombre de color predefinido. El
color del segundo pincel se describe con una notación hexadecimal.
<!-- Both of these buttons' backgrounds are painted with red
SolidColorBrush objects, described using object element
syntax. -->
<Button>A Button

<Button.Background>
<SolidColorBrush Color="Red" />
</Button.Background>
</Button>

<Button>A Button

<Button.Background>
<SolidColorBrush Color="#FFFF0000" />
</Button.Background>
</Button>

Pintar con SolidColorBrush en el código


Para pintar un área con un color sólido en el código, use una de las opciones siguientes.
Use uno de los pinceles predefinidos proporcionados por la Brushes clase. En el ejemplo siguiente,
Background Button de se establece en Red.

Button myButton = new Button();


myButton.Content = "A Button";
myButton.Background = Brushes.Red;

Cree un SolidColorBrush y establezca su Color propiedad mediante una Color estructura. Puede usar
un color predefinido de la Colors clase o puede Color crear con el método estático FromArgb .
En el ejemplo siguiente se muestra cómo establecer Color la propiedad SolidColorBrush de con un
color predefinido.

Button myButton = new Button();


myButton.Content = "A Button";

SolidColorBrush mySolidColorBrush = new SolidColorBrush();


mySolidColorBrush.Color = Colors.Red;
myButton.Background = mySolidColorBrush;

El estático FromArgb permite especificar los valores alfa, rojo, verde y azul del color. El intervalo habitual de
cada uno de estos valores es 0 a 255. Por ejemplo, un valor alfa de 0 indica que un color es completamente
transparente, mientras que un valor de 255 indica que es completamente opaco. Del mismo modo, un valor
rojo de 0 indica que un color no tiene rojo, mientras que un valor de 255 indica que un color tiene la
cantidad máxima posible de rojo. En el ejemplo siguiente, el color de un pincel se describe al especificar los
valores alfa, rojo, verde y azul.
Button myButton = new Button();
myButton.Content = "A Button";

SolidColorBrush mySolidColorBrush = new SolidColorBrush();


mySolidColorBrush.Color =
Color.FromArgb(
255, // Specifies the transparency of the color.
255, // Specifies the amount of red.
0, // specifies the amount of green.
0); // Specifies the amount of blue.

myButton.Background = mySolidColorBrush;

Para más formas de especificar el color, vea Color el tema de referencia.

Pintar un área con un degradado


Un pincel de degradado pinta un área con varios colores que se mezclan entre sí a lo largo de un eje. Puede
usarlos para crear impresiones de luz y sombra, lo da a los controles una sensación tridimensional. También
puede usarlos para simular vidrio, cromo, agua y otras superficies lisas. WPFproporciona dos tipos de
pinceles de LinearGradientBrush degradado: y RadialGradientBrush.

Degradados lineales
Dibuja un área con un degradado definido a lo largo de una línea, el eje de degradado. LinearGradientBrush
Los colores del degradado y su ubicación se especifican a lo largo GradientStop del eje de degradado
mediante objetos. También puede modificar el eje de degradado, lo que le permite crear degradados
horizontales y verticales e invertir la dirección de degradado. El eje de degradado se describe en la sección
siguiente. De manera predeterminada, se crea un degradado diagonal.
En el ejemplo siguiente se muestra el código que crea un degradado lineal con cuatro colores.

<!-- This rectangle is painted with a diagonal linear gradient. -->


<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Rectangle diagonalFillRectangle = new Rectangle();
diagonalFillRectangle.Width = 200;
diagonalFillRectangle.Height = 100;

// Create a diagonal linear gradient with four stops.


LinearGradientBrush myLinearGradientBrush =
new LinearGradientBrush();
myLinearGradientBrush.StartPoint = new Point(0,0);
myLinearGradientBrush.EndPoint = new Point(1,1);
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.Yellow, 0.0));
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.Red, 0.25));
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.Blue, 0.75));
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.LimeGreen, 1.0));

// Use the brush to paint the rectangle.


diagonalFillRectangle.Fill = myLinearGradientBrush;

Este código genera el degradado siguiente:

NOTE
En los ejemplos de degradado de este tema se usa el sistema de coordenadas predeterminado para establecer puntos
de inicio y extremos. El sistema de coordenadas predeterminado es relativo a un cuadro de límite: 0 indica 0 por ciento
del rectángulo de selección y 1 indica el 100 por ciento del cuadro de límite. Puede cambiar este sistema de
coordenadas estableciendo la MappingMode propiedad en el valor. Absolute Un sistema de coordenadas absoluto no
está relacionado con un rectángulo de selección. Los valores se interpretan directamente en el espacio local.

GradientStop Es el bloque de creación básico de un pincel de degradado. Un delimitador de Color degradado


Offset especifica un a lo largo del eje de degradado.
La propiedad del Color delimitador de degradado especifica el color del delimitador de degradado.
Puede establecer el color mediante el uso de un color predefinido (proporcionado por Colors la clase)
o especificando valores ScRGB o ARGB. En XAML, también puede usar la notación hexadecimal para
describir un color. Para obtener más información, vea Color la estructura.
La propiedad del Offset delimitador de degradado especifica la posición del color del delimitador de
degradado en el eje de degradado. El desplazamiento es un Double que va de 0 a 1. Cuanto más se
acerque a 0 el valor de desplazamiento de un delimitador de degradado, más cerca del inicio del
degradado está el color. Cuanto más se acerque a 1 el valor de desplazamiento del degradado, más
cerca del final del degradado está el color.
El color de cada punto entre los delimitadores de degradado está interpolado linealmente como una
combinación del color que especifican los dos delimitadores de degradado. En la ilustración siguiente se
resaltan los delimitadores de degradado del ejemplo anterior. Los círculos marcan la posición de los
delimitadores de degradado y una línea discontinua muestra el eje de degradado.
El primer delimitador de degradado especifica el color amarillo con un desplazamiento de 0.0 . El segundo
delimitador de degradado especifica el color rojo con un desplazamiento de 0.25 . Los puntos entre estos
dos delimitadores cambian gradualmente de amarillo a rojo a medida que se mueve de izquierda a derecha
a lo largo del eje de degradado. El tercer delimitador de degradado especifica el color azul con un
desplazamiento de 0.75 . Los puntos entre el segundo y el tercer delimitador de degradado cambian
gradualmente de rojo a azul. El cuarto delimitador de degradado especifica el color verde lima con un
desplazamiento de 1.0 . Los puntos entre el tercer y el cuarto delimitador de degradado cambian
gradualmente de azul a verde lima.
El eje de degradado
Tal como se mencionó anteriormente, los delimitadores de degradado de un pincel de degradado lineal están
ubicados a lo largo de una línea, el eje de degradado. Puede cambiar la orientación y el tamaño de la línea
mediante las propiedades y StartPoint EndPoint del pincel. Manipulando el StartPoint y EndPointel pincel,
puede crear degradados horizontales y verticales, invertir la dirección del degradado, condensar la
distribución del degradado, etc.
De forma predeterminada, los pinceles de StartPoint degradado lineal y EndPoint son relativos al área que se
está pintando. El punto (0,0) representa la esquina superior izquierda del área que se pinta, mientras que
(1,1) representa la esquina inferior derecha de la misma. El valor StartPoint predeterminado
LinearGradientBrush de es (0,0) y su valor predeterminado EndPoint es (1,1), que crea un degradado
diagonal que comienza en la esquina superior izquierda y se extiende hasta la esquina inferior derecha del
área que se está pintando. En la ilustración siguiente se muestra el eje de degradado de un pincel StartPoint
de EndPointdegradado lineal con default y.

En el ejemplo siguiente se muestra cómo crear un degradado horizontal especificando el y StartPoint


EndPointel del pincel. Observe que los delimitadores de degradado son los mismos que en los ejemplos
anteriores. con solo cambiar StartPoint y EndPoint, el degradado se ha cambiado de diagonal a horizontal.
<!-- This rectangle is painted with a horizontal linear gradient. -->
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

Rectangle horizontalFillRectangle = new Rectangle();


horizontalFillRectangle.Width = 200;
horizontalFillRectangle.Height = 100;

// Create a horizontal linear gradient with four stops.


LinearGradientBrush myHorizontalGradient =
new LinearGradientBrush();
myHorizontalGradient.StartPoint = new Point(0,0.5);
myHorizontalGradient.EndPoint = new Point(1,0.5);
myHorizontalGradient.GradientStops.Add(
new GradientStop(Colors.Yellow, 0.0));
myHorizontalGradient.GradientStops.Add(
new GradientStop(Colors.Red, 0.25));
myHorizontalGradient.GradientStops.Add(
new GradientStop(Colors.Blue, 0.75));
myHorizontalGradient.GradientStops.Add(
new GradientStop(Colors.LimeGreen, 1.0));

// Use the brush to paint the rectangle.


horizontalFillRectangle.Fill = myHorizontalGradient;

En la ilustración siguiente se muestra el degradado que se creó. El eje de degradado está marcado con una
línea discontinua, mientras que los delimitadores de degradado están marcados con círculos.

En el ejemplo siguiente se muestra cómo crear un degradado vertical.

<!-- This rectangle is painted with a vertical gradient. -->


<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Rectangle verticalFillRectangle = new Rectangle();
verticalFillRectangle.Width = 200;
verticalFillRectangle.Height = 100;

// Create a vertical linear gradient with four stops.


LinearGradientBrush myVerticalGradient =
new LinearGradientBrush();
myVerticalGradient.StartPoint = new Point(0.5,0);
myVerticalGradient.EndPoint = new Point(0.5,1);
myVerticalGradient.GradientStops.Add(
new GradientStop(Colors.Yellow, 0.0));
myVerticalGradient.GradientStops.Add(
new GradientStop(Colors.Red, 0.25));
myVerticalGradient.GradientStops.Add(
new GradientStop(Colors.Blue, 0.75));
myVerticalGradient.GradientStops.Add(
new GradientStop(Colors.LimeGreen, 1.0));

// Use the brush to paint the rectangle.


verticalFillRectangle.Fill = myVerticalGradient;

En la ilustración siguiente se muestra el degradado que se creó. El eje de degradado está marcado con una
línea discontinua, mientras que los delimitadores de degradado están marcados con círculos.

Degradados radiales
LinearGradientBrush ComoRadialGradientBrush , pinta un área con colores que se combinan a lo largo de
un eje. En los ejemplos anteriores se mostró que el eje de un pincel de degradado lineal es una línea recta. El
eje de un pincel de degradado radial está definido con un círculo; sus colores "se irradian" hacia afuera desde
su origen.
En el ejemplo siguiente, se usa un pincel de degradado radial para pintar el interior de un rectángulo.

<!-- This rectangle is painted with a diagonal linear gradient. -->


<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<RadialGradientBrush
GradientOrigin="0.5,0.5" Center="0.5,0.5"
RadiusX="0.5" RadiusY="0.5">
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
RadialGradientBrush myRadialGradientBrush = new RadialGradientBrush();
myRadialGradientBrush.GradientOrigin = new Point(0.5,0.5);
myRadialGradientBrush.Center = new Point(0.5,0.5);
myRadialGradientBrush.RadiusX = 0.5;
myRadialGradientBrush.RadiusY = 0.5;
myRadialGradientBrush.GradientStops.Add(
new GradientStop(Colors.Yellow, 0.0));
myRadialGradientBrush.GradientStops.Add(
new GradientStop(Colors.Red, 0.25));
myRadialGradientBrush.GradientStops.Add(
new GradientStop(Colors.Blue, 0.75));
myRadialGradientBrush.GradientStops.Add(
new GradientStop(Colors.LimeGreen, 1.0));

Rectangle myRectangle = new Rectangle();


myRectangle.Width = 200;
myRectangle.Height = 100;
myRectangle.Fill = myRadialGradientBrush;

En la ilustración siguiente se muestra el degradado que se creó en el ejemplo anterior. Se resaltan los
delimitadores de degradado del pincel. Tenga en cuenta que, a pesar de que los resultados son distintos, los
delimitadores de degradado de este ejemplo son idénticos a los de los ejemplos de pincel de degradado
lineal anteriores.

GradientOrigin Especifica el punto inicial del eje de degradado de un pincel de degradado radial. El eje de
degradado irradia desde el origen del degradado al círculo del degradado. El círculo de degradado de un
pincel se Centerdefine RadiusXmediante sus RadiusY propiedades, y.
En la ilustración siguiente se muestran varios degradados radiales Centercon RadiusXvalores diferentes
RadiusY GradientOrigin,, y.

RadialGradientBrushes con distintos valores de


GradientOrigin, Center, RadiusX y RADIUS.
Especificación de delimitadores de degradado transparentes o
parcialmente transparentes
Dado que los delimitadores de degradado no proporcionan una propiedad Opacity, debe especificar el canal
alfa de los colores mediante la notación hexadecimal Color.FromScRgb ARGB en el marcado o utilizar el
método para crear delimitadores de degradado que son transparentes o parcialmente transparentes. En las
secciones siguientes se explica cómo crear delimitadores de degradado parcialmente transparentes en
XAML y en el código.
Especificación de la opacidad del color en "XAML"
En XAML, se usa la notación hexadecimal ARGB para especificar la opacidad de los colores individuales. La
notación hexadecimal ARGB utiliza la sintaxis siguiente:
# aa rrggbb
El valor aa de la línea anterior representa un valor hexadecimal de dos dígitos que se usa para especificar la
opacidad del color. Cada uno de los valores rr, gg y bb representa un valor hexadecimal de dos dígitos que se
usa para especificar la cantidad de rojo, verde y azul en el color. Cada dígito hexadecimal debe tener un valor
entre 0 t 9 y entre A y F. 0 es el valor menor y F, el mayor. Un valor alfa de 00 especifica un color
completamente transparente, mientras que un valor alfa de FF crea un color completamente opaco. En el
ejemplo siguiente, la notación ARGB hexadecimal se usa para especificar dos colores. El primero es
parcialmente transparente (tiene un valor alfa de x20), mientras que el segundo es completamente opaco.

<Rectangle Width="100" Height="100">


<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0">

<!-- This gradient stop is partially transparent. -->


<GradientStop Color="#200000FF" Offset="0.0" />

<!-- This gradient stop is fully opaque. -->


<GradientStop Color="#FF0000FF" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

Especificación de la opacidad del color en el código


Cuando se usa código, el FromArgb método estático permite especificar un valor alfa al crear un color. El
método toma cuatro parámetros de tipo Byte. El primer parámetro especifica el canal alfa del color, mientras
que los otros tres especifican los valores rojo, verde y azul del color. Cada valor debe estar comprendido
entre 0 y 255, ambos inclusive. Un valor alfa de 0 especifica que el color es completamente transparente,
mientras que un valor alfa de 255 especifica que el color es completamente opaco. En el ejemplo siguiente, el
FromArgb método se utiliza para generar dos colores. El primer color es parcialmente transparente (tiene un
valor alfa de 32), mientras que el segundo es completamente opaco.
LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush();

// This gradient stop is partially transparent.


myLinearGradientBrush.GradientStops.Add(
new GradientStop(Color.FromArgb(32, 0, 0, 255), 0.0));

// This gradient stop is fully opaque.


myLinearGradientBrush.GradientStops.Add(
new GradientStop(Color.FromArgb(255, 0, 0, 255), 1.0));

Rectangle myRectangle = new Rectangle();


myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = myLinearGradientBrush;

Como alternativa, puede utilizar el FromScRgb método, que le permite usar valores ScRGB para crear un
color.

Pintar con imágenes, dibujos, elementos visuales y patrones


ImageBrushlas DrawingBrushclases, VisualBrush y permiten pintar un área con imágenes, dibujos u objetos
visuales. Para información sobre cómo pintar con imágenes, dibujos y patrones, consulte el artículo Pintar
con imágenes, dibujos y elementos visuales.

Vea también
Brush
SolidColorBrush
LinearGradientBrush
RadialGradientBrush
Pintar con imágenes, dibujos y elementos visuales
Información general sobre la transformación de pinceles
Niveles de representación de gráficos
Pintar con imágenes, dibujos y elementos
visuales
23/10/2019 • 20 minutes to read • Edit Online

En este tema se describe cómo ImageBrushutilizar DrawingBrushlos objetos VisualBrush , y para pintar
un área con una imagen, Drawingun o un Visual.

Requisitos previos
Para entender este tema, debe estar familiarizado con los distintos tipos de pinceles que Windows
Presentation Foundation (WPF ) proporciona y sus características básicas. Para una introducción, consulte
Información general sobre pinceles de WPF.

Pintar un área con una imagen


Dibuja un área con un ImageSource. ImageBrush El tipo más común de ImageSource que ImageBrush se
utiliza con es un BitmapImage, que describe un gráfico de mapa de bits. Puede usar DrawingImage para
pintar con un Drawing objeto, pero es DrawingBrush más sencillo utilizar en su lugar. Para obtener más
información ImageSource acerca de los objetos, consulte la información general sobre imágenes.
Para pintar con ImageBrush, cree un BitmapImage y úselo para cargar el contenido del mapa de bits. A
continuación, utilice BitmapImage para establecer la ImageSource propiedad de ImageBrush. Por último,
aplique ImageBrush al objeto que desea pintar. En Lenguaje XAML (Extensible Application Markup
Language), también puede establecer la ImageSource propiedad de ImageBrush con la ruta de acceso de
la imagen que se va a cargar.
Al igual Brush que todos los ImageBrush objetos, se puede usar para pintar objetos como formas, paneles,
controles y texto. En la ilustración siguiente se muestran algunos efectos que se pueden lograr
ImageBrushcon un.

Objetos pintados mediante ImageBrush


De forma predeterminada, ImageBrush un ajusta su imagen para rellenar completamente el área que se
está pintando, lo que posiblemente distorsiona la imagen si el área pintada tiene una relación de aspecto
diferente a la imagen. Puede cambiar este comportamiento Stretch cambiando la propiedad de su valor
predeterminado de Fill a None, Uniformo UniformToFill. Dado ImageBrush que es un tipo TileBrushde,
puede especificar exactamente cómo un pincel de imagen rellena el área de salida e incluso crear patrones.
Para obtener más información acerca TileBrush de las características avanzadas, consulte información
general de TileBrush.
Ejemplo: Pintar un objeto con una imagen de mapa de bits
ImageBrush En el ejemplo siguiente se utiliza para pintar Background el de Canvasun.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.BrushExamples.ImageBrushExample"
WindowTitle="ImageBrush Example"
Background="White">

<StackPanel>

<Canvas
Height="200" Width="300">
<Canvas.Background>
<ImageBrush ImageSource="sampleImages\Waterlilies.jpg" />
</Canvas.Background>
</Canvas>

</StackPanel>
</Page>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Microsoft.Samples.BrushExamples
{

public class ImageBrushExample : Page


{

public ImageBrushExample()
{

StackPanel mainPanel = new StackPanel();


canvasBackgroundExample(mainPanel);
this.Content = mainPanel;
}

private void canvasBackgroundExample(Panel mainPanel)


{

BitmapImage theImage = new BitmapImage


(new Uri("sampleImages\\Waterlilies.jpg", UriKind.Relative));

ImageBrush myImageBrush = new ImageBrush(theImage);

Canvas myCanvas = new Canvas();


myCanvas.Width = 300;
myCanvas.Height = 200;
myCanvas.Background = myImageBrush;

mainPanel.Children.Add(myCanvas);
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Imaging

Namespace Microsoft.Samples.BrushExamples

Public Class ImageBrushExample


Inherits Page

Public Sub New()

Dim mainPanel As New StackPanel()


canvasBackgroundExample(mainPanel)
Me.Content = mainPanel

End Sub

Private Sub canvasBackgroundExample(ByVal mainPanel As Panel)

Dim theImage As New BitmapImage(New Uri("sampleImages\Waterlilies.jpg", UriKind.Relative))

Dim myImageBrush As New ImageBrush(theImage)

Dim myCanvas As New Canvas()


myCanvas.Width = 300
myCanvas.Height = 200
myCanvas.Background = myImageBrush

mainPanel.Children.Add(myCanvas)

End Sub

End Class

End Namespace

Pintar un área con un dibujo


DrawingBrush Permite pintar un área con formas, texto, imágenes y vídeo. Las formas que se encuentran
dentro de un pincel de dibujo pueden dibujarse a sí mismas con un color sólido DrawingBrush, un
degradado, una imagen o incluso otro. En la ilustración siguiente se muestran algunos usos
DrawingBrushde un.

Objetos pintados mediante DrawingBrush


Dibuja un área con un Drawing objeto. DrawingBrush Un Drawing objeto describe el contenido visible,
como una forma, un mapa de bits, un vídeo o una línea de texto. Distintos tipos de dibujo describen tipos
de contenido diferentes. La siguiente lista muestra los distintos tipos de objetos de dibujo.
GeometryDrawing: Dibuja una forma.
ImageDrawing: Dibuja una imagen.
GlyphRunDrawing: Dibuja texto.
VideoDrawing: Reproduce un archivo de audio o de vídeo.
DrawingGroup: Dibuja otros dibujos. Use un grupo de dibujo para combinar otros dibujos en un
solo dibujo compuesto.
Para obtener más información Drawing sobre los objetos, vea información general sobre objetos Drawing.
Al igual que Drawing DrawingBrush ImageBrush, un amplía su para rellenar su área de salida. Puede
invalidar este comportamiento cambiando la Stretch propiedad de su configuración predeterminada de.
Fill Para obtener más información, vea la propiedad Stretch.

Ejemplo: Pintar un objeto con un dibujo


En el ejemplo siguiente se muestra cómo pintar un objeto con un dibujo de tres elipses. GeometryDrawing
Se usa para describir los puntos suspensivos.

<Button Content="A Button">


<Button.Background>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="LightBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="12.5" RadiusY="25" Center="25,50" />
<EllipseGeometry RadiusX="12.5" RadiusY="25" Center="50,50" />
<EllipseGeometry RadiusX="12.5" RadiusY="25" Center="75,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="Gray" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Button.Background>
</Button>
// Create a DrawingBrush.
DrawingBrush myDrawingBrush = new DrawingBrush();

// Create a drawing.
GeometryDrawing myGeometryDrawing = new GeometryDrawing();
myGeometryDrawing.Brush = Brushes.LightBlue;
myGeometryDrawing.Pen = new Pen(Brushes.Gray, 1);
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(new EllipseGeometry(new Point(25,50), 12.5, 25));
ellipses.Children.Add(new EllipseGeometry(new Point(50,50), 12.5, 25));
ellipses.Children.Add(new EllipseGeometry(new Point(75,50), 12.5, 25));

myGeometryDrawing.Geometry = ellipses;
myDrawingBrush.Drawing = myGeometryDrawing;

Button myButton = new Button();


myButton.Content = "A Button";

// Use the DrawingBrush to paint the button's background.


myButton.Background = myDrawingBrush;

' Create a DrawingBrush.


Dim myDrawingBrush As New DrawingBrush()

' Create a drawing.


Dim myGeometryDrawing As New GeometryDrawing()
myGeometryDrawing.Brush = Brushes.LightBlue
myGeometryDrawing.Pen = New Pen(Brushes.Gray, 1)
Dim ellipses As New GeometryGroup()
ellipses.Children.Add(New EllipseGeometry(New Point(25,50), 12.5, 25))
ellipses.Children.Add(New EllipseGeometry(New Point(50,50), 12.5, 25))
ellipses.Children.Add(New EllipseGeometry(New Point(75,50), 12.5, 25))

myGeometryDrawing.Geometry = ellipses
myDrawingBrush.Drawing = myGeometryDrawing

Dim myButton As New Button()


myButton.Content = "A Button"

' Use the DrawingBrush to paint the button's background.


myButton.Background = myDrawingBrush

Pintar un área con un objeto visual


La más versátil y eficaz de todos los pinceles, VisualBrush pinta un área con un Visual. Un Visual es un
tipo gráfico de bajo nivel que actúa como antecesor de muchos componentes gráficos útiles. Por ejemplo,
las Windowclases FrameworkElement, y Control son todos los tipos de Visual objetos. Con, puede pintar
áreas con casi cualquier Windows Presentation Foundation (WPF ) objeto gráfico. VisualBrush

NOTE
Aunque VisualBrush es un tipo de Freezable objeto, no se puede inmovilizar (hacer de solo lectura) Visual cuando su
propiedad se establece en un valor null distinto de.

Hay dos maneras de especificar el Visual contenido de un. VisualBrush


Cree un nuevo Visual y úselo para establecer la Visual propiedad de VisualBrush. Para obtener un
ejemplo, vea el ejemplo: Pinte un objeto con una sección visual que se muestra a continuación.
Use un existente Visual, que crea una imagen duplicada del destino Visual. Después, puede usar
VisualBrush para crear efectos interesantes, como la reflexión y la ampliación. Para obtener un
ejemplo, vea el ejemplo: Cree una sección de reflexión.
Al definir un nuevo Visual para un VisualBrush y que Visual es un UIElement (como un UIElement panel o
control), el sistema de diseño se ejecuta en y sus elementos secundarios cuando la AutoLayoutContent
propiedad está establecida en true . Sin embargo, la UIElement raíz está esencialmente aislada del resto
del sistema: los estilos y el diseño externo no pueden contratar este límite. Por lo tanto, debe especificar
explícitamente el tamaño de UIElementla raíz, porque su único elemento VisualBrush primario es y, por lo
tanto, no puede ajustarse automáticamente al área que se está pintando. Para más información sobre el
diseño en Windows Presentation Foundation (WPF ), consulte Diseño.
Al ImageBrush igual DrawingBrushque y VisualBrush , un ajusta su contenido para rellenar su área de
salida. Puede invalidar este comportamiento cambiando la Stretch propiedad de su configuración
predeterminada de. Fill Para obtener más información, vea la propiedad Stretch.

Ejemplo: Pintar un objeto con un objeto visual


En el ejemplo siguiente, se usan varios controles y un panel para pintar un rectángulo.

<Rectangle Width="150" Height="150" Stroke="Black" Margin="5,0,5,0">


<Rectangle.Fill>
<VisualBrush>
<VisualBrush.Visual>
<StackPanel Background="White">
<Rectangle Width="25" Height="25" Fill="Red" Margin="2" />
<TextBlock FontSize="10pt" Margin="2">Hello, World!</TextBlock>
<Button Margin="2">A Button</Button>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
VisualBrush myVisualBrush = new VisualBrush();

// Create the visual brush's contents.


StackPanel myStackPanel = new StackPanel();
myStackPanel.Background = Brushes.White;

Rectangle redRectangle = new Rectangle();


redRectangle.Width = 25;
redRectangle.Height =25;
redRectangle.Fill = Brushes.Red;
redRectangle.Margin = new Thickness(2);
myStackPanel.Children.Add(redRectangle);

TextBlock someText = new TextBlock();


FontSizeConverter myFontSizeConverter = new FontSizeConverter();
someText.FontSize = (double)myFontSizeConverter.ConvertFrom("10pt");
someText.Text = "Hello, World!";
someText.Margin = new Thickness(2);
myStackPanel.Children.Add(someText);

Button aButton = new Button();


aButton.Content = "A Button";
aButton.Margin = new Thickness(2);
myStackPanel.Children.Add(aButton);

// Use myStackPanel as myVisualBrush's content.


myVisualBrush.Visual = myStackPanel;

// Create a rectangle to paint.


Rectangle myRectangle = new Rectangle();
myRectangle.Width = 150;
myRectangle.Height = 150;
myRectangle.Stroke = Brushes.Black;
myRectangle.Margin = new Thickness(5,0,5,0);

// Use myVisualBrush to paint myRectangle.


myRectangle.Fill = myVisualBrush;
Dim myVisualBrush As New VisualBrush()

' Create the visual brush's contents.


Dim myStackPanel As New StackPanel()
myStackPanel.Background = Brushes.White

Dim redRectangle As New Rectangle()


With redRectangle
.Width = 25
.Height = 25
.Fill = Brushes.Red
.Margin = New Thickness(2)
End With
myStackPanel.Children.Add(redRectangle)

Dim someText As New TextBlock()


Dim myFontSizeConverter As New FontSizeConverter()
someText.FontSize = CDbl(myFontSizeConverter.ConvertFrom("10pt"))
someText.Text = "Hello, World!"
someText.Margin = New Thickness(2)
myStackPanel.Children.Add(someText)

Dim aButton As New Button()


aButton.Content = "A Button"
aButton.Margin = New Thickness(2)
myStackPanel.Children.Add(aButton)

' Use myStackPanel as myVisualBrush's content.


myVisualBrush.Visual = myStackPanel

' Create a rectangle to paint.


Dim myRectangle As New Rectangle()
With myRectangle
.Width = 150
.Height = 150
.Stroke = Brushes.Black
.Margin = New Thickness(5, 0, 5, 0)
End With

' Use myVisualBrush to paint myRectangle.


myRectangle.Fill = myVisualBrush

Ejemplo: Crear una reflexión


En el ejemplo anterior se mostró cómo crear un Visual nuevo para usarlo como fondo. También puede
usar un VisualBrush para mostrar un visual existente; esta funcionalidad le permite generar efectos
visuales interesantes, como reflejos y aumento. VisualBrush En el ejemplo siguiente se usa para crear un
reflejo de Border un que contiene varios elementos. En la ilustración siguiente se muestra el resultado que
genera el ejemplo.
Objeto Visual reflejado

using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.IO;
using System.Collections.ObjectModel;
using System.Windows.Shapes;
namespace SDKSample
{
public partial class ReflectionExample : Page
{
public ReflectionExample()
{
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());

this.Background = Brushes.Black;
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(50);

Border myReflectedBorder = new Border();


this.RegisterName("ReflectedVisual", myReflectedBorder);

// Create a gradient background for the border.


GradientStop firstStop = new GradientStop();
firstStop.Offset = 0.0;
Color firstStopColor = new Color();
firstStopColor.R = 204;
firstStopColor.G = 204;
firstStopColor.B = 255;
firstStopColor.A = 255;
firstStop.Color = firstStopColor;
GradientStop secondStop = new GradientStop();
secondStop.Offset = 1.0;
secondStop.Color = Colors.White;

GradientStopCollection myGradientStopCollection = new GradientStopCollection();


myGradientStopCollection.Add(firstStop);
myGradientStopCollection.Add(secondStop);

LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush();


myLinearGradientBrush.StartPoint = new Point(0, 0.5);
myLinearGradientBrush.EndPoint = new Point(1, 0.5);
myLinearGradientBrush.GradientStops = myGradientStopCollection;

myReflectedBorder.Background = myLinearGradientBrush;

// Add contents to the border.


StackPanel borderStackPanel = new StackPanel();
borderStackPanel.Orientation = Orientation.Horizontal;
borderStackPanel.Margin = new Thickness(10);

TextBlock myTextBlock = new TextBlock();


myTextBlock.TextWrapping = TextWrapping.Wrap;
myTextBlock.Width = 200;
myTextBlock.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." +
" Suspendisse vel ante. Donec luctus tortor sit amet est." +
" Nullam pulvinar odio et wisi." +
" Pellentesque quis magna. Sed pellentesque." +
" Nulla euismod." +
"Pellentesque habitant morbi tristique senectus et netus et malesuada
fames ac turpis egestas.";
borderStackPanel.Children.Add(myTextBlock);

StackPanel ellipseStackPanel = new StackPanel();

Ellipse ellipse1 = new Ellipse();


ellipse1.Margin = new Thickness(10);
ellipse1.Height = 50;
ellipse1.Width = 50;
ellipse1.Fill = Brushes.Black;
ellipseStackPanel.Children.Add(ellipse1);
Ellipse ellipse2 = new Ellipse();
ellipse2.Margin = new Thickness(10);
ellipse2.Height = 50;
ellipse2.Width = 50;
ellipse2.Fill = Brushes.Black;
ellipseStackPanel.Children.Add(ellipse2);
Ellipse ellipse3 = new Ellipse();
ellipse3.Margin = new Thickness(10);
ellipse3.Height = 50;
ellipse3.Width = 50;
ellipse3.Fill = Brushes.Black;
ellipseStackPanel.Children.Add(ellipse3);
borderStackPanel.Children.Add(ellipseStackPanel);

myReflectedBorder.Child = borderStackPanel;

// Create divider rectangle


Rectangle dividerRectangle = new Rectangle();
dividerRectangle.Height = 1;
dividerRectangle.Fill = Brushes.Gray;
dividerRectangle.HorizontalAlignment = HorizontalAlignment.Stretch;

// Create the object to contain the reflection.


Rectangle reflectionRectangle = new Rectangle();

// Bind the height of the rectangle to the border height.


Binding heightBinding = new Binding();
heightBinding.ElementName = "ReflectedVisual";
heightBinding.Path = new PropertyPath(Rectangle.HeightProperty);
BindingOperations.SetBinding(reflectionRectangle, Rectangle.HeightProperty,
heightBinding);

// Bind the width of the rectangle to the border width.


Binding widthBinding = new Binding();
widthBinding.ElementName = "ReflectedVisual";
widthBinding.Path = new PropertyPath(Rectangle.WidthProperty);
BindingOperations.SetBinding(reflectionRectangle, Rectangle.WidthProperty, widthBinding);

// Creates the reflection.


VisualBrush myVisualBrush = new VisualBrush();
myVisualBrush.Opacity = 0.75;
myVisualBrush.Stretch = Stretch.None;
Binding reflectionBinding = new Binding();
reflectionBinding.ElementName = "ReflectedVisual";
BindingOperations.SetBinding(myVisualBrush, VisualBrush.VisualProperty,
reflectionBinding);

ScaleTransform myScaleTransform = new ScaleTransform();


myScaleTransform.ScaleX = 1;
myScaleTransform.ScaleY = -1;
TranslateTransform myTranslateTransform = new TranslateTransform();
myTranslateTransform.Y = 1;

TransformGroup myTransformGroup = new TransformGroup();


myTransformGroup.Children.Add(myScaleTransform);
myTransformGroup.Children.Add(myTranslateTransform);

myVisualBrush.RelativeTransform = myTransformGroup;
reflectionRectangle.Fill = myVisualBrush;

// Create a gradient background for the border.


GradientStop firstStop2 = new GradientStop();
firstStop2.Offset = 0.0;
Color c1 = new Color();
c1.R = 0;
c1.G = 0;
c1.B = 0;
c1.A = 255;
firstStop2.Color = c1;
GradientStop secondStop2 = new GradientStop();
secondStop2.Offset = 0.5;
Color c2 = new Color();
c2.R = 0;
c2.G = 0;
c2.B = 0;
c2.A = 51;
firstStop2.Color = c2;
GradientStop thirdStop = new GradientStop();
thirdStop.Offset = 0.75;
Color c3 = new Color();
c3.R = 0;
c3.G = 0;
c3.B = 0;
c3.A = 0;
thirdStop.Color = c3;

GradientStopCollection myGradientStopCollection2 = new GradientStopCollection();


myGradientStopCollection2.Add(firstStop2);
myGradientStopCollection2.Add(secondStop2);
myGradientStopCollection2.Add(thirdStop);

LinearGradientBrush myLinearGradientBrush2 = new LinearGradientBrush();


myLinearGradientBrush2.StartPoint = new Point(0.5, 0);
myLinearGradientBrush2.EndPoint = new Point(0.5, 1);
myLinearGradientBrush2.GradientStops = myGradientStopCollection2;

reflectionRectangle.OpacityMask = myLinearGradientBrush2;

BlurBitmapEffect myBlurBitmapEffect = new BlurBitmapEffect();


myBlurBitmapEffect.Radius = 1.5;

reflectionRectangle.BitmapEffect = myBlurBitmapEffect;

myStackPanel.Children.Add(myReflectedBorder);
myStackPanel.Children.Add(dividerRectangle);
myStackPanel.Children.Add(reflectionRectangle);
this.Content = myStackPanel;
}
/*
<Rectangle
Height="{Binding Path=ActualHeight, ElementName=ReflectedVisual}"
Width="{Binding Path=ActualWidth, ElementName=ReflectedVisual}">

<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FF000000" Offset="0.0" />
<GradientStop Color="#33000000" Offset="0.5" />
<GradientStop Color="#00000000" Offset="0.75" />
</LinearGradientBrush>
</Rectangle.OpacityMask>

<Rectangle.BitmapEffect>
<BlurBitmapEffect Radius="1.5" />
</Rectangle.BitmapEffect>

</Rectangle>
</StackPanel>
</StackPanel>
</Page>

*/
}
}

Imports System.Windows
Imports System.Windows.Data
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Effects
Imports System.Windows.Media.Imaging
Imports System.IO
Imports System.Collections.ObjectModel
Imports System.Windows.Shapes
Namespace SDKSample
Partial Public Class ReflectionExample
Inherits Page
Public Sub New()
' Create a name scope for the page.
NameScope.SetNameScope(Me, New NameScope())

Me.Background = Brushes.Black
Dim myStackPanel As New StackPanel()
myStackPanel.Margin = New Thickness(50)

Dim myReflectedBorder As New Border()


Me.RegisterName("ReflectedVisual", myReflectedBorder)

' Create a gradient background for the border.


Dim firstStop As New GradientStop()
firstStop.Offset = 0.0
Dim firstStopColor As New Color()
firstStopColor.R = 204
firstStopColor.G = 204
firstStopColor.B = 255
firstStopColor.A = 255
firstStop.Color = firstStopColor
Dim secondStop As New GradientStop()
secondStop.Offset = 1.0
secondStop.Color = Colors.White

Dim myGradientStopCollection As New GradientStopCollection()


myGradientStopCollection.Add(firstStop)
myGradientStopCollection.Add(secondStop)

Dim myLinearGradientBrush As New LinearGradientBrush()


myLinearGradientBrush.StartPoint = New Point(0, 0.5)
myLinearGradientBrush.EndPoint = New Point(1, 0.5)
myLinearGradientBrush.GradientStops = myGradientStopCollection

myReflectedBorder.Background = myLinearGradientBrush

' Add contents to the border.


Dim borderStackPanel As New StackPanel()
borderStackPanel.Orientation = Orientation.Horizontal
borderStackPanel.Margin = New Thickness(10)

Dim myTextBlock As New TextBlock()


myTextBlock.TextWrapping = TextWrapping.Wrap
myTextBlock.Width = 200
myTextBlock.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." & "
Suspendisse vel ante. Donec luctus tortor sit amet est." & " Nullam pulvinar odio et wisi." & "
Pellentesque quis magna. Sed pellentesque." & " Nulla euismod." & "Pellentesque habitant morbi
tristique senectus et netus et malesuada fames ac turpis egestas."
borderStackPanel.Children.Add(myTextBlock)

Dim ellipseStackPanel As New StackPanel()

Dim ellipse1 As New Ellipse()


ellipse1.Margin = New Thickness(10)
ellipse1.Height = 50
ellipse1.Width = 50
ellipse1.Fill = Brushes.Black
ellipseStackPanel.Children.Add(ellipse1)
Dim ellipse2 As New Ellipse()
ellipse2.Margin = New Thickness(10)
ellipse2.Height = 50
ellipse2.Width = 50
ellipse2.Fill = Brushes.Black
ellipseStackPanel.Children.Add(ellipse2)
Dim ellipse3 As New Ellipse()
ellipse3.Margin = New Thickness(10)
ellipse3.Height = 50
ellipse3.Width = 50
ellipse3.Fill = Brushes.Black
ellipseStackPanel.Children.Add(ellipse3)
borderStackPanel.Children.Add(ellipseStackPanel)

myReflectedBorder.Child = borderStackPanel

' Create divider rectangle


Dim dividerRectangle As New Rectangle()
dividerRectangle.Height = 1
dividerRectangle.Fill = Brushes.Gray
dividerRectangle.HorizontalAlignment = HorizontalAlignment.Stretch

' Create the object to contain the reflection.


Dim reflectionRectangle As New Rectangle()

' Bind the height of the rectangle to the border height.


Dim heightBinding As New Binding()
heightBinding.ElementName = "ReflectedVisual"
heightBinding.Path = New PropertyPath(Rectangle.HeightProperty)
BindingOperations.SetBinding(reflectionRectangle, Rectangle.HeightProperty, heightBinding)

' Bind the width of the rectangle to the border width.


Dim widthBinding As New Binding()
widthBinding.ElementName = "ReflectedVisual"
widthBinding.Path = New PropertyPath(Rectangle.WidthProperty)
BindingOperations.SetBinding(reflectionRectangle, Rectangle.WidthProperty, widthBinding)

' Creates the reflection.


Dim myVisualBrush As New VisualBrush()
myVisualBrush.Opacity = 0.75
myVisualBrush.Stretch = Stretch.None
Dim reflectionBinding As New Binding()
reflectionBinding.ElementName = "ReflectedVisual"
BindingOperations.SetBinding(myVisualBrush, VisualBrush.VisualProperty, reflectionBinding)

Dim myScaleTransform As New ScaleTransform()


myScaleTransform.ScaleX = 1
myScaleTransform.ScaleY = -1
Dim myTranslateTransform As New TranslateTransform()
myTranslateTransform.Y = 1

Dim myTransformGroup As New TransformGroup()


myTransformGroup.Children.Add(myScaleTransform)
myTransformGroup.Children.Add(myTranslateTransform)

myVisualBrush.RelativeTransform = myTransformGroup

reflectionRectangle.Fill = myVisualBrush
' Create a gradient background for the border.
Dim firstStop2 As New GradientStop()
firstStop2.Offset = 0.0
Dim c1 As New Color()
c1.R = 0
c1.G = 0
c1.B = 0
c1.A = 255
firstStop2.Color = c1
Dim secondStop2 As New GradientStop()
secondStop2.Offset = 0.5
Dim c2 As New Color()
c2.R = 0
c2.G = 0
c2.B = 0
c2.A = 51
firstStop2.Color = c2
Dim thirdStop As New GradientStop()
thirdStop.Offset = 0.75
Dim c3 As New Color()
c3.R = 0
c3.G = 0
c3.B = 0
c3.A = 0
thirdStop.Color = c3

Dim myGradientStopCollection2 As New GradientStopCollection()


myGradientStopCollection2.Add(firstStop2)
myGradientStopCollection2.Add(secondStop2)
myGradientStopCollection2.Add(thirdStop)

Dim myLinearGradientBrush2 As New LinearGradientBrush()


myLinearGradientBrush2.StartPoint = New Point(0.5, 0)
myLinearGradientBrush2.EndPoint = New Point(0.5, 1)
myLinearGradientBrush2.GradientStops = myGradientStopCollection2

reflectionRectangle.OpacityMask = myLinearGradientBrush2

Dim myBlurBitmapEffect As New BlurBitmapEffect()


myBlurBitmapEffect.Radius = 1.5

reflectionRectangle.BitmapEffect = myBlurBitmapEffect

myStackPanel.Children.Add(myReflectedBorder)
myStackPanel.Children.Add(dividerRectangle)
myStackPanel.Children.Add(reflectionRectangle)
Me.Content = myStackPanel

End Sub
End Class
End Namespace

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black">

<StackPanel Margin="50">

<!-- The object to reflect. -->


<Border Name="ReflectedVisual" Width="400">
<Border.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Offset="0.0" Color="#CCCCFF" />
<GradientStop Offset="1.0" Color="White" />
</LinearGradientBrush>
</LinearGradientBrush>
</Border.Background>
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock TextWrapping="Wrap" Width="200" Margin="10">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Suspendisse vel ante. Donec luctus tortor sit amet est.
Nullam pulvinar odio et wisi.
Pellentesque quis magna. Sed pellentesque.
Nulla euismod.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis
egestas.
</TextBlock>
<StackPanel>
<Ellipse Margin="10" Height="50" Width="50" Fill="Black" />
<Ellipse Margin="10" Height="50" Width="50" Fill="Black" />
<Ellipse Margin="10" Height="50" Width="50" Fill="Black" />
</StackPanel>
</StackPanel>
</Border>

<Rectangle Height="1" Fill="Gray" HorizontalAlignment="Stretch" />

<!-- The object to contain the reflection.-->


<Rectangle
Height="{Binding Path=ActualHeight, ElementName=ReflectedVisual}"
Width="{Binding Path=ActualWidth, ElementName=ReflectedVisual}">
<Rectangle.Fill>

<!-- Creates the reflection. -->


<VisualBrush
Opacity="0.75" Stretch="None"
Visual="{Binding ElementName=ReflectedVisual}">
<VisualBrush.RelativeTransform>

<!-- Flip the reflection. -->


<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="-1" />
<TranslateTransform Y="1" />
</TransformGroup>
</VisualBrush.RelativeTransform>
</VisualBrush>
</Rectangle.Fill>

<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FF000000" Offset="0.0" />
<GradientStop Color="#33000000" Offset="0.5" />
<GradientStop Color="#00000000" Offset="0.75" />
</LinearGradientBrush>
</Rectangle.OpacityMask>

<Rectangle.BitmapEffect>
<BlurBitmapEffect Radius="1.5" />
</Rectangle.BitmapEffect>

</Rectangle>
</StackPanel>
</Page>

Si quiere ver ejemplos adicionales que muestren cómo aumentar partes de la pantalla y cómo crear
reflejos, consulte Ejemplo de VisualBrush.

Características de TileBrush
ImageBrush, DrawingBrush TileBrush y VisualBrush son tipos de objetos. TileBrushlos objetos
proporcionan un gran control sobre cómo se pinta un área con una imagen, un dibujo o un objeto visual.
Por ejemplo, en lugar de limitarse a dibujar un área con una sola imagen ajustada, puede dibujar un área
con una serie de mosaicos de imagen que crean un patrón.
Un TileBrush tiene tres componentes principales: contenido, mosaicos y el área de salida.

Componentes de TileBrush con un solo mosaico

Componentes de TileBrush con varios mosaicos


Para obtener más información sobre las características de TileBrush mosaico de los objetos, vea
información general sobre TileBrush.

Vea también
ImageBrush
DrawingBrush
VisualBrush
TileBrush
Información general sobre objetos TileBrush
Información general sobre pinceles de WPF
Información general sobre imágenes
Información general sobre objetos Drawing
Información general sobre las máscaras de opacidad
Información general sobre la representación de gráficos en WPF
Ejemplo de ImageBrush
Ejemplo de VisualBrush
Información general sobre objetos TileBrush
23/10/2019 • 12 minutes to read • Edit Online

TileBrush los objetos que proporcionan un gran control sobre cómo se pinta un área con una imagen, Drawing, o
Visual. Este tema describe cómo usar TileBrush características para obtener más control sobre cómo un
ImageBrush, DrawingBrush, o VisualBrush pinta un área.

Requisitos previos
Para entender este tema, es útil entender cómo usar las características básicas de la ImageBrush, DrawingBrush,
o VisualBrush clase. Para obtener una introducción a estos tipos, vea la pintar con imágenes, dibujos y elementos
visuales.

Dibujo de un área con mosaicos


ImageBrush, DrawingBrush, son VisualBrush son tipos de TileBrush objetos. Los pinceles de mosaico
proporcionan un gran control sobre cómo se dibuja un área con una imagen, un dibujo o un objeto visual. Por
ejemplo, en lugar de limitarse a dibujar un área con una sola imagen ajustada, puede dibujar un área con una
serie de mosaicos de imagen que crean un patrón.
Para dibujar un área con un pincel de mosaico se necesitan tres componentes: contenido, mosaico base y área de
resultados.

Componentes de TileBrush con un solo mosaico

Componentes de TileBrush con un valor de TileMode de Tile


El área de salida es el área que se va a pintar, como el Fill de un Ellipse o Background de un Button. Las secciones
siguientes describen los dos componentes de un TileBrush.

Contenido del objeto Brush


Hay tres tipos diferentes de TileBrush y cada uno de ellos pinta con un tipo diferente del contenido.
Si el pincel es un ImageBrush, este contenido es una imagen del ImageSource propiedad especifica el
contenido de la ImageBrush.
Si el pincel es un DrawingBrush, este contenido es un dibujo. El Drawing propiedad especifica el contenido
de la DrawingBrush.
Si el pincel es un VisualBrush, este contenido es un objeto visual. El Visual propiedad especifica el
contenido de la VisualBrush.
Puede especificar la posición y las dimensiones de TileBrush contenido mediante el uso de la Viewbox propiedad,
aunque es frecuente dejar el Viewbox establecido en su valor predeterminado. De forma predeterminada, el
Viewbox se configura para contener completamente el contenido del pincel. Para obtener más información acerca
de cómo configurar el Viewbox, consulte la Viewbox página de propiedades.

Mosaico base
Un TileBrush proyecta su contenido en un mosaico base. El Stretch propiedad controla cómo TileBrush contenido
se ajusta para rellenar el mosaico base. El Stretch propiedad acepta los valores siguientes, definidos por el Stretch
enumeración:
None: El contenido del pincel no se ajusta para rellenar el mosaico.
Fill: El contenido del pincel se ajusta para rellenar el mosaico. Como el alto y el ancho del contenido se
ajustan de forma independiente, podría no conservarse la relación de aspecto original del contenido. En
otras palabras, el contenido del pincel podría distorsionarse para rellenar por completo el mosaico de
salida.
Uniform: El contenido del pincel se escala para que quepa completamente dentro del mosaico. Se
conserva la relación de aspecto del contenido.
UniformToFill: El contenido del pincel se escala para que rellene completamente el área de salida
conservando la relación de aspecto original del contenido.
La siguiente imagen ilustra los diferentes Stretch configuración.

En el ejemplo siguiente, el contenido de un ImageBrush está establecida para que no se ajusta para rellenar el
área de salida.
<Rectangle
Width="125" Height="175"
Stroke="Black"
StrokeThickness="1"
Margin="0,0,5,0">
<Rectangle.Fill>
<ImageBrush
Stretch="None"
ImageSource="sampleImages\testImage.gif"/>
</Rectangle.Fill>
</Rectangle>

// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 125;
myRectangle.Height = 175;
myRectangle.Stroke = Brushes.Black;
myRectangle.StrokeThickness = 1;
myRectangle.Margin = new Thickness(0,5,0,0);

// Load the image.


BitmapImage theImage =
new BitmapImage(
new Uri("sampleImages\\testImage.gif", UriKind.Relative));
ImageBrush myImageBrush = new ImageBrush(theImage);

// Configure the brush so that it


// doesn't stretch its image to fill
// the rectangle.
myImageBrush.Stretch = Stretch.None;

// Use the ImageBrush to paint the rectangle's background.


myRectangle.Fill = myImageBrush;

' Create a rectangle.


Dim myRectangle As New Rectangle()
With myRectangle
.Width = 125
.Height = 175
.Stroke = Brushes.Black
.StrokeThickness = 1
.Margin = New Thickness(0, 5, 0, 0)
End With

' Load the image.


Dim theImage As New BitmapImage(New Uri("sampleImages\testImage.gif", UriKind.Relative))
Dim myImageBrush As New ImageBrush(theImage)

' Configure the brush so that it


' doesn't stretch its image to fill
' the rectangle.
myImageBrush.Stretch = Stretch.None

' Use the ImageBrush to paint the rectangle's background.


myRectangle.Fill = myImageBrush

De forma predeterminada, un TileBrush genera un único mosaico (el mosaico base) y ajusta ese mosaico hasta
rellenar completamente el área de salida. Puede cambiar el tamaño y la posición del mosaico base estableciendo
la Viewport y ViewportUnits propiedades.
Tamaño del mosaico base
El Viewport propiedad determina el tamaño y la posición del mosaico base y el ViewportUnits propiedad
determina si el Viewport se especifica mediante coordenadas absolutas o relativas. Si las coordenadas son
relativas, lo son con respecto al tamaño del área de salida. El punto (0,0) representa la parte superior izquierda
esquina del área de salida y (1,1) representa la parte inferior derecha del área de salida. Para especificar que el
Viewport propiedad usa coordenadas absolutas, establezca el ViewportUnits propiedad Absolute.
La siguiente ilustración muestra la diferencia entre un TileBrush con el valor relativo frente a absoluto
ViewportUnits. Observe que las ilustraciones muestran un patrón de mosaicos; en la siguiente sección se
describe cómo especificar el patrón de mosaicos.

En el ejemplo siguiente, se utiliza una imagen para crear un mosaico con un ancho y alto del 50%. El mosaico
base se encuentra en la posición (0,0) del área de salida.

<Rectangle
Width="50" Height="100">
<Rectangle.Fill>

<!-- Paints an area with 4 tiles. -->


<ImageBrush ImageSource="sampleImages\cherries_larger.jpg"
Viewport="0,0,0.5,0.5"
ViewportUnits="RelativeToBoundingBox"
TileMode="Tile" />
</Rectangle.Fill>
</Rectangle>
// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 50;
myRectangle.Height = 100;

// Load the image.


BitmapImage theImage =
new BitmapImage(
new Uri("sampleImages\\cherries_larger.jpg", UriKind.Relative));
ImageBrush myImageBrush = new ImageBrush(theImage);

// Create tiles that are 1/4 the size of


// the output area.
myImageBrush.Viewport = new Rect(0,0,0.25,0.25);
myImageBrush.ViewportUnits = BrushMappingMode.RelativeToBoundingBox;

// Set the tile mode to Tile.


myImageBrush.TileMode = TileMode.Tile;

// Use the ImageBrush to paint the rectangle's background.


myRectangle.Fill = myImageBrush;

' Create a rectangle.


Dim myRectangle As New Rectangle()
myRectangle.Width = 50
myRectangle.Height = 100

' Load the image.


Dim theImage As New BitmapImage(New Uri("sampleImages\cherries_larger.jpg", UriKind.Relative))
Dim myImageBrush As New ImageBrush(theImage)

' Create tiles that are 1/4 the size of


' the output area.
myImageBrush.Viewport = New Rect(0, 0, 0.25, 0.25)
myImageBrush.ViewportUnits = BrushMappingMode.RelativeToBoundingBox

' Set the tile mode to Tile.


myImageBrush.TileMode = TileMode.Tile

' Use the ImageBrush to paint the rectangle's background.


myRectangle.Fill = myImageBrush

El ejemplo siguiente establece los iconos de un ImageBrush a 25 por 25 píxeles independientes del dispositivo.
Dado que el ViewportUnits son absolutos, el ImageBrush los iconos son siempre de 25 por 25 píxeles,
independientemente del tamaño del área que se está pintando.

<Rectangle
Width="50" Height="100">
<Rectangle.Fill>

<!-- Paints an area with 25 x 25 tiles. -->


<ImageBrush ImageSource="sampleImages\cherries_larger.jpg"
Viewport="0,0,25,25"
ViewportUnits="Absolute"
TileMode="Tile" />
</Rectangle.Fill>
</Rectangle>
// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 50;
myRectangle.Height = 100;

// Load the image.


BitmapImage theImage =
new BitmapImage(
new Uri("sampleImages\\cherries_larger.jpg", UriKind.Relative));
ImageBrush myImageBrush = new ImageBrush(theImage);

// Create tiles that are 25 x 25, regardless of the size


// of the output area.
myImageBrush.Viewport = new Rect(0, 0, 25, 25);
myImageBrush.ViewportUnits = BrushMappingMode.Absolute;

// Set the tile mode to Tile.


myImageBrush.TileMode = TileMode.Tile;

// Use the ImageBrush to paint the rectangle's background.


myRectangle.Fill = myImageBrush;

' Create a rectangle.


Dim myRectangle As New Rectangle()
myRectangle.Width = 50
myRectangle.Height = 100

' Load the image.


Dim theImage As New BitmapImage(New Uri("sampleImages\cherries_larger.jpg", UriKind.Relative))
Dim myImageBrush As New ImageBrush(theImage)

' Create tiles that are 25 x 25, regardless of the size


' of the output area.
myImageBrush.Viewport = New Rect(0, 0, 25, 25)
myImageBrush.ViewportUnits = BrushMappingMode.Absolute

' Set the tile mode to Tile.


myImageBrush.TileMode = TileMode.Tile

' Use the ImageBrush to paint the rectangle's background.


myRectangle.Fill = myImageBrush

Comportamiento de la colocación en mosaico


Un TileBrush genera un patrón de mosaicos cuando su mosaico base no rellena completamente el área de salida
y un modo de disposición en mosaico distinto None se especifica. Cuando mosaico un icono de pincel de no
rellena completamente el área de salida, su TileMode propiedad especifica si el mosaico base se debe duplicar
para rellenar el área de salida y, si es así, ¿cómo la base se debe duplicar. El TileMode propiedad acepta los
valores siguientes, definidos por el TileMode enumeración:
None: Se dibuja el mosaico base.
Tile: Se dibuja el mosaico base y el área restante se rellena repitiendo el mosaico base, que es adyacente al
borde izquierdo del siguiente y el borde derecho de un mosaico de forma similar para los bordes superior
e inferior.
FlipX: Igual que Tile, pero las columnas alternativas de los mosaicos se voltean horizontalmente.
FlipY: Igual que Tile, pero las filas alternas de los mosaicos se voltean verticalmente.
FlipXY: Combinación de FlipX y FlipY.
La siguiente imagen ilustra los diferentes modos de colocación en mosaico.
En el ejemplo siguiente, se utiliza una imagen para dibujar un rectángulo de 100 píxeles de ancho por 100 píxeles
de alto. Al establecer el pincel Viewport se ha establecido en 0,0,0.25,0.25, mosaico base el pincel de se realiza
para ser de 1/4 del área de salida. El pincel TileMode está establecido en FlipXY. para que rellene el rectángulo
con filas de mosaicos.

<Rectangle
Width="100" Height="100" >
<Rectangle.Fill>
<ImageBrush ImageSource="sampleImages\triangle.jpg"
Viewport="0,0,0.25,0.25"
TileMode="FlipXY"
/>
</Rectangle.Fill>
</Rectangle>

// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 100;
myRectangle.Height = 100;

// Load the image.


BitmapImage theImage =
new BitmapImage(
new Uri("sampleImages\\triangle.jpg", UriKind.Relative));
ImageBrush myImageBrush = new ImageBrush(theImage);

// Create tiles that are 1/4 the size of


// the output area.
myImageBrush.Viewport = new Rect(0,0,0.25,0.25);

// Set the tile mode to FlipXY.


myImageBrush.TileMode = TileMode.FlipXY;

// Use the ImageBrush to paint the rectangle's background.


myRectangle.Fill = myImageBrush;

' Create a rectangle.


Dim myRectangle As New Rectangle()
myRectangle.Width = 100
myRectangle.Height = 100

' Load the image.


Dim theImage As New BitmapImage(New Uri("sampleImages\triangle.jpg", UriKind.Relative))
Dim myImageBrush As New ImageBrush(theImage)

' Create tiles that are 1/4 the size of


' the output area.
myImageBrush.Viewport = New Rect(0, 0, 0.25, 0.25)

' Set the tile mode to FlipXY.


myImageBrush.TileMode = TileMode.FlipXY

' Use the ImageBrush to paint the rectangle's background.


myRectangle.Fill = myImageBrush
Vea también
ImageBrush
DrawingBrush
VisualBrush
TileBrush
Pintar con imágenes, dibujos y elementos visuales
Temas "Cómo..."
Información general sobre objetos Freezable
Ejemplo de ImageBrush
Ejemplo de VisualBrush
Temas "Cómo..." de pinceles
23/10/2019 • 2 minutes to read • Edit Online

Los temas siguientes muestran cómo usar Windows Presentation Foundation (WPF ) pinceles para pintar el
contenido en la pantalla.

En esta sección
Animar el color o la opacidad de un objeto SolidColorBrush
Animar la posición o color de un delimitador de degradado
Crear una reflexión
Crear patrones de mosaico diferentes con un objeto TileBrush
Definir una pluma
Pintar un área con un dibujo
Pintar un área con una imagen
Pintar un área con un degradado lineal
Pintar un área con un degradado radial
Pintar un área con un color sólido
Pintar un área con un pincel del sistema
Pintar un área con un vídeo
Pintar un área con un objeto visual
Conservar la relación de aspecto de una imagen utilizada como fondo
Establecer la alineación horizontal y vertical de TileBrush
Establecer el tamaño del mosaico de un TileBrush
Transformar un pincel
Usar colores del sistema en un degradado

Referencia
Brush
SolidColorBrush
LinearGradientBrush
RadialGradientBrush
DrawingBrush
VisualBrush

Secciones relacionadas
Gráficos y multimedia
Información general sobre la representación de gráficos en WPF
Cómo: Animar el color o la opacidad de un objeto
SolidColorBrush
20/02/2020 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo animar el Color y Opacity de una SolidColorBrush.

Ejemplo
En el ejemplo siguiente se usan tres animaciones para animar el Color y Opacity de una SolidColorBrush.
La primera animación, una ColorAnimation, cambia el color del pincel a Gray cuando el Mouse entra en el
rectángulo.
La siguiente animación, otra ColorAnimation, cambia el color del pincel a Orange cuando el mouse sale del
rectángulo.
La animación final, una DoubleAnimation, cambia la opacidad del pincel a 0,0 cuando se presiona el botón
primario del mouse.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Input;

namespace Microsoft.Samples.Animation
{
/// <summary>
/// This example shows how to animate the Opacity and Color
/// properties of a SolidColorBrush.
/// </summary>
public class SolidColorBrushExample : Page
{

public SolidColorBrushExample()
{
Title = "SolidColorBrush Animation Example";
Background = Brushes.White;

// Create a NameScope for the page so


// that Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

// Create a Rectangle.
Rectangle aRectangle = new Rectangle();
aRectangle.Width = 100;
aRectangle.Height = 100;

// Create a SolidColorBrush to paint


// the rectangle's fill. The Opacity
// and Color properties of the brush
// will be animated.
SolidColorBrush myAnimatedBrush = new SolidColorBrush();
myAnimatedBrush.Color = Colors.Orange;
aRectangle.Fill = myAnimatedBrush;

// Register the brush's name with the page


// Register the brush's name with the page
// so that it can be targeted by storyboards.
this.RegisterName("MyAnimatedBrush", myAnimatedBrush);

//
// Animate the brush's color to gray when
// the mouse enters the rectangle.
//
ColorAnimation mouseEnterColorAnimation = new ColorAnimation();
mouseEnterColorAnimation.To = Colors.Gray;
mouseEnterColorAnimation.Duration = TimeSpan.FromSeconds(1);
Storyboard.SetTargetName(mouseEnterColorAnimation, "MyAnimatedBrush");
Storyboard.SetTargetProperty(
mouseEnterColorAnimation, new PropertyPath(SolidColorBrush.ColorProperty));
Storyboard mouseEnterStoryboard = new Storyboard();
mouseEnterStoryboard.Children.Add(mouseEnterColorAnimation);
aRectangle.MouseEnter += delegate(object sender, MouseEventArgs e)
{
mouseEnterStoryboard.Begin(this);
};

//
// Animate the brush's color to orange when
// the mouse leaves the rectangle.
//
ColorAnimation mouseLeaveColorAnimation = new ColorAnimation();
mouseLeaveColorAnimation.To = Colors.Orange;
mouseLeaveColorAnimation.Duration = TimeSpan.FromSeconds(1);
Storyboard.SetTargetName(mouseLeaveColorAnimation, "MyAnimatedBrush");
Storyboard.SetTargetProperty(
mouseLeaveColorAnimation, new PropertyPath(SolidColorBrush.ColorProperty));
Storyboard mouseLeaveStoryboard = new Storyboard();
mouseLeaveStoryboard.Children.Add(mouseLeaveColorAnimation);
aRectangle.MouseLeave += delegate(object sender, MouseEventArgs e)
{
mouseLeaveStoryboard.Begin(this);
};

//
// Animate the brush's opacity to 0 and back when
// the left mouse button is pressed over the rectangle.
//
DoubleAnimation opacityAnimation = new DoubleAnimation();
opacityAnimation.To = 0.0;
opacityAnimation.Duration = TimeSpan.FromSeconds(0.5);
opacityAnimation.AutoReverse = true;
Storyboard.SetTargetName(opacityAnimation, "MyAnimatedBrush");
Storyboard.SetTargetProperty(
opacityAnimation, new PropertyPath(SolidColorBrush.OpacityProperty));
Storyboard mouseLeftButtonDownStoryboard = new Storyboard();
mouseLeftButtonDownStoryboard.Children.Add(opacityAnimation);
aRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
{
mouseLeftButtonDownStoryboard.Begin(this);
};

StackPanel mainPanel = new StackPanel();


mainPanel.Margin = new Thickness(20);
mainPanel.Children.Add(aRectangle);
Content = mainPanel;
}
}
}

Para obtener un ejemplo más completo, en el que se muestra cómo animar distintos tipos de pinceles, vea el
ejemplo de pinceles. Para obtener más información acerca de la animación, consulte información general sobre
animaciones.
Para mantener la coherencia con otros ejemplos de animación, en las versiones de código de este ejemplo se usa
un objeto Storyboard para aplicar sus animaciones. Sin embargo, al aplicar una animación única en el código, es
más fácil utilizar el método BeginAnimation en lugar de usar un Storyboard. Para obtener un ejemplo, vea Animar
una propiedad sin utilizar un guión gráfico.

Consulte también
Información general sobre animaciones
Información general sobre objetos Storyboard
Ejemplo de pinceles
Cómo: Animar la posición o color de un punto de
degradado
20/02/2020 • 6 minutes to read • Edit Online

En este ejemplo se muestra cómo animar el Color y Offset de GradientStop objetos.

Ejemplo
En el ejemplo siguiente se animan tres delimitadores de degradado dentro de un LinearGradientBrush. En el
ejemplo se usan tres animaciones, cada una de las cuales anima un delimitador de degradado diferente:
La primera animación, una DoubleAnimation, anima el primer Offset de delimitador de degradado de 0,0 a
1,0 y después vuelve a 0,0. Como resultado, el primer color del degradado se desplaza desde el lado
izquierdo hasta el lado derecho del rectángulo y, a continuación, vuelve al lado izquierdo.
La segunda animación, una ColorAnimation, anima el Color del segundo delimitador de degradado de
Purple a Yellow y, a continuación, de nuevo a Purple. Como resultado, el color intermedio del degradado
cambia de púrpura a amarillo y de nuevo a púrpura.
La tercera animación, otra ColorAnimation, anima la opacidad del tercer delimitador de degradado Color
por-1 y, a continuación, hacia atrás. Como resultado, el tercer color del degradado se atenúa y vuelve a ser
opaco.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace BrushesIntroduction
{
public class GradientStopAnimationExample : Page
{
public GradientStopAnimationExample()
{
Title = "GradientStop Animation Example";
Background = Brushes.White;

// Create a NameScope for the page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

// Create a rectangle. This rectangle will


// be painted with a gradient.
Rectangle aRectangle = new Rectangle();
aRectangle.Width = 200;
aRectangle.Height = 100;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 1;

// Create a LinearGradientBrush to paint


// the rectangle's fill.
LinearGradientBrush gradientBrush = new LinearGradientBrush();

// Create gradient stops for the brush.


GradientStop stop1 = new GradientStop(Colors.MediumBlue, 0.0);
GradientStop stop1 = new GradientStop(Colors.MediumBlue, 0.0);
GradientStop stop2 = new GradientStop(Colors.Purple, 0.5);
GradientStop stop3 = new GradientStop(Colors.Red, 1.0);

// Register a name for each gradient stop with the


// page so that they can be animated by a storyboard.
this.RegisterName("GradientStop1", stop1);
this.RegisterName("GradientStop2", stop2);
this.RegisterName("GradientStop3", stop3);

// Add the stops to the brush.


gradientBrush.GradientStops.Add(stop1);
gradientBrush.GradientStops.Add(stop2);
gradientBrush.GradientStops.Add(stop3);

// Apply the brush to the rectangle.


aRectangle.Fill = gradientBrush;

//
// Animate the first gradient stop's offset from
// 0.0 to 1.0 and then back to 0.0.
//
DoubleAnimation offsetAnimation = new DoubleAnimation();
offsetAnimation.From = 0.0;
offsetAnimation.To = 1.0;
offsetAnimation.Duration = TimeSpan.FromSeconds(1.5);
offsetAnimation.AutoReverse = true;
Storyboard.SetTargetName(offsetAnimation, "GradientStop1");
Storyboard.SetTargetProperty(offsetAnimation,
new PropertyPath(GradientStop.OffsetProperty));

//
// Animate the second gradient stop's color from
// Purple to Yellow and then back to Purple.
//
ColorAnimation gradientStopColorAnimation = new ColorAnimation();
gradientStopColorAnimation.From = Colors.Purple;
gradientStopColorAnimation.To = Colors.Yellow;
gradientStopColorAnimation.Duration = TimeSpan.FromSeconds(1.5);
gradientStopColorAnimation.AutoReverse = true;
Storyboard.SetTargetName(gradientStopColorAnimation, "GradientStop2");
Storyboard.SetTargetProperty(gradientStopColorAnimation,
new PropertyPath(GradientStop.ColorProperty));

// Set the animation to begin after the first animation


// ends.
gradientStopColorAnimation.BeginTime = TimeSpan.FromSeconds(3);

//
// Animate the third gradient stop's color so
// that it becomes transparent.
//
ColorAnimation opacityAnimation = new ColorAnimation();

// Reduces the target color's alpha value by 1,


// making the color transparent.
opacityAnimation.By = Color.FromScRgb(-1.0F, 0F, 0F, 0F);
opacityAnimation.Duration = TimeSpan.FromSeconds(1.5);
opacityAnimation.AutoReverse = true;
Storyboard.SetTargetName(opacityAnimation, "GradientStop3");
Storyboard.SetTargetProperty(opacityAnimation,
new PropertyPath(GradientStop.ColorProperty));

// Set the animation to begin after the first two


// animations have ended.
opacityAnimation.BeginTime = TimeSpan.FromSeconds(6);

// Create a Storyboard to apply the animations.


Storyboard gradientStopAnimationStoryboard = new Storyboard();
gradientStopAnimationStoryboard.Children.Add(offsetAnimation);
gradientStopAnimationStoryboard.Children.Add(offsetAnimation);
gradientStopAnimationStoryboard.Children.Add(gradientStopColorAnimation);
gradientStopAnimationStoryboard.Children.Add(opacityAnimation);

// Begin the storyboard when the left mouse button is


// pressed over the rectangle.
aRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
{
gradientStopAnimationStoryboard.Begin(this);
};

StackPanel mainPanel = new StackPanel();


mainPanel.Margin = new Thickness(10);
mainPanel.Children.Add(aRectangle);
Content = mainPanel;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes

Namespace BrushesIntroduction
Public Class GradientStopAnimationExample
Inherits Page
Public Sub New()
Title = "GradientStop Animation Example"
Background = Brushes.White

' Create a NameScope for the page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

' Create a rectangle. This rectangle will


' be painted with a gradient.
Dim aRectangle As New Rectangle()
aRectangle.Width = 200
aRectangle.Height = 100
aRectangle.Stroke = Brushes.Black
aRectangle.StrokeThickness = 1

' Create a LinearGradientBrush to paint


' the rectangle's fill.
Dim gradientBrush As New LinearGradientBrush()

' Create gradient stops for the brush.


Dim stop1 As New GradientStop(Colors.MediumBlue, 0.0)
Dim stop2 As New GradientStop(Colors.Purple, 0.5)
Dim stop3 As New GradientStop(Colors.Red, 1.0)

' Register a name for each gradient stop with the


' page so that they can be animated by a storyboard.
Me.RegisterName("GradientStop1", stop1)
Me.RegisterName("GradientStop2", stop2)
Me.RegisterName("GradientStop3", stop3)

' Add the stops to the brush.


gradientBrush.GradientStops.Add(stop1)
gradientBrush.GradientStops.Add(stop2)
gradientBrush.GradientStops.Add(stop3)

' Apply the brush to the rectangle.


aRectangle.Fill = gradientBrush
aRectangle.Fill = gradientBrush

'
' Animate the first gradient stop's offset from
' 0.0 to 1.0 and then back to 0.0.
'
Dim offsetAnimation As New DoubleAnimation()
offsetAnimation.From = 0.0
offsetAnimation.To = 1.0
offsetAnimation.Duration = TimeSpan.FromSeconds(1.5)
offsetAnimation.AutoReverse = True
Storyboard.SetTargetName(offsetAnimation, "GradientStop1")
Storyboard.SetTargetProperty(offsetAnimation, New PropertyPath(GradientStop.OffsetProperty))

'
' Animate the second gradient stop's color from
' Purple to Yellow and then back to Purple.
'
Dim gradientStopColorAnimation As New ColorAnimation()
gradientStopColorAnimation.From = Colors.Purple
gradientStopColorAnimation.To = Colors.Yellow
gradientStopColorAnimation.Duration = TimeSpan.FromSeconds(1.5)
gradientStopColorAnimation.AutoReverse = True
Storyboard.SetTargetName(gradientStopColorAnimation, "GradientStop2")
Storyboard.SetTargetProperty(gradientStopColorAnimation, New
PropertyPath(GradientStop.ColorProperty))

' Set the animation to begin after the first animation


' ends.
gradientStopColorAnimation.BeginTime = TimeSpan.FromSeconds(3)

'
' Animate the third gradient stop's color so
' that it becomes transparent.
'
Dim opacityAnimation As New ColorAnimation()

' Reduces the target color's alpha value by 1,


' making the color transparent.
opacityAnimation.By = Color.FromScRgb(-1.0F, 0F, 0F, 0F)
opacityAnimation.Duration = TimeSpan.FromSeconds(1.5)
opacityAnimation.AutoReverse = True
Storyboard.SetTargetName(opacityAnimation, "GradientStop3")
Storyboard.SetTargetProperty(opacityAnimation, New PropertyPath(GradientStop.ColorProperty))

' Set the animation to begin after the first two


' animations have ended.
opacityAnimation.BeginTime = TimeSpan.FromSeconds(6)

' Create a Storyboard to apply the animations.


Dim gradientStopAnimationStoryboard As New Storyboard()
gradientStopAnimationStoryboard.Children.Add(offsetAnimation)
gradientStopAnimationStoryboard.Children.Add(gradientStopColorAnimation)
gradientStopAnimationStoryboard.Children.Add(opacityAnimation)

' Begin the storyboard when the left mouse button is


' pressed over the rectangle.
AddHandler aRectangle.MouseLeftButtonDown, Sub(sender As Object, e As MouseButtonEventArgs)
gradientStopAnimationStoryboard.Begin(Me)

Dim mainPanel As New StackPanel()


mainPanel.Margin = New Thickness(10)
mainPanel.Children.Add(aRectangle)
Content = mainPanel
End Sub
End Class
End Namespace
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="GradientStop Animation Example"
Background="White">
<StackPanel Margin="10">

<Rectangle
Width="200"
Height="100"
Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop x:Name="GradientStop1" Color="MediumBlue" Offset="0.0" />
<GradientStop x:Name="GradientStop2" Color="Purple" Offset="0.5" />
<GradientStop x:Name="GradientStop3" Color="Red" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="GradientStop1"
Storyboard.TargetProperty="Offset"
From="0.0" To="1.0" Duration="0:0:1.5"
AutoReverse="True" />
<ColorAnimation
Storyboard.TargetName="GradientStop2"
Storyboard.TargetProperty="Color"
From="Purple" To="Yellow"
Duration="0:0:1.5"
AutoReverse="True"
BeginTime="0:0:3" />
<ColorAnimation
Storyboard.TargetName="GradientStop3"
Storyboard.TargetProperty="Color"
Duration="0:0:1.5"
AutoReverse="True"
BeginTime="0:0:6">
<ColorAnimation.By>
<Color ScA="-1" ScR="0" ScB="0" ScG="0" />
</ColorAnimation.By>
</ColorAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

</StackPanel>
</Page>

Aunque en este ejemplo se usa un LinearGradientBrush, el proceso es el mismo para animar objetos GradientStop
dentro de un RadialGradientBrush.
Para obtener más ejemplos, vea el ejemplo brushes.

Consulte también
GradientStop
Información general sobre animaciones
Información general sobre objetos Storyboard
Cómo: Crear una reflexión
20/02/2020 • 7 minutes to read • Edit Online

En este ejemplo se muestra cómo utilizar una VisualBrush para crear una reflexión. Dado que un VisualBrush
puede mostrar un visual existente, puede usar esta capacidad para generar efectos visuales interesantes, como
reflejos y ampliación.

Ejemplo
En el ejemplo siguiente se usa una VisualBrush para crear un reflejo de una Border que contiene varios elementos.
En la ilustración siguiente se muestra el resultado que genera el ejemplo.

Objeto Visual reflejado

using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.IO;
using System.Collections.ObjectModel;
using System.Windows.Shapes;
namespace SDKSample
{
public partial class ReflectionExample : Page
{
public ReflectionExample()
{
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());

this.Background = Brushes.Black;
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(50);

Border myReflectedBorder = new Border();


this.RegisterName("ReflectedVisual", myReflectedBorder);

// Create a gradient background for the border.


GradientStop firstStop = new GradientStop();
firstStop.Offset = 0.0;
Color firstStopColor = new Color();
firstStopColor.R = 204;
firstStopColor.G = 204;
firstStopColor.B = 255;
firstStopColor.A = 255;
firstStopColor.A = 255;
firstStop.Color = firstStopColor;
GradientStop secondStop = new GradientStop();
secondStop.Offset = 1.0;
secondStop.Color = Colors.White;

GradientStopCollection myGradientStopCollection = new GradientStopCollection();


myGradientStopCollection.Add(firstStop);
myGradientStopCollection.Add(secondStop);

LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush();


myLinearGradientBrush.StartPoint = new Point(0, 0.5);
myLinearGradientBrush.EndPoint = new Point(1, 0.5);
myLinearGradientBrush.GradientStops = myGradientStopCollection;

myReflectedBorder.Background = myLinearGradientBrush;

// Add contents to the border.


StackPanel borderStackPanel = new StackPanel();
borderStackPanel.Orientation = Orientation.Horizontal;
borderStackPanel.Margin = new Thickness(10);

TextBlock myTextBlock = new TextBlock();


myTextBlock.TextWrapping = TextWrapping.Wrap;
myTextBlock.Width = 200;
myTextBlock.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." +
" Suspendisse vel ante. Donec luctus tortor sit amet est." +
" Nullam pulvinar odio et wisi." +
" Pellentesque quis magna. Sed pellentesque." +
" Nulla euismod." +
"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac
turpis egestas.";

borderStackPanel.Children.Add(myTextBlock);

StackPanel ellipseStackPanel = new StackPanel();

Ellipse ellipse1 = new Ellipse();


ellipse1.Margin = new Thickness(10);
ellipse1.Height = 50;
ellipse1.Width = 50;
ellipse1.Fill = Brushes.Black;
ellipseStackPanel.Children.Add(ellipse1);
Ellipse ellipse2 = new Ellipse();
ellipse2.Margin = new Thickness(10);
ellipse2.Height = 50;
ellipse2.Width = 50;
ellipse2.Fill = Brushes.Black;
ellipseStackPanel.Children.Add(ellipse2);
Ellipse ellipse3 = new Ellipse();
ellipse3.Margin = new Thickness(10);
ellipse3.Height = 50;
ellipse3.Width = 50;
ellipse3.Fill = Brushes.Black;
ellipseStackPanel.Children.Add(ellipse3);
borderStackPanel.Children.Add(ellipseStackPanel);

myReflectedBorder.Child = borderStackPanel;

// Create divider rectangle


Rectangle dividerRectangle = new Rectangle();
dividerRectangle.Height = 1;
dividerRectangle.Fill = Brushes.Gray;
dividerRectangle.HorizontalAlignment = HorizontalAlignment.Stretch;

// Create the object to contain the reflection.


Rectangle reflectionRectangle = new Rectangle();

// Bind the height of the rectangle to the border height.


Binding heightBinding = new Binding();
Binding heightBinding = new Binding();
heightBinding.ElementName = "ReflectedVisual";
heightBinding.Path = new PropertyPath(Rectangle.HeightProperty);
BindingOperations.SetBinding(reflectionRectangle, Rectangle.HeightProperty, heightBinding);

// Bind the width of the rectangle to the border width.


Binding widthBinding = new Binding();
widthBinding.ElementName = "ReflectedVisual";
widthBinding.Path = new PropertyPath(Rectangle.WidthProperty);
BindingOperations.SetBinding(reflectionRectangle, Rectangle.WidthProperty, widthBinding);

// Creates the reflection.


VisualBrush myVisualBrush = new VisualBrush();
myVisualBrush.Opacity = 0.75;
myVisualBrush.Stretch = Stretch.None;
Binding reflectionBinding = new Binding();
reflectionBinding.ElementName = "ReflectedVisual";
BindingOperations.SetBinding(myVisualBrush, VisualBrush.VisualProperty, reflectionBinding);

ScaleTransform myScaleTransform = new ScaleTransform();


myScaleTransform.ScaleX = 1;
myScaleTransform.ScaleY = -1;
TranslateTransform myTranslateTransform = new TranslateTransform();
myTranslateTransform.Y = 1;

TransformGroup myTransformGroup = new TransformGroup();


myTransformGroup.Children.Add(myScaleTransform);
myTransformGroup.Children.Add(myTranslateTransform);

myVisualBrush.RelativeTransform = myTransformGroup;

reflectionRectangle.Fill = myVisualBrush;

// Create a gradient background for the border.


GradientStop firstStop2 = new GradientStop();
firstStop2.Offset = 0.0;
Color c1 = new Color();
c1.R = 0;
c1.G = 0;
c1.B = 0;
c1.A = 255;
firstStop2.Color = c1;
GradientStop secondStop2 = new GradientStop();
secondStop2.Offset = 0.5;
Color c2 = new Color();
c2.R = 0;
c2.G = 0;
c2.B = 0;
c2.A = 51;
firstStop2.Color = c2;
GradientStop thirdStop = new GradientStop();
thirdStop.Offset = 0.75;
Color c3 = new Color();
c3.R = 0;
c3.G = 0;
c3.B = 0;
c3.A = 0;
thirdStop.Color = c3;

GradientStopCollection myGradientStopCollection2 = new GradientStopCollection();


myGradientStopCollection2.Add(firstStop2);
myGradientStopCollection2.Add(secondStop2);
myGradientStopCollection2.Add(thirdStop);

LinearGradientBrush myLinearGradientBrush2 = new LinearGradientBrush();


myLinearGradientBrush2.StartPoint = new Point(0.5, 0);
myLinearGradientBrush2.EndPoint = new Point(0.5, 1);
myLinearGradientBrush2.GradientStops = myGradientStopCollection2;
reflectionRectangle.OpacityMask = myLinearGradientBrush2;

BlurBitmapEffect myBlurBitmapEffect = new BlurBitmapEffect();


myBlurBitmapEffect.Radius = 1.5;

reflectionRectangle.BitmapEffect = myBlurBitmapEffect;

myStackPanel.Children.Add(myReflectedBorder);
myStackPanel.Children.Add(dividerRectangle);
myStackPanel.Children.Add(reflectionRectangle);
this.Content = myStackPanel;
}
/*
<Rectangle
Height="{Binding Path=ActualHeight, ElementName=ReflectedVisual}"
Width="{Binding Path=ActualWidth, ElementName=ReflectedVisual}">

<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FF000000" Offset="0.0" />
<GradientStop Color="#33000000" Offset="0.5" />
<GradientStop Color="#00000000" Offset="0.75" />
</LinearGradientBrush>
</Rectangle.OpacityMask>

<Rectangle.BitmapEffect>
<BlurBitmapEffect Radius="1.5" />
</Rectangle.BitmapEffect>

</Rectangle>
</StackPanel>
</Page>

*/
}
}

Imports System.Windows
Imports System.Windows.Data
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Effects
Imports System.Windows.Media.Imaging
Imports System.IO
Imports System.Collections.ObjectModel
Imports System.Windows.Shapes
Namespace SDKSample
Partial Public Class ReflectionExample
Inherits Page
Public Sub New()
' Create a name scope for the page.
NameScope.SetNameScope(Me, New NameScope())

Me.Background = Brushes.Black
Dim myStackPanel As New StackPanel()
myStackPanel.Margin = New Thickness(50)

Dim myReflectedBorder As New Border()


Me.RegisterName("ReflectedVisual", myReflectedBorder)

' Create a gradient background for the border.


Dim firstStop As New GradientStop()
firstStop.Offset = 0.0
Dim firstStopColor As New Color()
firstStopColor.R = 204
firstStopColor.G = 204
firstStopColor.B = 255
firstStopColor.A = 255
firstStop.Color = firstStopColor
Dim secondStop As New GradientStop()
secondStop.Offset = 1.0
secondStop.Color = Colors.White

Dim myGradientStopCollection As New GradientStopCollection()


myGradientStopCollection.Add(firstStop)
myGradientStopCollection.Add(secondStop)

Dim myLinearGradientBrush As New LinearGradientBrush()


myLinearGradientBrush.StartPoint = New Point(0, 0.5)
myLinearGradientBrush.EndPoint = New Point(1, 0.5)
myLinearGradientBrush.GradientStops = myGradientStopCollection

myReflectedBorder.Background = myLinearGradientBrush

' Add contents to the border.


Dim borderStackPanel As New StackPanel()
borderStackPanel.Orientation = Orientation.Horizontal
borderStackPanel.Margin = New Thickness(10)

Dim myTextBlock As New TextBlock()


myTextBlock.TextWrapping = TextWrapping.Wrap
myTextBlock.Width = 200
myTextBlock.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." & " Suspendisse vel
ante. Donec luctus tortor sit amet est." & " Nullam pulvinar odio et wisi." & " Pellentesque quis magna. Sed
pellentesque." & " Nulla euismod." & "Pellentesque habitant morbi tristique senectus et netus et malesuada
fames ac turpis egestas."

borderStackPanel.Children.Add(myTextBlock)

Dim ellipseStackPanel As New StackPanel()

Dim ellipse1 As New Ellipse()


ellipse1.Margin = New Thickness(10)
ellipse1.Height = 50
ellipse1.Width = 50
ellipse1.Fill = Brushes.Black
ellipseStackPanel.Children.Add(ellipse1)
Dim ellipse2 As New Ellipse()
ellipse2.Margin = New Thickness(10)
ellipse2.Height = 50
ellipse2.Width = 50
ellipse2.Fill = Brushes.Black
ellipseStackPanel.Children.Add(ellipse2)
Dim ellipse3 As New Ellipse()
ellipse3.Margin = New Thickness(10)
ellipse3.Height = 50
ellipse3.Width = 50
ellipse3.Fill = Brushes.Black
ellipseStackPanel.Children.Add(ellipse3)
borderStackPanel.Children.Add(ellipseStackPanel)

myReflectedBorder.Child = borderStackPanel

' Create divider rectangle


Dim dividerRectangle As New Rectangle()
dividerRectangle.Height = 1
dividerRectangle.Fill = Brushes.Gray
dividerRectangle.HorizontalAlignment = HorizontalAlignment.Stretch

' Create the object to contain the reflection.


Dim reflectionRectangle As New Rectangle()

' Bind the height of the rectangle to the border height.


Dim heightBinding As New Binding()
heightBinding.ElementName = "ReflectedVisual"
heightBinding.Path = New PropertyPath(Rectangle.HeightProperty)
BindingOperations.SetBinding(reflectionRectangle, Rectangle.HeightProperty, heightBinding)

' Bind the width of the rectangle to the border width.


Dim widthBinding As New Binding()
widthBinding.ElementName = "ReflectedVisual"
widthBinding.Path = New PropertyPath(Rectangle.WidthProperty)
BindingOperations.SetBinding(reflectionRectangle, Rectangle.WidthProperty, widthBinding)

' Creates the reflection.


Dim myVisualBrush As New VisualBrush()
myVisualBrush.Opacity = 0.75
myVisualBrush.Stretch = Stretch.None
Dim reflectionBinding As New Binding()
reflectionBinding.ElementName = "ReflectedVisual"
BindingOperations.SetBinding(myVisualBrush, VisualBrush.VisualProperty, reflectionBinding)

Dim myScaleTransform As New ScaleTransform()


myScaleTransform.ScaleX = 1
myScaleTransform.ScaleY = -1
Dim myTranslateTransform As New TranslateTransform()
myTranslateTransform.Y = 1

Dim myTransformGroup As New TransformGroup()


myTransformGroup.Children.Add(myScaleTransform)
myTransformGroup.Children.Add(myTranslateTransform)

myVisualBrush.RelativeTransform = myTransformGroup

reflectionRectangle.Fill = myVisualBrush

' Create a gradient background for the border.


Dim firstStop2 As New GradientStop()
firstStop2.Offset = 0.0
Dim c1 As New Color()
c1.R = 0
c1.G = 0
c1.B = 0
c1.A = 255
firstStop2.Color = c1
Dim secondStop2 As New GradientStop()
secondStop2.Offset = 0.5
Dim c2 As New Color()
c2.R = 0
c2.G = 0
c2.B = 0
c2.A = 51
firstStop2.Color = c2
Dim thirdStop As New GradientStop()
thirdStop.Offset = 0.75
Dim c3 As New Color()
c3.R = 0
c3.G = 0
c3.B = 0
c3.A = 0
thirdStop.Color = c3

Dim myGradientStopCollection2 As New GradientStopCollection()


myGradientStopCollection2.Add(firstStop2)
myGradientStopCollection2.Add(secondStop2)
myGradientStopCollection2.Add(thirdStop)

Dim myLinearGradientBrush2 As New LinearGradientBrush()


myLinearGradientBrush2.StartPoint = New Point(0.5, 0)
myLinearGradientBrush2.EndPoint = New Point(0.5, 1)
myLinearGradientBrush2.GradientStops = myGradientStopCollection2

reflectionRectangle.OpacityMask = myLinearGradientBrush2
Dim myBlurBitmapEffect As New BlurBitmapEffect()
myBlurBitmapEffect.Radius = 1.5

reflectionRectangle.BitmapEffect = myBlurBitmapEffect

myStackPanel.Children.Add(myReflectedBorder)
myStackPanel.Children.Add(dividerRectangle)
myStackPanel.Children.Add(reflectionRectangle)
Me.Content = myStackPanel

End Sub
End Class
End Namespace

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black">

<StackPanel Margin="50">

<!-- The object to reflect. -->


<Border Name="ReflectedVisual" Width="400">
<Border.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Offset="0.0" Color="#CCCCFF" />
<GradientStop Offset="1.0" Color="White" />
</LinearGradientBrush>
</Border.Background>
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock TextWrapping="Wrap" Width="200" Margin="10">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Suspendisse vel ante. Donec luctus tortor sit amet est.
Nullam pulvinar odio et wisi.
Pellentesque quis magna. Sed pellentesque.
Nulla euismod.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
</TextBlock>
<StackPanel>
<Ellipse Margin="10" Height="50" Width="50" Fill="Black" />
<Ellipse Margin="10" Height="50" Width="50" Fill="Black" />
<Ellipse Margin="10" Height="50" Width="50" Fill="Black" />
</StackPanel>
</StackPanel>
</Border>

<Rectangle Height="1" Fill="Gray" HorizontalAlignment="Stretch" />

<!-- The object to contain the reflection.-->


<Rectangle
Height="{Binding Path=ActualHeight, ElementName=ReflectedVisual}"
Width="{Binding Path=ActualWidth, ElementName=ReflectedVisual}">
<Rectangle.Fill>

<!-- Creates the reflection. -->


<VisualBrush
Opacity="0.75" Stretch="None"
Visual="{Binding ElementName=ReflectedVisual}">
<VisualBrush.RelativeTransform>

<!-- Flip the reflection. -->


<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="-1" />
<TranslateTransform Y="1" />
</TransformGroup>
</VisualBrush.RelativeTransform>
</VisualBrush>
</Rectangle.Fill>

<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FF000000" Offset="0.0" />
<GradientStop Color="#33000000" Offset="0.5" />
<GradientStop Color="#00000000" Offset="0.75" />
</LinearGradientBrush>
</Rectangle.OpacityMask>

<Rectangle.BitmapEffect>
<BlurBitmapEffect Radius="1.5" />
</Rectangle.BitmapEffect>

</Rectangle>
</StackPanel>
</Page>

Para obtener el ejemplo completo, que incluye ejemplos que muestran cómo ampliar partes de la pantalla y cómo
crear reflejos, vea ejemplo de VisualBrush.

Consulte también
VisualBrush
Pintar con imágenes, dibujos y elementos visuales
Procedimiento Crear patrones de mosaico diferentes
con un objeto TileBrush
23/10/2019 • 7 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el TileMode propiedad de un TileBrush para crear un patrón.
El TileMode propiedad le permite especificar cómo el contenido de un TileBrush se repite, es decir, en mosaico
para rellenar un área de salida. Para crear un modelo, puede establecer el TileMode a Tile, FlipX, FlipY, o FlipXY.
También debe establecer el Viewport de la TileBrush para que sea menor que el área que se está pintando; en caso
contrario, solo un único mosaico está generado, independientemente que TileMode configuración utilizada.

Ejemplo
En el ejemplo siguiente se crea cinco DrawingBrush los objetos, proporciona a cada uno un diferentes TileMode
configuración y los usa para dibujar cinco rectángulos. Aunque este ejemplo usa el DrawingBrush clase para
demostrar TileMode comportamiento, el TileMode propiedad funciona de forma idéntica para todas la TileBrush
objetos, es decir, para ImageBrush, VisualBrush, y DrawingBrush.
En la ilustración siguiente se muestra el resultado que genera el ejemplo.

Patrones de mosaico creados con la propiedad TileMode

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace BrushesIntroduction
{
public class TileModeExample : Page
{

public TileModeExample()
{
Background = Brushes.White;
Margin = new Thickness(20);
StackPanel mainPanel = new StackPanel();
mainPanel.HorizontalAlignment = HorizontalAlignment.Left;

//
// Create a Drawing. This will be the DrawingBrushes' content.
//
PolyLineSegment triangleLinesSegment = new PolyLineSegment();
triangleLinesSegment.Points.Add(new Point(50, 0));
triangleLinesSegment.Points.Add(new Point(0, 50));
PathFigure triangleFigure = new PathFigure();
triangleFigure.IsClosed = true;
triangleFigure.StartPoint = new Point(0, 0);
triangleFigure.Segments.Add(triangleLinesSegment);
PathGeometry triangleGeometry = new PathGeometry();
triangleGeometry.Figures.Add(triangleFigure);
GeometryDrawing triangleDrawing = new GeometryDrawing();
triangleDrawing.Geometry = triangleGeometry;
triangleDrawing.Brush = new SolidColorBrush(Color.FromArgb(255, 204, 204, 255));
Pen trianglePen = new Pen(Brushes.Black, 2);
triangleDrawing.Pen = trianglePen;
trianglePen.MiterLimit = 0;
triangleDrawing.Freeze();

//
// Create the first TileBrush. Its content is not tiled.
//
DrawingBrush tileBrushWithoutTiling = new DrawingBrush();
tileBrushWithoutTiling.Drawing = triangleDrawing;
tileBrushWithoutTiling.TileMode = TileMode.None;

// Create a rectangle and paint it with the DrawingBrush.


Rectangle noTileExampleRectangle = createExampleRectangle();
noTileExampleRectangle.Fill = tileBrushWithoutTiling;

// Add a header and the rectangle to the main panel.


mainPanel.Children.Add(createExampleHeader("None"));
mainPanel.Children.Add(noTileExampleRectangle);

//
// Create another TileBrush, this time with tiling.
//
DrawingBrush tileBrushWithTiling = new DrawingBrush();
tileBrushWithTiling.Drawing = triangleDrawing;
tileBrushWithTiling.TileMode = TileMode.Tile;

// Specify the brush's Viewport. Otherwise,


// a single tile will be produced that fills
// the entire output area and its TileMode will
// have no effect.
// This setting uses realtive values to
// creates four tiles.
tileBrushWithTiling.Viewport = new Rect(0, 0, 0.5, 0.5);

// Create a rectangle and paint it with the DrawingBrush.


Rectangle tilingExampleRectangle = createExampleRectangle();
tilingExampleRectangle.Fill = tileBrushWithTiling;
mainPanel.Children.Add(createExampleHeader("Tile"));
mainPanel.Children.Add(tilingExampleRectangle);

//
// Create a TileBrush with FlipX tiling.
// The brush's content is flipped horizontally as it is
// tiled in this example
//
DrawingBrush tileBrushWithFlipXTiling = new DrawingBrush();
tileBrushWithFlipXTiling.Drawing = triangleDrawing;
tileBrushWithFlipXTiling.TileMode = TileMode.FlipX;

// Specify the brush's Viewport.


tileBrushWithFlipXTiling.Viewport = new Rect(0, 0, 0.5, 0.5);

// Create a rectangle and paint it with the DrawingBrush.


Rectangle flipXTilingExampleRectangle = createExampleRectangle();
flipXTilingExampleRectangle.Fill = tileBrushWithFlipXTiling;
mainPanel.Children.Add(createExampleHeader("FlipX"));
mainPanel.Children.Add(flipXTilingExampleRectangle);

//
// Create a TileBrush with FlipY tiling.
// The brush's content is flipped vertically as it is
// tiled in this example
//
DrawingBrush tileBrushWithFlipYTiling = new DrawingBrush();
tileBrushWithFlipYTiling.Drawing = triangleDrawing;
tileBrushWithFlipYTiling.Drawing = triangleDrawing;
tileBrushWithFlipYTiling.TileMode = TileMode.FlipY;

// Specify the brush's Viewport.


tileBrushWithFlipYTiling.Viewport = new Rect(0, 0, 0.5, 0.5);

// Create a rectangle and paint it with the DrawingBrush.


Rectangle flipYTilingExampleRectangle = createExampleRectangle();
flipYTilingExampleRectangle.Fill = tileBrushWithFlipYTiling;
mainPanel.Children.Add(createExampleHeader("FlipY"));
mainPanel.Children.Add(flipYTilingExampleRectangle);

//
// Create a TileBrush with FlipXY tiling.
// The brush's content is flipped vertically as it is
// tiled in this example
//
DrawingBrush tileBrushWithFlipXYTiling = new DrawingBrush();
tileBrushWithFlipXYTiling.Drawing = triangleDrawing;
tileBrushWithFlipXYTiling.TileMode = TileMode.FlipXY;

// Specify the brush's Viewport.


tileBrushWithFlipXYTiling.Viewport = new Rect(0, 0, 0.5, 0.5);

// Create a rectangle and paint it with the DrawingBrush.


Rectangle flipXYTilingExampleRectangle = createExampleRectangle();
flipXYTilingExampleRectangle.Fill = tileBrushWithFlipXYTiling;
mainPanel.Children.Add(createExampleHeader("FlipXY"));
mainPanel.Children.Add(flipXYTilingExampleRectangle);

Content = mainPanel;
}

//
// Helper method that creates rectangle elements.
//
private static Rectangle createExampleRectangle()
{
Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 50;
exampleRectangle.Height = 50;
exampleRectangle.Stroke = Brushes.Black;
exampleRectangle.StrokeThickness = 1;
return exampleRectangle;
}

//
// Helper method that creates headers for the examples.
//
private static TextBlock createExampleHeader(String text)
{
TextBlock header = new TextBlock();
header.Margin = new Thickness(0, 10, 0, 0);
header.Text = text;
return header;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes

Namespace BrushesIntroduction
Namespace BrushesIntroduction
Public Class TileModeExample
Inherits Page

Public Sub New()


Background = Brushes.White
Margin = New Thickness(20)
Dim mainPanel As New StackPanel()
mainPanel.HorizontalAlignment = HorizontalAlignment.Left

'
' Create a Drawing. This will be the DrawingBrushes' content.
'
Dim triangleLinesSegment As New PolyLineSegment()
triangleLinesSegment.Points.Add(New Point(50, 0))
triangleLinesSegment.Points.Add(New Point(0, 50))
Dim triangleFigure As New PathFigure()
triangleFigure.IsClosed = True
triangleFigure.StartPoint = New Point(0, 0)
triangleFigure.Segments.Add(triangleLinesSegment)
Dim triangleGeometry As New PathGeometry()
triangleGeometry.Figures.Add(triangleFigure)

Dim triangleDrawing As New GeometryDrawing()


triangleDrawing.Geometry = triangleGeometry
triangleDrawing.Brush = New SolidColorBrush(Color.FromArgb(255, 204, 204, 255))
Dim trianglePen As New Pen(Brushes.Black, 2)
triangleDrawing.Pen = trianglePen
trianglePen.MiterLimit = 0
triangleDrawing.Freeze()

'
' Create the first TileBrush. Its content is not tiled.
'
Dim tileBrushWithoutTiling As New DrawingBrush()
tileBrushWithoutTiling.Drawing = triangleDrawing
tileBrushWithoutTiling.TileMode = TileMode.None

' Create a rectangle and paint it with the DrawingBrush.


Dim noTileExampleRectangle As Rectangle = createExampleRectangle()
noTileExampleRectangle.Fill = tileBrushWithoutTiling

' Add a header and the rectangle to the main panel.


mainPanel.Children.Add(createExampleHeader("None"))
mainPanel.Children.Add(noTileExampleRectangle)

'
' Create another TileBrush, this time with tiling.
'
Dim tileBrushWithTiling As New DrawingBrush()
tileBrushWithTiling.Drawing = triangleDrawing
tileBrushWithTiling.TileMode = TileMode.Tile

' Specify the brush's Viewport. Otherwise,


' a single tile will be produced that fills
' the entire output area and its TileMode will
' have no effect.
' This setting uses realtive values to
' creates four tiles.
tileBrushWithTiling.Viewport = New Rect(0, 0, 0.5, 0.5)

' Create a rectangle and paint it with the DrawingBrush.


Dim tilingExampleRectangle As Rectangle = createExampleRectangle()
tilingExampleRectangle.Fill = tileBrushWithTiling
mainPanel.Children.Add(createExampleHeader("Tile"))
mainPanel.Children.Add(tilingExampleRectangle)

'
' Create a TileBrush with FlipX tiling.
' The brush's content is flipped horizontally as it is
' The brush's content is flipped horizontally as it is
' tiled in this example
'
Dim tileBrushWithFlipXTiling As New DrawingBrush()
tileBrushWithFlipXTiling.Drawing = triangleDrawing
tileBrushWithFlipXTiling.TileMode = TileMode.FlipX

' Specify the brush's Viewport.


tileBrushWithFlipXTiling.Viewport = New Rect(0, 0, 0.5, 0.5)

' Create a rectangle and paint it with the DrawingBrush.


Dim flipXTilingExampleRectangle As Rectangle = createExampleRectangle()
flipXTilingExampleRectangle.Fill = tileBrushWithFlipXTiling
mainPanel.Children.Add(createExampleHeader("FlipX"))
mainPanel.Children.Add(flipXTilingExampleRectangle)

'
' Create a TileBrush with FlipY tiling.
' The brush's content is flipped vertically as it is
' tiled in this example
'
Dim tileBrushWithFlipYTiling As New DrawingBrush()
tileBrushWithFlipYTiling.Drawing = triangleDrawing
tileBrushWithFlipYTiling.TileMode = TileMode.FlipY

' Specify the brush's Viewport.


tileBrushWithFlipYTiling.Viewport = New Rect(0, 0, 0.5, 0.5)

' Create a rectangle and paint it with the DrawingBrush.


Dim flipYTilingExampleRectangle As Rectangle = createExampleRectangle()
flipYTilingExampleRectangle.Fill = tileBrushWithFlipYTiling
mainPanel.Children.Add(createExampleHeader("FlipY"))
mainPanel.Children.Add(flipYTilingExampleRectangle)

'
' Create a TileBrush with FlipXY tiling.
' The brush's content is flipped vertically as it is
' tiled in this example
'
Dim tileBrushWithFlipXYTiling As New DrawingBrush()
tileBrushWithFlipXYTiling.Drawing = triangleDrawing
tileBrushWithFlipXYTiling.TileMode = TileMode.FlipXY

' Specify the brush's Viewport.


tileBrushWithFlipXYTiling.Viewport = New Rect(0, 0, 0.5, 0.5)

' Create a rectangle and paint it with the DrawingBrush.


Dim flipXYTilingExampleRectangle As Rectangle = createExampleRectangle()
flipXYTilingExampleRectangle.Fill = tileBrushWithFlipXYTiling
mainPanel.Children.Add(createExampleHeader("FlipXY"))
mainPanel.Children.Add(flipXYTilingExampleRectangle)

Content = mainPanel
End Sub

'
' Helper method that creates rectangle elements.
'
Private Shared Function createExampleRectangle() As Rectangle
Dim exampleRectangle As New Rectangle()
exampleRectangle.Width = 50
exampleRectangle.Height = 50
exampleRectangle.Stroke = Brushes.Black
exampleRectangle.StrokeThickness = 1
Return exampleRectangle
End Function

'
' Helper method that creates headers for the examples.
'
Private Shared Function createExampleHeader(ByVal text As String) As TextBlock
Dim header As New TextBlock()
header.Margin = New Thickness(0, 10, 0, 0)
header.Text = text
Return header
End Function
End Class
End Namespace

<!-- Demonstrates TileMode values. -->


<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Background="White" Margin="20">
<Page.Resources>

<!-- Define a Drawing as a resource that it can be easily used


as content for all the DrawingBrush objects in this example. -->
<GeometryDrawing x:Key="TriangleDrawing"
Geometry="M0,0 L50,0 0,50Z" Brush="#CCCCFF"
PresentationOptions:Freeze="True" >
<GeometryDrawing.Pen>
<Pen Thickness="2" Brush="Black" MiterLimit="0" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</Page.Resources>

<StackPanel HorizontalAlignment="Left">
<TextBlock Margin="0,10,0,0">None</TextBlock>
<Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>

<!-- The DrawingBrush's content is not tiled in this example. -->


<DrawingBrush TileMode="None"
Drawing="{StaticResource TriangleDrawing}" />
</Rectangle.Fill>
</Rectangle>

<TextBlock Margin="0,10,0,0">Tile</TextBlock>
<Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>

<!-- The DrawingBrush's content is tiled in this example.


The Viewport property is set to create four tiles. -->
<DrawingBrush TileMode="Tile" Viewport="0,0,0.5,0.5"
Drawing="{StaticResource TriangleDrawing}"/>
</Rectangle.Fill>
</Rectangle>

<TextBlock Margin="0,10,0,0">FlipX</TextBlock>
<Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>

<!-- The DrawingBrush's content is flipped horizontally as it is


tiled in this example. -->
<DrawingBrush
TileMode="FlipX" Viewport="0,0,0.5,0.5"
Drawing="{StaticResource TriangleDrawing}" />
</Rectangle.Fill>
</Rectangle>

<TextBlock Margin="0,10,0,0">FlipY</TextBlock>
<Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>
<Rectangle.Fill>

<!-- The DrawingBrush's content is flipped vertically as it is


tiled in this example. -->
<DrawingBrush TileMode="FlipY" Viewport="0,0,0.5,0.5"
Drawing="{StaticResource TriangleDrawing}" />
</Rectangle.Fill>
</Rectangle>

<TextBlock Margin="0,10,0,0">FlipXY</TextBlock>
<Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>

<!-- The DrawingBrush's content is flipped horizontally


and vertically as it is tiled in this example. -->
<DrawingBrush TileMode="FlipXY" Viewport="0,0,0.5,0.5"
Drawing="{StaticResource TriangleDrawing}" />
</Rectangle.Fill>
</Rectangle>

</StackPanel>
</Page>

Vea también
Establecer el tamaño del mosaico de un TileBrush
Pintar con imágenes, dibujos y elementos visuales
Procedimiento Definir un lápiz
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo utilizar un Pen para esquematizar una forma. Para crear una sencilla Pen, sólo
necesita especificar su Thickness y Brush. Puede crear lápiz más complejo especificando un DashStyle, DashCap,
LineJoin, StartLineCap, y EndLineCap.

Ejemplo
En el ejemplo siguiente se usa un Pen describir una forma definida por un GeometryDrawing.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace SDKSample
{
public partial class PenExample : Page
{
public PenExample()
{
// Create several geometries.
RectangleGeometry myRectangleGeometry = new RectangleGeometry();
myRectangleGeometry.Rect = new Rect(0, 0, 50, 50);
EllipseGeometry myEllipseGeometry = new EllipseGeometry();
myEllipseGeometry.Center = new Point(75, 75);
myEllipseGeometry.RadiusX = 50;
myEllipseGeometry.RadiusY = 50;
LineGeometry myLineGeometry = new LineGeometry();
myLineGeometry.StartPoint = new Point(75, 75);
myLineGeometry.EndPoint = new Point(75, 0);

// Create a GeometryGroup and add the geometries to it.


GeometryGroup myGeometryGroup = new GeometryGroup();
myGeometryGroup.Children.Add(myRectangleGeometry);
myGeometryGroup.Children.Add(myEllipseGeometry);
myGeometryGroup.Children.Add(myLineGeometry);

// Create a GeometryDrawing and use the GeometryGroup to specify


// its geometry.
GeometryDrawing myGeometryDrawing = new GeometryDrawing();
myGeometryDrawing.Geometry = myGeometryGroup;

// Add the GeometryDrawing to a DrawingGroup.


DrawingGroup myDrawingGroup = new DrawingGroup();
myDrawingGroup.Children.Add(myGeometryDrawing);

// Create a Pen to add to the GeometryDrawing created above.


Pen myPen = new Pen();
myPen.Thickness = 10;
myPen.LineJoin = PenLineJoin.Round;
myPen.EndLineCap = PenLineCap.Round;

// Create a gradient to use as a value for the Pen's Brush property.


GradientStop firstStop = new GradientStop();
firstStop.Offset = 0.0;
Color c1 = new Color();
c1.A = 255;
c1.R = 204;
c1.G = 204;
c1.B = 255;
c1.B = 255;
firstStop.Color = c1;
GradientStop secondStop = new GradientStop();
secondStop.Offset = 1.0;
secondStop.Color = Colors.Purple;

LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush();


myLinearGradientBrush.GradientStops.Add(firstStop);
myLinearGradientBrush.GradientStops.Add(secondStop);

myPen.Brush = myLinearGradientBrush;
myGeometryDrawing.Pen = myPen;

// Create an Image and set its DrawingImage to the Geometry created above.
Image myImage = new Image();
myImage.Stretch = Stretch.None;
myImage.Margin = new Thickness(10);

DrawingImage myDrawingImage = new DrawingImage();


myDrawingImage.Drawing = myDrawingGroup;
myImage.Source = myDrawingImage;

this.Content = myImage;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Namespace SDKSample
Partial Public Class PenExample
Inherits Page
Public Sub New()
' Create several geometries.
Dim myRectangleGeometry As New RectangleGeometry()
myRectangleGeometry.Rect = New Rect(0, 0, 50, 50)
Dim myEllipseGeometry As New EllipseGeometry()
myEllipseGeometry.Center = New Point(75, 75)
myEllipseGeometry.RadiusX = 50
myEllipseGeometry.RadiusY = 50
Dim myLineGeometry As New LineGeometry()
myLineGeometry.StartPoint = New Point(75, 75)
myLineGeometry.EndPoint = New Point(75, 0)

' Create a GeometryGroup and add the geometries to it.


Dim myGeometryGroup As New GeometryGroup()
myGeometryGroup.Children.Add(myRectangleGeometry)
myGeometryGroup.Children.Add(myEllipseGeometry)
myGeometryGroup.Children.Add(myLineGeometry)

' Create a GeometryDrawing and use the GeometryGroup to specify


' its geometry.
Dim myGeometryDrawing As New GeometryDrawing()
myGeometryDrawing.Geometry = myGeometryGroup

' Add the GeometryDrawing to a DrawingGroup.


Dim myDrawingGroup As New DrawingGroup()
myDrawingGroup.Children.Add(myGeometryDrawing)

' Create a Pen to add to the GeometryDrawing created above.


Dim myPen As New Pen()
myPen.Thickness = 10
myPen.LineJoin = PenLineJoin.Round
myPen.EndLineCap = PenLineCap.Round

' Create a gradient to use as a value for the Pen's Brush property.
' Create a gradient to use as a value for the Pen's Brush property.
Dim firstStop As New GradientStop()
firstStop.Offset = 0.0
Dim c1 As New Color()
c1.A = 255
c1.R = 204
c1.G = 204
c1.B = 255
firstStop.Color = c1
Dim secondStop As New GradientStop()
secondStop.Offset = 1.0
secondStop.Color = Colors.Purple

Dim myLinearGradientBrush As New LinearGradientBrush()


myLinearGradientBrush.GradientStops.Add(firstStop)
myLinearGradientBrush.GradientStops.Add(secondStop)

myPen.Brush = myLinearGradientBrush
myGeometryDrawing.Pen = myPen

' Create an Image and set its DrawingImage to the Geometry created above.
Dim myImage As New Image()
myImage.Stretch = Stretch.None
myImage.Margin = New Thickness(10)

Dim myDrawingImage As New DrawingImage()


myDrawingImage.Drawing = myDrawingGroup
myImage.Source = myDrawingImage

Me.Content = myImage

End Sub
End Class
End Namespace

GeometryDrawing
Procedimiento Pintar un área con un dibujo
23/10/2019 • 6 minutes to read • Edit Online

En este ejemplo se muestra cómo pintar un área con un dibujo. Para pintar un área con un dibujo, usa un
DrawingBrush y uno o varios Drawing objetos. En el ejemplo siguiente se usa un DrawingBrush para pintar un
objeto con un dibujo de dos elipses.

Ejemplo
<!-- Demonstrates the use of DrawingBrush. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="White">
<StackPanel Margin="20">

<Rectangle Width="150" Height="150" Stroke="Black" StrokeThickness="1">


<Rectangle.Fill>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="10">
<Pen.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Black" />
<GradientStop Offset="1.0" Color="Gray" />
</LinearGradientBrush>
</Pen.Brush>
</Pen>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</StackPanel>
</Page>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Microsoft.Samples.DrawingBrushExamples
{
/// <summary>
/// Paints a Rectangle element with a DrawingBrush.
/// </summary>
/// </summary>
public class DrawingBrushExample : Page
{
public DrawingBrushExample()
{
Background = Brushes.White;
StackPanel mainPanel = new StackPanel();

// Create a drawing of two ellipses.


GeometryDrawing aDrawing = new GeometryDrawing();

// Use geometries to describe two overlapping ellipses.


EllipseGeometry ellipse1 = new EllipseGeometry();
ellipse1.RadiusX = 20;
ellipse1.RadiusY = 45;
ellipse1.Center = new Point(50, 50);
EllipseGeometry ellipse2 = new EllipseGeometry();
ellipse2.RadiusX = 45;
ellipse2.RadiusY = 20;
ellipse2.Center = new Point(50, 50);
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(ellipse1);
ellipses.Children.Add(ellipse2);

// Add the geometry to the drawing.


aDrawing.Geometry = ellipses;

// Specify the drawing's fill.


aDrawing.Brush = Brushes.Blue;

// Specify the drawing's stroke.


Pen stroke = new Pen();
stroke.Thickness = 10.0;
stroke.Brush = new LinearGradientBrush(
Colors.Black, Colors.Gray, new Point(0, 0), new Point(1, 1));
aDrawing.Pen = stroke;

// Create a DrawingBrush
DrawingBrush myDrawingBrush = new DrawingBrush();
myDrawingBrush.Drawing = aDrawing;

// Create a Rectangle element.


Rectangle aRectangle = new Rectangle();
aRectangle.Width = 150;
aRectangle.Height = 150;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 1.0;

// Use the DrawingBrush to paint the rectangle's


// background.
aRectangle.Fill = myDrawingBrush;

mainPanel.Children.Add(aRectangle);

this.Content = mainPanel;
}
}
}
Imports System.Windows.Media.Animation

Namespace Microsoft.Samples.DrawingBrushExamples
''' <summary>
''' Paints a Rectangle element with a DrawingBrush.
''' </summary>
Public Class DrawingBrushExample
Inherits Page
Public Sub New()
Background = Brushes.White
Dim mainPanel As New StackPanel()

' Create a drawing of two ellipses.


Dim aDrawing As New GeometryDrawing()

' Use geometries to describe two overlapping ellipses.


Dim ellipse1 As New EllipseGeometry()
ellipse1.RadiusX = 20
ellipse1.RadiusY = 45
ellipse1.Center = New Point(50, 50)
Dim ellipse2 As New EllipseGeometry()
ellipse2.RadiusX = 45
ellipse2.RadiusY = 20
ellipse2.Center = New Point(50, 50)
Dim ellipses As New GeometryGroup()
ellipses.Children.Add(ellipse1)
ellipses.Children.Add(ellipse2)

' Add the geometry to the drawing.


aDrawing.Geometry = ellipses

' Specify the drawing's fill.


aDrawing.Brush = Brushes.Blue

' Specify the drawing's stroke.


Dim stroke As New Pen()
stroke.Thickness = 10.0
stroke.Brush = New LinearGradientBrush(Colors.Black, Colors.Gray, New Point(0, 0), New Point(1,
1))
aDrawing.Pen = stroke

' Create a DrawingBrush


Dim myDrawingBrush As New DrawingBrush()
myDrawingBrush.Drawing = aDrawing

' Create a Rectangle element.


Dim aRectangle As New Rectangle()
aRectangle.Width = 150
aRectangle.Height = 150
aRectangle.Stroke = Brushes.Black
aRectangle.StrokeThickness = 1.0

' Use the DrawingBrush to paint the rectangle's


' background.
aRectangle.Fill = myDrawingBrush

mainPanel.Children.Add(aRectangle)

Me.Content = mainPanel

End Sub
End Class
End Namespace
En la siguiente ilustración se muestra el resultado del ejemplo.

(El centro de la forma es blanco por las razones descritas en controlar el relleno de una forma compuesta.)
Estableciendo un DrawingBrush del objeto Viewport y TileMode propiedades, puede crear un patrón de repetición.
En el ejemplo siguiente se pinta un objeto con un patrón creado a partir de un dibujo de dos elipses.

<!-- Demonstrates the use of DrawingBrush. -->


<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="White">
<StackPanel Margin="20">

<Rectangle Width="150" Height="150" Stroke="Black" StrokeThickness="1">


<Rectangle.Fill>
<DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="10">
<Pen.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Black" />
<GradientStop Offset="1.0" Color="Gray" />
</LinearGradientBrush>
</Pen.Brush>
</Pen>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</StackPanel>
</Page>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Microsoft.Samples.DrawingBrushExamples
{

/// <summary>
/// <summary>
/// Paints a Rectangle element with a tiled DrawingBrush.
/// </summary>
public class TiledDrawingBrushExample : Page
{

public TiledDrawingBrushExample()
{
Background = Brushes.White;
StackPanel mainPanel = new StackPanel();

// Create a drawing of two ellipses.


GeometryDrawing aDrawing = new GeometryDrawing();

// Use geometries to describe two overlapping ellipses.


EllipseGeometry ellipse1 = new EllipseGeometry();
ellipse1.RadiusX = 20;
ellipse1.RadiusY = 45;
ellipse1.Center = new Point(50, 50);
EllipseGeometry ellipse2 = new EllipseGeometry();
ellipse2.RadiusX = 45;
ellipse2.RadiusY = 20;
ellipse2.Center = new Point(50, 50);
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(ellipse1);
ellipses.Children.Add(ellipse2);

// Add the geometry to the drawing.


aDrawing.Geometry = ellipses;

// Specify the drawing's fill.


aDrawing.Brush = Brushes.Blue;

// Specify the drawing's stroke.


Pen stroke = new Pen();
stroke.Thickness = 10.0;
stroke.Brush = new LinearGradientBrush(
Colors.Black, Colors.Gray, new Point(0, 0), new Point(1, 1));
aDrawing.Pen = stroke;

// Create a DrawingBrush
DrawingBrush myDrawingBrush = new DrawingBrush();
myDrawingBrush.Drawing = aDrawing;

// Set the DrawingBrush's Viewport and TileMode


// properties so that it generates a pattern.
myDrawingBrush.Viewport = new Rect(0, 0, 0.25, 0.25);
myDrawingBrush.TileMode = TileMode.Tile;

// Create a Rectangle element.


Rectangle aRectangle = new Rectangle();
aRectangle.Width = 150;
aRectangle.Height = 150;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 1.0;

// Use the DrawingBrush to paint the rectangle's


// background.
aRectangle.Fill = myDrawingBrush;

mainPanel.Children.Add(aRectangle);

this.Content = mainPanel;
}
}
}
Imports System.Windows.Media.Animation

Namespace Microsoft.Samples.DrawingBrushExamples

''' <summary>
''' Paints a Rectangle element with a tiled DrawingBrush.
''' </summary>
Public Class TiledDrawingBrushExample
Inherits Page

Public Sub New()


Background = Brushes.White
Dim mainPanel As New StackPanel()

' Create a drawing of two ellipses.


Dim aDrawing As New GeometryDrawing()

' Use geometries to describe two overlapping ellipses.


Dim ellipse1 As New EllipseGeometry()
ellipse1.RadiusX = 20
ellipse1.RadiusY = 45
ellipse1.Center = New Point(50, 50)
Dim ellipse2 As New EllipseGeometry()
ellipse2.RadiusX = 45
ellipse2.RadiusY = 20
ellipse2.Center = New Point(50, 50)
Dim ellipses As New GeometryGroup()
ellipses.Children.Add(ellipse1)
ellipses.Children.Add(ellipse2)

' Add the geometry to the drawing.


aDrawing.Geometry = ellipses

' Specify the drawing's fill.


aDrawing.Brush = Brushes.Blue

' Specify the drawing's stroke.


Dim stroke As New Pen()
stroke.Thickness = 10.0
stroke.Brush = New LinearGradientBrush(Colors.Black, Colors.Gray, New Point(0, 0), New Point(1,
1))
aDrawing.Pen = stroke

' Create a DrawingBrush


Dim myDrawingBrush As New DrawingBrush()
myDrawingBrush.Drawing = aDrawing

' Set the DrawingBrush's Viewport and TileMode


' properties so that it generates a pattern.
myDrawingBrush.Viewport = New Rect(0, 0, 0.25, 0.25)
myDrawingBrush.TileMode = TileMode.Tile

' Create a Rectangle element.


Dim aRectangle As New Rectangle()
aRectangle.Width = 150
aRectangle.Height = 150
aRectangle.Stroke = Brushes.Black
aRectangle.StrokeThickness = 1.0

' Use the DrawingBrush to paint the rectangle's


' background.
aRectangle.Fill = myDrawingBrush

mainPanel.Children.Add(aRectangle)

Me.Content = mainPanel

End Sub
End Sub

End Class
End Namespace

La siguiente ilustración muestra el mosaico DrawingBrush salida.

Para obtener más información acerca de los pinceles de dibujo, consulte pintar con imágenes, dibujos y elementos
visuales. Para obtener más información acerca de Drawing objetos, vea el información general sobre objetos de
dibujo.
Procedimiento Pintar un área con una imagen
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el ImageBrush clase para pintar un área con una imagen. Un ImageBrush
muestra una sola imagen, que se especifica mediante su ImageSource propiedad.

Ejemplo
Las operaciones de pintura de ejemplo siguiente la Background de un botón mediante el uso de un ImageBrush.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Media;

namespace Microsoft.Samples.Graphics.UsingImageBrush
{

public class PaintingWithImagesExample : Page


{

public PaintingWithImagesExample()
{
Background = Brushes.White;
StackPanel mainPanel = new StackPanel();
mainPanel.Margin = new Thickness(20.0);

// Create a button.
Button berriesButton = new Button();
berriesButton.Foreground = Brushes.White;
berriesButton.FontWeight = FontWeights.Bold;
FontSizeConverter sizeConverter = new FontSizeConverter();
berriesButton.FontSize = (Double)sizeConverter.ConvertFromString("16pt");
berriesButton.FontFamily = new FontFamily("Verdana");
berriesButton.Content = "Berries";
berriesButton.Padding = new Thickness(20.0);
berriesButton.HorizontalAlignment = HorizontalAlignment.Left;

// Create an ImageBrush.
ImageBrush berriesBrush = new ImageBrush();
berriesBrush.ImageSource =
new BitmapImage(
new Uri(@"sampleImages\berries.jpg", UriKind.Relative)
);

// Use the brush to paint the button's background.


berriesButton.Background = berriesBrush;

mainPanel.Children.Add(berriesButton);
this.Content = mainPanel;
}
}
}

De forma predeterminada, un ImageBrush ajusta su imagen hasta rellenar completamente el área que se está
pintando. En el ejemplo anterior, la imagen se ajusta para rellenar el botón, lo que puede distorsionar la imagen.
Puede controlar este comportamiento estableciendo el Stretch propiedad de TileBrush a Uniform o UniformToFill,
lo que hace que el pincel conserve la relación de aspecto de la imagen.
Si establece la Viewport y TileMode las propiedades de un ImageBrush, puede crear un patrón de repetición. En el
ejemplo siguiente se pinta un botón mediante un patrón creado a partir de una imagen.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Media;

namespace Microsoft.Samples.Graphics.UsingImageBrush
{

public class TiledImageBrushExample : Page


{

public TiledImageBrushExample()
{
Background = Brushes.White;
StackPanel mainPanel = new StackPanel();
mainPanel.Margin = new Thickness(20.0);

// Create a button.
Button berriesButton = new Button();
berriesButton.Foreground = Brushes.White;
berriesButton.FontWeight = FontWeights.Bold;
FontSizeConverter sizeConverter = new FontSizeConverter();
berriesButton.FontSize = (Double)sizeConverter.ConvertFromString("16pt");
berriesButton.FontFamily = new FontFamily("Verdana");
berriesButton.Content = "Berries";
berriesButton.Padding = new Thickness(20.0);
berriesButton.HorizontalAlignment = HorizontalAlignment.Left;

// Create an ImageBrush.
ImageBrush berriesBrush = new ImageBrush();
berriesBrush.ImageSource =
new BitmapImage(
new Uri(@"sampleImages\berries.jpg", UriKind.Relative)
);

// Set the ImageBrush's Viewport and TileMode


// so that it produces a pattern from
// the image.
berriesBrush.Viewport = new Rect(0,0,0.5,0.5);
berriesBrush.TileMode = TileMode.FlipXY;

// Use the brush to paint the button's background.


berriesButton.Background = berriesBrush;

mainPanel.Children.Add(berriesButton);
this.Content = mainPanel;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media.Imaging
Imports System.Windows.Media

Namespace Microsoft.Samples.Graphics.UsingImageBrush

Public Class TiledImageBrushExample


Inherits Page

Public Sub New()


Background = Brushes.White
Dim mainPanel As New StackPanel()
mainPanel.Margin = New Thickness(20.0)

' Create a button.


Dim berriesButton As New Button()
With berriesButton
.Foreground = Brushes.White
.FontWeight = FontWeights.Bold
Dim sizeConverter As New FontSizeConverter()
.FontSize = CType(sizeConverter.ConvertFromString("16pt"), Double)
.FontFamily = New FontFamily("Verdana")
.Content = "Berries"
.Padding = New Thickness(20.0)
.HorizontalAlignment = HorizontalAlignment.Left
End With

' Create an ImageBrush.


Dim berriesBrush As New ImageBrush()
berriesBrush.ImageSource = New BitmapImage(New Uri("sampleImages\berries.jpg", UriKind.Relative))

' Set the ImageBrush's Viewport and TileMode


' so that it produces a pattern from
' the image.
berriesBrush.Viewport = New Rect(0, 0, 0.5, 0.5)
berriesBrush.TileMode = TileMode.FlipXY

' Use the brush to paint the button's background.


berriesButton.Background = berriesBrush

mainPanel.Children.Add(berriesButton)
Me.Content = mainPanel
End Sub
End Class
End Namespace

Para obtener más información sobre la ImageBrush de clases, vea pintar con imágenes, dibujos y elementos
visuales.
Este ejemplo de código forma parte de un ejemplo más extenso proporcionado para el ImageBrush clase. Para
obtener un ejemplo completo, vea ejemplo de ImageBrush.

Vea también
Pintar con imágenes, dibujos y elementos visuales
Cómo: Pintar un área con un degradado lineal
20/02/2020 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar la clase LinearGradientBrush para pintar un área con un degradado lineal.
En el ejemplo siguiente, el Fill de una Rectangle se pinta con un degradado lineal diagonal que realiza la transición
de amarillo a rojo a azul a verde lima.

Ejemplo
<!-- This rectangle is painted with a diagonal linear gradient. -->
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

Rectangle diagonalFillRectangle = new Rectangle();


diagonalFillRectangle.Width = 200;
diagonalFillRectangle.Height = 100;

// Create a diagonal linear gradient with four stops.


LinearGradientBrush myLinearGradientBrush =
new LinearGradientBrush();
myLinearGradientBrush.StartPoint = new Point(0,0);
myLinearGradientBrush.EndPoint = new Point(1,1);
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.Yellow, 0.0));
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.Red, 0.25));
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.Blue, 0.75));
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.LimeGreen, 1.0));

// Use the brush to paint the rectangle.


diagonalFillRectangle.Fill = myLinearGradientBrush;

En la ilustración siguiente se muestra el degradado creado en el ejemplo anterior.

Para crear un degradado lineal horizontal, cambie el StartPoint y EndPoint de la LinearGradientBrush a (0, 0.5) y (1,
0.5). En el ejemplo siguiente, se pinta un Rectangle con un degradado lineal horizontal.
<!-- This rectangle is painted with a horizontal linear gradient. -->
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

Rectangle horizontalFillRectangle = new Rectangle();


horizontalFillRectangle.Width = 200;
horizontalFillRectangle.Height = 100;

// Create a horizontal linear gradient with four stops.


LinearGradientBrush myHorizontalGradient =
new LinearGradientBrush();
myHorizontalGradient.StartPoint = new Point(0,0.5);
myHorizontalGradient.EndPoint = new Point(1,0.5);
myHorizontalGradient.GradientStops.Add(
new GradientStop(Colors.Yellow, 0.0));
myHorizontalGradient.GradientStops.Add(
new GradientStop(Colors.Red, 0.25));
myHorizontalGradient.GradientStops.Add(
new GradientStop(Colors.Blue, 0.75));
myHorizontalGradient.GradientStops.Add(
new GradientStop(Colors.LimeGreen, 1.0));

// Use the brush to paint the rectangle.


horizontalFillRectangle.Fill = myHorizontalGradient;

En la ilustración siguiente se muestra el degradado creado en el ejemplo anterior.

Para crear un degradado lineal vertical, cambie los StartPoint y EndPoint de la LinearGradientBrush a (0.5, 0) y (0.5,
1). En el ejemplo siguiente, se pinta un Rectangle con un degradado lineal vertical.

<!-- This rectangle is painted with a vertical gradient. -->


<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Rectangle verticalFillRectangle = new Rectangle();
verticalFillRectangle.Width = 200;
verticalFillRectangle.Height = 100;

// Create a vertical linear gradient with four stops.


LinearGradientBrush myVerticalGradient =
new LinearGradientBrush();
myVerticalGradient.StartPoint = new Point(0.5,0);
myVerticalGradient.EndPoint = new Point(0.5,1);
myVerticalGradient.GradientStops.Add(
new GradientStop(Colors.Yellow, 0.0));
myVerticalGradient.GradientStops.Add(
new GradientStop(Colors.Red, 0.25));
myVerticalGradient.GradientStops.Add(
new GradientStop(Colors.Blue, 0.75));
myVerticalGradient.GradientStops.Add(
new GradientStop(Colors.LimeGreen, 1.0));

// Use the brush to paint the rectangle.


verticalFillRectangle.Fill = myVerticalGradient;

En la ilustración siguiente se muestra el degradado creado en el ejemplo anterior.

NOTE
En los ejemplos de este tema se usa el sistema de coordenadas predeterminado para establecer puntos de inicio y extremos.
El sistema de coordenadas predeterminado es relativo a un rectángulo de selección: 0 indica 0 por ciento del rectángulo de
selección y 1 indica el 100 por ciento del cuadro de límite. Puede cambiar este sistema de coordenadas estableciendo la
propiedad MappingMode en el valor BrushMappingMode.Absolute. Un sistema de coordenadas absoluto no está
relacionado con un rectángulo de selección. Los valores se interpretan directamente en el espacio local.

Para obtener más ejemplos, vea ejemplo de pinceles. Para obtener más información sobre los degradados y otros
tipos de pinceles, consulte información general sobre el dibujo con colores sólidos y degradados.
Cómo: Pintar un área con un degradado radial
20/02/2020 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar la clase RadialGradientBrush para pintar un área con un degradado radial.

Ejemplo
En el ejemplo siguiente se usa un RadialGradientBrush para pintar un rectángulo con un degradado radial que
realiza la transición de amarillo a rojo a azul a verde lima.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace BrushesIntroduction
{
public class RadialGradientBrushSnippet : Page
{
public RadialGradientBrushSnippet()
{
Title = "RadialGradientBrush Example";
Background = Brushes.White;
Margin = new Thickness(20);

//
// Create a RadialGradientBrush with four gradient stops.
//
RadialGradientBrush radialGradient = new RadialGradientBrush();

// Set the GradientOrigin to the center of the area being painted.


radialGradient.GradientOrigin = new Point(0.5, 0.5);

// Set the gradient center to the center of the area being painted.
radialGradient.Center = new Point(0.5, 0.5);

// Set the radius of the gradient circle so that it extends to


// the edges of the area being painted.
radialGradient.RadiusX = 0.5;
radialGradient.RadiusY = 0.5;

// Create four gradient stops.


radialGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
radialGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));
radialGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));
radialGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));

// Freeze the brush (make it unmodifiable) for performance benefits.


radialGradient.Freeze();

// Create a rectangle and paint it with the


// RadialGradientBrush.
Rectangle aRectangle = new Rectangle();
aRectangle.Width = 200;
aRectangle.Height = 100;
aRectangle.Fill = radialGradient;

StackPanel mainPanel = new StackPanel();


mainPanel.Children.Add(aRectangle);
Content = mainPanel;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes

Namespace BrushesIntroduction
Public Class RadialGradientBrushSnippet
Inherits Page
Public Sub New()
Title = "RadialGradientBrush Example"
Background = Brushes.White
Margin = New Thickness(20)

'
' Create a RadialGradientBrush with four gradient stops.
'
Dim radialGradient As New RadialGradientBrush()

' Set the GradientOrigin to the center of the area being painted.
radialGradient.GradientOrigin = New Point(0.5, 0.5)

' Set the gradient center to the center of the area being painted.
radialGradient.Center = New Point(0.5, 0.5)

' Set the radius of the gradient circle so that it extends to


' the edges of the area being painted.
radialGradient.RadiusX = 0.5
radialGradient.RadiusY = 0.5

' Create four gradient stops.


radialGradient.GradientStops.Add(New GradientStop(Colors.Yellow, 0.0))
radialGradient.GradientStops.Add(New GradientStop(Colors.Red, 0.25))
radialGradient.GradientStops.Add(New GradientStop(Colors.Blue, 0.75))
radialGradient.GradientStops.Add(New GradientStop(Colors.LimeGreen, 1.0))

' Freeze the brush (make it unmodifiable) for performance benefits.


radialGradient.Freeze()

' Create a rectangle and paint it with the


' RadialGradientBrush.
Dim aRectangle As New Rectangle()
aRectangle.Width = 200
aRectangle.Height = 100
aRectangle.Fill = radialGradient

Dim mainPanel As New StackPanel()


mainPanel.Children.Add(aRectangle)
Content = mainPanel

End Sub

End Class
End Namespace
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RadialGradientBrush Example"
Background="White" Margin="20">
<StackPanel>

<!-- This rectangle is painted with a radial gradient. -->


<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<RadialGradientBrush
GradientOrigin="0.5,0.5"
Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
</StackPanel>
</Page>

En la ilustración siguiente se muestra el degradado del ejemplo anterior. Los topes del degradado se han resaltado.

NOTE
En los ejemplos de este tema se usa el sistema de coordenadas predeterminado para establecer los puntos de control. El
sistema de coordenadas predeterminado es relativo a un rectángulo de selección: 0 indica 0 por ciento del rectángulo de
selección y 1 indica el 100 por ciento del cuadro de límite. Puede cambiar este sistema de coordenadas estableciendo la
propiedad MappingMode en el valor Absolute. Un sistema de coordenadas absoluto no está relacionado con un rectángulo
de selección. Los valores se interpretan directamente en el espacio local.

Para obtener más ejemplos de RadialGradientBrush, vea el ejemplo de pinceles. Para obtener más información
sobre los degradados y otros tipos de pinceles, consulte información general sobre el dibujo con colores sólidos y
degradados.
Procedimiento Pintar un área con un color sólido
23/10/2019 • 2 minutes to read • Edit Online

Para pintar un área con un color sólido, puede usar un pincel del sistema predefinidos, como Red o Blue, o bien
puede crear un nuevo SolidColorBrush y describir su Color mediante valores alfabéticos, rojos, verde y azules. En
XAML, también puede pintar un área con un color sólido utilizando la notación hexadecimal.
Los ejemplos siguientes se usa cada una de estas técnicas para pintar un Rectangle azul.

Ejemplo
Utilizar un pincel predefinido
En el ejemplo siguiente se usa el pincel predefinido Blue para pintar un rectángulo azul.

<Rectangle Width="50" Height="50" Fill="Blue" />

// Create a rectangle and paint it with


// a predefined brush.
Rectangle myPredefinedBrushRectangle = new Rectangle();
myPredefinedBrushRectangle.Width = 50;
myPredefinedBrushRectangle.Height = 50;
myPredefinedBrushRectangle.Fill = Brushes.Blue;

Utilizar la notación hexadecimal


En el ejemplo siguiente se utiliza la notación hexadecimal de 8 dígitos para pintar un rectángulo azul.

<!-- Note that the first two characters "FF" of the 8-digit
value is the alpha which controls the transparency of
the color. Therefore, to make a completely transparent
color (invisible), use "00" for those digits (e.g. #000000FF). -->
<Rectangle Width="50" Height="50" Fill="#FF0000FF" />

Utilizar los valores ARGB


El ejemplo siguiente se crea un SolidColorBrush y describe su Color utilizando los valores ARGB para el color
azul.
<Rectangle Width="50" Height="50">
<Rectangle.Fill>
<SolidColorBrush>
<SolidColorBrush.Color>

<!-- Describes the brush's color using


RGB values. Each value has a range of 0-255.
R is for red, G is for green, and B is for blue.
A is for alpha which controls transparency of the
color. Therefore, to make a completely transparent
color (invisible), use a value of 0 for Alpha. -->
<Color A="255" R="0" G="0" B="255" />
</SolidColorBrush.Color>
</SolidColorBrush>
</Rectangle.Fill>
</Rectangle>

Rectangle myRgbRectangle = new Rectangle();


myRgbRectangle.Width = 50;
myRgbRectangle.Height = 50;
SolidColorBrush mySolidColorBrush = new SolidColorBrush();

// Describes the brush's color using RGB values.


// Each value has a range of 0-255.
mySolidColorBrush.Color = Color.FromArgb(255, 0, 0, 255);
myRgbRectangle.Fill = mySolidColorBrush;

Para conocer otras formas de describir colores, consulte el Color estructura.


Temas relacionados
Para obtener más información acerca de SolidColorBrush y ejemplos adicionales, vea el el dibujo con colores
sólidos y degradados información general.
Este ejemplo de código forma parte de un ejemplo más extenso proporcionado para el SolidColorBrush clase.
Para ver el ejemplo completo, consulte el ejemplo de pinceles.

Vea también
Brushes
Procedimiento Pintar un área con un pincel del
sistema
23/10/2019 • 3 minutes to read • Edit Online

El SystemColors clase proporciona acceso a los pinceles del sistema y los colores, como ControlBrush,
ControlBrushKey, y DesktopBrush. Un pincel del sistema es un SolidColorBrush objeto que pinta un área con el
color del sistema especificado. Un pincel del sistema siempre produce un relleno sólido; no puede usarse para
crear un degradado.
Puede utilizar los pinceles del sistema como un recurso estático o dinámico. Utilice un recurso dinámico si desea
que el pincel se actualice automáticamente si el usuario cambia el pincel del sistema mientras se ejecuta la
aplicación; de lo contrario, utilice un recurso estático. La clase SystemColors contiene varias propiedades estáticas
que siguen una convención de nomenclatura estricta:
<SystemColor> Brush
Obtiene una referencia estática a un SolidColorBrush del color del sistema especificado.
<SystemColor> BrushKey
Obtiene una referencia dinámica a un SolidColorBrush del color del sistema especificado.
<SystemColor> Color
Obtiene una referencia estática a una Color estructura de color del sistema especificado.
<SystemColor> ColorKey
Obtiene una referencia dinámica a la Color estructura de color del sistema especificado.
Un color del sistema es un Color estructura que se puede usar para configurar un pincel. Por ejemplo, puede crear
un degradado con los colores del sistema estableciendo el Color las propiedades de un LinearGradientBrush
delimitadores de degradado del objeto con los colores del sistema. Para obtener un ejemplo, vea usar colores del
sistema en un degradado.

Ejemplo
En el ejemplo siguiente se utiliza una referencia dinámica de pincel del sistema para establecer el fondo de un
botón.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="SystemColors Example" Background="White">
<StackPanel Margin="20">

<!-- Uses a dynamic resource to set the


background of a button.
If the desktop brush changes while this application
is running, this button will be updated. -->
<Button
Background="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}"
Content="Hello, World!" />

</StackPanel>
</Page>

En el ejemplo siguiente se utiliza una referencia estática de pincel del sistema para establecer el fondo de un
botón.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="SystemColors Example" Background="White">
<StackPanel Margin="20">

<!-- Uses a static brush to set the


background of a button.
If the desktop brush changes while this application
is running, this button will not be updated until
the page is loaded again. -->
<Button
Background="{x:Static SystemColors.DesktopBrush}"
Content="Hello, World!" />

</StackPanel>
</Page>

Para obtener un ejemplo que muestra cómo utilizar un color del sistema en un degradado, vea usar colores del
sistema en un degradado.

Vea también
Usar colores del sistema en un degradado
Información general sobre el dibujo con colores sólidos y degradados
Procedimiento Pintar un área con un vídeo
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo pintar un área con medios. Una manera de pintar un área con medios es usar un
MediaElement junto con un VisualBrush. Utilice la MediaElement para cargar y reproducir el archivo multimedia y,
a continuación, usarla para establecer el Visual propiedad de la VisualBrush. A continuación, puede usar el
VisualBrush para pintar un área con el elemento multimedia cargado.

Ejemplo
En el ejemplo siguiente se usa un MediaElement y un VisualBrush para pintar el Foreground de un TextBlock
control con vídeo. Este ejemplo se establece la IsMuted propiedad de la MediaElement a true para que no genere
ningún sonido.

MediaElement myMediaElement = new MediaElement();


myMediaElement.Source = new Uri("sampleMedia\\xbox.wmv", UriKind.Relative);
myMediaElement.IsMuted = true;

VisualBrush myVisualBrush = new VisualBrush();


myVisualBrush.Visual = myMediaElement;

TextBlock myTextBlock = new TextBlock();


myTextBlock.FontSize = 150;
myTextBlock.Text = "Some Text";
myTextBlock.FontWeight = FontWeights.Bold;

myTextBlock.Foreground = myVisualBrush;

Dim myMediaElement As New MediaElement()


myMediaElement.Source = New Uri("sampleMedia\xbox.wmv", UriKind.Relative)
myMediaElement.IsMuted = True

Dim myVisualBrush As New VisualBrush()


myVisualBrush.Visual = myMediaElement

Dim myTextBlock As New TextBlock()


myTextBlock.FontSize = 150
myTextBlock.Text = "Some Text"
myTextBlock.FontWeight = FontWeights.Bold

myTextBlock.Foreground = myVisualBrush

<TextBlock FontSize="100pt" Text="Some Text" FontWeight="Bold">


<TextBlock.Foreground>
<VisualBrush>
<VisualBrush.Visual>
<MediaElement Source="sampleMedia\xbox.wmv" IsMuted="True" />
</VisualBrush.Visual>
</VisualBrush>
</TextBlock.Foreground>
</TextBlock>

Ejemplo
Dado que VisualBrush hereda el TileBrush (clase), proporciona varios modos de mosaico. Estableciendo el
TileMode propiedad de un VisualBrush a Tile y estableciendo su Viewport propiedad en un valor menor que el
área que se está pintando, puede crear un patrón de mosaicos.
El ejemplo siguiente es idéntico al ejemplo anterior, salvo que el VisualBrush genera un modelo a partir del vídeo.

MediaElement myMediaElement = new MediaElement();


myMediaElement.Source = new Uri("sampleMedia\\xbox.wmv", UriKind.Relative);
myMediaElement.IsMuted = true;

VisualBrush myVisualBrush = new VisualBrush();


myVisualBrush.Viewport = new Rect(0, 0, 0.5, 0.5);
myVisualBrush.TileMode = TileMode.Tile;
myVisualBrush.Visual = myMediaElement;

TextBlock myTextBlock = new TextBlock();


myTextBlock.FontSize = 150;
myTextBlock.Text = "Some Text";
myTextBlock.FontWeight = FontWeights.Bold;

myTextBlock.Foreground = myVisualBrush;

Dim myMediaElement As New MediaElement()


myMediaElement.Source = New Uri("sampleMedia\xbox.wmv", UriKind.Relative)
myMediaElement.IsMuted = True

Dim myVisualBrush As New VisualBrush()


myVisualBrush.Viewport = New Rect(0, 0, 0.5, 0.5)
myVisualBrush.TileMode = TileMode.Tile
myVisualBrush.Visual = myMediaElement

Dim myTextBlock As New TextBlock()


myTextBlock.FontSize = 150
myTextBlock.Text = "Some Text"
myTextBlock.FontWeight = FontWeights.Bold

myTextBlock.Foreground = myVisualBrush

<TextBlock FontSize="100pt" Text="Some Text" FontWeight="Bold">


<TextBlock.Foreground>
<VisualBrush Viewport="0,0,0.5,0.5" TileMode="Tile">
<VisualBrush.Visual>

<MediaElement Source="sampleMedia\xbox.wmv" IsMuted="True" />


</VisualBrush.Visual>
</VisualBrush>
</TextBlock.Foreground>
</TextBlock>

Para obtener información acerca de cómo agregar un archivo de contenido, como un archivo multimedia, a la
aplicación, consulte WPF Application Resource, contenido y los archivos de datos. Cuando se agrega un archivo
multimedia, debe agregarlo como un archivo de contenido, no como un archivo de recursos.

Vea también
VisualBrush
Pintar con imágenes, dibujos y elementos visuales
Información general sobre objetos TileBrush
Información general sobre multimedia
Procedimiento Pintar un área con un objeto visual
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el VisualBrush clase para pintar un área con un Visual.
En el ejemplo siguiente, se utilizan varios controles y un panel como el fondo de un rectángulo.

Ejemplo
<Rectangle Width="150" Height="150" Stroke="Black" Margin="5,0,5,0">
<Rectangle.Fill>
<VisualBrush>
<VisualBrush.Visual>
<StackPanel Background="White">
<Rectangle Width="25" Height="25" Fill="Red" Margin="2" />
<TextBlock FontSize="10pt" Margin="2">Hello, World!</TextBlock>
<Button Margin="2">A Button</Button>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
VisualBrush myVisualBrush = new VisualBrush();

// Create the visual brush's contents.


StackPanel myStackPanel = new StackPanel();
myStackPanel.Background = Brushes.White;

Rectangle redRectangle = new Rectangle();


redRectangle.Width = 25;
redRectangle.Height =25;
redRectangle.Fill = Brushes.Red;
redRectangle.Margin = new Thickness(2);
myStackPanel.Children.Add(redRectangle);

TextBlock someText = new TextBlock();


FontSizeConverter myFontSizeConverter = new FontSizeConverter();
someText.FontSize = (double)myFontSizeConverter.ConvertFrom("10pt");
someText.Text = "Hello, World!";
someText.Margin = new Thickness(2);
myStackPanel.Children.Add(someText);

Button aButton = new Button();


aButton.Content = "A Button";
aButton.Margin = new Thickness(2);
myStackPanel.Children.Add(aButton);

// Use myStackPanel as myVisualBrush's content.


myVisualBrush.Visual = myStackPanel;

// Create a rectangle to paint.


Rectangle myRectangle = new Rectangle();
myRectangle.Width = 150;
myRectangle.Height = 150;
myRectangle.Stroke = Brushes.Black;
myRectangle.Margin = new Thickness(5,0,5,0);

// Use myVisualBrush to paint myRectangle.


myRectangle.Fill = myVisualBrush;
Dim myVisualBrush As New VisualBrush()

' Create the visual brush's contents.


Dim myStackPanel As New StackPanel()
myStackPanel.Background = Brushes.White

Dim redRectangle As New Rectangle()


With redRectangle
.Width = 25
.Height = 25
.Fill = Brushes.Red
.Margin = New Thickness(2)
End With
myStackPanel.Children.Add(redRectangle)

Dim someText As New TextBlock()


Dim myFontSizeConverter As New FontSizeConverter()
someText.FontSize = CDbl(myFontSizeConverter.ConvertFrom("10pt"))
someText.Text = "Hello, World!"
someText.Margin = New Thickness(2)
myStackPanel.Children.Add(someText)

Dim aButton As New Button()


aButton.Content = "A Button"
aButton.Margin = New Thickness(2)
myStackPanel.Children.Add(aButton)

' Use myStackPanel as myVisualBrush's content.


myVisualBrush.Visual = myStackPanel

' Create a rectangle to paint.


Dim myRectangle As New Rectangle()
With myRectangle
.Width = 150
.Height = 150
.Stroke = Brushes.Black
.Margin = New Thickness(5, 0, 5, 0)
End With

' Use myVisualBrush to paint myRectangle.


myRectangle.Fill = myVisualBrush

Para obtener más información acerca de VisualBrush y ejemplos adicionales, vea el pintar con imágenes, dibujos y
elementos visuales información general.
Este ejemplo de código forma parte de un ejemplo más extenso proporcionado para el VisualBrush clase. Para
obtener un ejemplo completo, vea el ejemplo de VisualBrush.

Vea también
Pintar con imágenes, dibujos y elementos visuales
Procedimiento Conservar la relación de aspecto de
una imagen usada como fondo
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el Stretch propiedad de un ImageBrush con el fin de conservar la relación
de aspecto de la imagen.
De forma predeterminada, cuando se usa un ImageBrush para pintar un área, el contenido se expande para
rellenar completamente el área de salida. Cuando el área de salida y la imagen tienen relaciones de aspecto
diferentes, la imagen queda distorsionada al ajustarse.
Para realizar una ImageBrush conservar la relación de aspecto de su imagen, establezca la Stretch propiedad
Uniform o UniformToFill.

Ejemplo
El ejemplo siguiente utiliza dos ImageBrush objetos para pintar dos rectángulos. Cada rectángulo tiene 300 por
150 píxeles y cada uno contiene una imagen de 300 por 300 píxeles. El Stretch propiedad del primer pincel se
establece en Uniformy el Stretch propiedad del segundo pincel se establece en UniformToFill.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Microsoft.Samples.Graphics.UsingImageBrush
{
/// <summary>
/// Demonstrates different ImageBrush Stretch settings.
/// </summary>
public class StretchModes : Page
{
public StretchModes()
{

// Create an ImageBrush with its Stretch


// property set to Uniform. The image it
// contains will be expanded as much as possible
// to fill the output area while still
// preserving its aspect ratio.
ImageBrush uniformBrush = new ImageBrush();
uniformBrush.ImageSource =
new BitmapImage(new Uri("sampleImages\\square.jpg", UriKind.Relative));
uniformBrush.Stretch = Stretch.Uniform;

// Freeze the brush (make it unmodifiable) for performance benefits.


uniformBrush.Freeze();

// Create a rectangle and paint it with the ImageBrush.


Rectangle rectangle1 = new Rectangle();
rectangle1.Width = 300;
rectangle1.Height = 150;
rectangle1.Stroke = Brushes.MediumBlue;
rectangle1.StrokeThickness = 1.0;
rectangle1.Fill = uniformBrush;
// Create an ImageBrush with its Stretch
// property set to UniformToFill. The image it
// contains will be expanded to completely fill
// the rectangle, but its aspect ratio is preserved.
ImageBrush uniformToFillBrush = new ImageBrush();
uniformToFillBrush.ImageSource =
new BitmapImage(new Uri("sampleImages\\square.jpg", UriKind.Relative));
uniformToFillBrush.Stretch = Stretch.UniformToFill;

// Freeze the brush (make it unmodifiable) for performance benefits.


uniformToFillBrush.Freeze();

// Create a rectangle and paint it with the ImageBrush.


Rectangle rectangle2 = new Rectangle();
rectangle2.Width = 300;
rectangle2.Height = 150;
rectangle2.Stroke = Brushes.MediumBlue;
rectangle2.StrokeThickness = 1.0;
rectangle2.Margin = new Thickness(0, 10, 0, 0);
rectangle2.Fill = uniformToFillBrush;

StackPanel mainPanel = new StackPanel();


mainPanel.Children.Add(rectangle1);
mainPanel.Children.Add(rectangle2);

Content = mainPanel;
Background = Brushes.White;
Margin = new Thickness(20);
Title = "ImageBrush Stretch Modes";
}
}
}

La siguiente ilustración muestra la salida del primer pincel, que tiene un Stretch de Uniform.

La siguiente ilustración muestra el resultado del segundo pincel, que tiene un Stretch de UniformToFill.

Tenga en cuenta que el Stretch propiedad se comporta exactamente igual para los demás TileBrush objetos, es
decir, para DrawingBrush y VisualBrush. Para obtener más información acerca de ImageBrush y el otro TileBrush
objetos, vea pintar con imágenes, dibujos y elementos visuales.
Tenga en cuenta también que, aunque el Stretch propiedad aparece para especificar cómo el TileBrush contenido
se estira para ajustarse a su área de salida, en realidad especifica cómo el TileBrush contenido se expande para
rellenar su mosaico base. Para obtener más información, consulta TileBrush.
Este ejemplo de código forma parte de un ejemplo más extenso proporcionado para el ImageBrush clase. Para
obtener un ejemplo completo, vea ejemplo de ImageBrush.

Vea también
TileBrush
Pintar con imágenes, dibujos y elementos visuales
Procedimiento Establecer la alineación horizontal y
vertical de un TileBrush
23/10/2019 • 8 minutes to read • Edit Online

En este ejemplo se muestra cómo controlar la alineación horizontal y vertical del contenido en un mosaico. Para
controlar la alineación horizontal y vertical de un TileBrush, use su AlignmentX y AlignmentY propiedades.
El AlignmentX y AlignmentY las propiedades de un TileBrush se usan cuando cualquiera de las siguientes
condiciones es verdadera:
El Stretch propiedad es Uniform o UniformToFill y Viewbox y Viewport tienen relaciones de aspecto
diferentes.
El Stretch propiedad es None y Viewbox y Viewport tienen tamaños diferentes.

Ejemplo
El ejemplo siguiente alinea el contenido de un DrawingBrush, que es un tipo de TileBrush, a la esquina superior
izquierda de su mosaico. Para alinear el contenido, el ejemplo establece la AlignmentX propiedad de la
DrawingBrush a Left y el AlignmentY propiedad Top. Este ejemplo produce el siguiente resultado:

TileBrush con alineación de contenido en la esquina superior izquierda


//
// Create a TileBrush and align its
// content to the top-left of its tile.
//
DrawingBrush topLeftAlignedTileBrush = new DrawingBrush();
topLeftAlignedTileBrush.AlignmentX = AlignmentX.Left;
topLeftAlignedTileBrush.AlignmentY = AlignmentY.Top;

// Set Stretch to None so that the brush's


// content doesn't automatically expand to
// fill the entire tile.
topLeftAlignedTileBrush.Stretch = Stretch.None;

// Define the brush's content.


GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 20, 45));
ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 45, 20));
Pen drawingPen = new Pen(Brushes.Gray, 10);
GeometryDrawing ellipseDrawing = new GeometryDrawing(Brushes.Blue, drawingPen, ellipses);
topLeftAlignedTileBrush.Drawing = ellipseDrawing;

// Use the brush to paint a rectangle.


Rectangle rectangle1 = new Rectangle();
rectangle1.Width = 150;
rectangle1.Height = 150;
rectangle1.Stroke = Brushes.Red;
rectangle1.StrokeThickness = 2;
rectangle1.Margin = new Thickness(20);
rectangle1.Fill = topLeftAlignedTileBrush;

'
' Create a TileBrush and align its
' content to the top-left of its tile.
'
Dim topLeftAlignedTileBrush As New DrawingBrush()
topLeftAlignedTileBrush.AlignmentX = AlignmentX.Left
topLeftAlignedTileBrush.AlignmentY = AlignmentY.Top

' Set Stretch to None so that the brush's


' content doesn't automatically expand to
' fill the entire tile.
topLeftAlignedTileBrush.Stretch = Stretch.None

' Define the brush's content.


Dim ellipses As New GeometryGroup()
ellipses.Children.Add(New EllipseGeometry(New Point(50, 50), 20, 45))
ellipses.Children.Add(New EllipseGeometry(New Point(50, 50), 45, 20))
Dim drawingPen As New Pen(Brushes.Gray, 10)
Dim ellipseDrawing As New GeometryDrawing(Brushes.Blue, drawingPen, ellipses)
topLeftAlignedTileBrush.Drawing = ellipseDrawing

' Use the brush to paint a rectangle.


Dim rectangle1 As New Rectangle()
With rectangle1
.Width = 150
.Height = 150
.Stroke = Brushes.Red
.StrokeThickness = 2
.Margin = New Thickness(20)
.Fill = topLeftAlignedTileBrush
End With
<Rectangle
Width="150" Height="150"
Stroke="Red" StrokeThickness="2"
Margin="20">
<Rectangle.Fill>

<!-- This brush's content is aligned to the top-left


of its tile. -->
<DrawingBrush
Stretch="None"
AlignmentX="Left"
AlignmentY="Top">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Gray" Thickness="10" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>

Ejemplo
En el ejemplo siguiente se alinea el contenido de un DrawingBrush a la esquina inferior derecha de su mosaico
estableciendo la AlignmentX propiedad Right y el AlignmentY propiedad Bottom. El ejemplo genera el siguiente
resultado.

TileBrush con alineación de contenido en la esquina inferior derecha


//
// Create a TileBrush and align its
// content to the bottom-right of its tile.
//
DrawingBrush bottomRightAlignedTileBrush = new DrawingBrush();
bottomRightAlignedTileBrush.AlignmentX = AlignmentX.Right;
bottomRightAlignedTileBrush.AlignmentY = AlignmentY.Bottom;
bottomRightAlignedTileBrush.Stretch = Stretch.None;

// Define the brush's content.


bottomRightAlignedTileBrush.Drawing = ellipseDrawing;

// Use the brush to paint a rectangle.


Rectangle rectangle2 = new Rectangle();
rectangle2.Width = 150;
rectangle2.Height = 150;
rectangle2.Stroke = Brushes.Red;
rectangle2.StrokeThickness = 2;
rectangle2.Margin = new Thickness(20);
rectangle2.Fill = bottomRightAlignedTileBrush;

'
' Create a TileBrush and align its
' content to the bottom-right of its tile.
'
Dim bottomRightAlignedTileBrush As New DrawingBrush()
With bottomRightAlignedTileBrush
.AlignmentX = AlignmentX.Right
.AlignmentY = AlignmentY.Bottom
.Stretch = Stretch.None

' Define the brush's content.


.Drawing = ellipseDrawing
End With

' Use the brush to paint a rectangle.


Dim rectangle2 As New Rectangle()
With rectangle2
.Width = 150
.Height = 150
.Stroke = Brushes.Red
.StrokeThickness = 2
.Margin = New Thickness(20)
.Fill = bottomRightAlignedTileBrush
End With
<Rectangle
Width="150" Height="150"
Stroke="Red" StrokeThickness="2"
Margin="20">
<Rectangle.Fill>

<!-- This brush's content is aligned to the bottom right


of its tile. -->
<DrawingBrush
Stretch="None"
AlignmentX="Right"
AlignmentY="Bottom">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Gray" Thickness="10" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>

Ejemplo
En el ejemplo siguiente se alinea el contenido de un DrawingBrush a la esquina superior izquierda de su mosaico
estableciendo la AlignmentX propiedad Left y el AlignmentY propiedad Top. También establece la Viewport y
TileMode de la DrawingBrush para generar un modelo de mosaico. El ejemplo genera el siguiente resultado.

Patrón de mosaico con el contenido alineado en la parte superior izquierda en el mosaico base
La ilustración destaca el mosaico base, por lo que puede ver cómo se alinea el contenido. Tenga en cuenta que el
AlignmentX configuración no tiene ningún efecto porque el contenido de la DrawingBrush rellena al completo el
mosaico base horizontalmente.
//
// Create a TileBrush that generates a
// tiled pattern and align its
// content to the top-left of its tile.
//
DrawingBrush tiledTopLeftAlignedTileBrush = new DrawingBrush();
tiledTopLeftAlignedTileBrush.AlignmentX = AlignmentX.Left;
tiledTopLeftAlignedTileBrush.AlignmentY = AlignmentY.Top;
tiledTopLeftAlignedTileBrush.Stretch = Stretch.Uniform;

// Set the brush's Viewport and TileMode to produce a


// tiled pattern.
tiledTopLeftAlignedTileBrush.Viewport = new Rect(0, 0, 0.25, 0.5);
tiledTopLeftAlignedTileBrush.TileMode = TileMode.Tile;

// Define the brush's content.


tiledTopLeftAlignedTileBrush.Drawing = ellipseDrawing;

// Use the brush to paint a rectangle.


Rectangle rectangle3 = new Rectangle();
rectangle3.Width = 150;
rectangle3.Height = 150;
rectangle3.Stroke = Brushes.Black;
rectangle3.StrokeThickness = 2;
rectangle3.Margin = new Thickness(20);
rectangle3.Fill = tiledTopLeftAlignedTileBrush;

'
' Create a TileBrush that generates a
' tiled pattern and align its
' content to the top-left of its tile.
'
Dim tiledTopLeftAlignedTileBrush As New DrawingBrush()
With tiledTopLeftAlignedTileBrush
.AlignmentX = AlignmentX.Left
.AlignmentY = AlignmentY.Top
.Stretch = Stretch.Uniform

' Set the brush's Viewport and TileMode to produce a


' tiled pattern.
.Viewport = New Rect(0, 0, 0.25, 0.5)
.TileMode = TileMode.Tile

' Define the brush's content.


.Drawing = ellipseDrawing
End With

' Use the brush to paint a rectangle.


Dim rectangle3 As New Rectangle()
With rectangle3
.Width = 150
.Height = 150
.Stroke = Brushes.Black
.StrokeThickness = 2
.Margin = New Thickness(20)
.Fill = tiledTopLeftAlignedTileBrush
End With
<Rectangle
Width="150" Height="150"
Stroke="Black" StrokeThickness="2"
Margin="20">
<Rectangle.Fill>

<!-- This brush's content is aligned to the top left


of its tile. -->
<DrawingBrush
Stretch="Uniform"
Viewport="0,0,0.25,0.5"
TileMode="Tile"
AlignmentX="Left"
AlignmentY="Top">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Gray" Thickness="10" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>

Ejemplo
En el ejemplo final se alinea el contenido de un mosaico DrawingBrush a la esquina inferior derecha de su mosaico
base estableciendo la AlignmentX propiedad Right y el AlignmentY propiedad Bottom. El ejemplo genera el
siguiente resultado.

Patrón de mosaico con el contenido alineado en la parte inferior derecha en el mosaico base
Nuevamente, el AlignmentX configuración no tiene ningún efecto porque el contenido de la DrawingBrush rellena
al completo el mosaico base horizontalmente.
//
// Create a TileBrush and align its
// content to the bottom-right of its tile.
//
DrawingBrush bottomRightAlignedTileBrush = new DrawingBrush();
bottomRightAlignedTileBrush.AlignmentX = AlignmentX.Right;
bottomRightAlignedTileBrush.AlignmentY = AlignmentY.Bottom;
bottomRightAlignedTileBrush.Stretch = Stretch.None;

// Define the brush's content.


bottomRightAlignedTileBrush.Drawing = ellipseDrawing;

// Use the brush to paint a rectangle.


Rectangle rectangle2 = new Rectangle();
rectangle2.Width = 150;
rectangle2.Height = 150;
rectangle2.Stroke = Brushes.Red;
rectangle2.StrokeThickness = 2;
rectangle2.Margin = new Thickness(20);
rectangle2.Fill = bottomRightAlignedTileBrush;

'
' Create a TileBrush and align its
' content to the bottom-right of its tile.
'
Dim bottomRightAlignedTileBrush As New DrawingBrush()
With bottomRightAlignedTileBrush
.AlignmentX = AlignmentX.Right
.AlignmentY = AlignmentY.Bottom
.Stretch = Stretch.None

' Define the brush's content.


.Drawing = ellipseDrawing
End With

' Use the brush to paint a rectangle.


Dim rectangle2 As New Rectangle()
With rectangle2
.Width = 150
.Height = 150
.Stroke = Brushes.Red
.StrokeThickness = 2
.Margin = New Thickness(20)
.Fill = bottomRightAlignedTileBrush
End With
<Rectangle
Width="150" Height="150"
Stroke="Red" StrokeThickness="2"
Margin="20">
<Rectangle.Fill>

<!-- This brush's content is aligned to the bottom right


of its tile. -->
<DrawingBrush
Stretch="None"
AlignmentX="Right"
AlignmentY="Bottom">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Gray" Thickness="10" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>

Los ejemplos usan DrawingBrush objetos para demostrar cómo el AlignmentX y AlignmentY se usan las
propiedades. Estas propiedades se comportan exactamente igual para todos los pinceles en mosaicos:
DrawingBrush, ImageBrush, y VisualBrush. Para más información sobre los pinceles en mosaicos, vea Pintar con
imágenes, dibujos y elementos visuales.

Vea también
DrawingBrush
ImageBrush
VisualBrush
Pintar con imágenes, dibujos y elementos visuales
Procedimiento Establecer el tamaño del mosaico de
un TileBrush
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo establecer el tamaño del mosaico para un TileBrush. De forma predeterminada,
un TileBrush genera un mosaico único que rellena completamente el área que se está pintando. Puede invalidar
este comportamiento estableciendo el Viewport y ViewportUnits propiedades.
El Viewport propiedad especifica el tamaño del mosaico para un TileBrush. De forma predeterminada, el valor de
la Viewport propiedad es relativo al tamaño del área que se está pintando. Para realizar la Viewport propiedad
especificar un tamaño de mosaico absoluto, establezca el ViewportUnits propiedad Absolute.

Ejemplo
En el ejemplo siguiente se usa un ImageBrush, un tipo de TileBrush, para pintar un rectángulo con mosaicos. El
ejemplo establece cada mosaico al 50 por ciento al 50 por ciento del área de salida (rectángulo). Como resultado,
el rectángulo se pinta con cuatro proyecciones de la imagen.
La siguiente ilustración muestra la salida que genera el ejemplo:

//
// Create an ImageBrush and set the size of each
// tile to 50% by 50% of the area being painted.
//
ImageBrush relativeTileSizeImageBrush = new ImageBrush();
relativeTileSizeImageBrush.ImageSource =
new BitmapImage(new Uri(@"sampleImages\cherries_larger.jpg", UriKind.Relative));
relativeTileSizeImageBrush.TileMode = TileMode.Tile;

// Specify the size of the base tile.


// By default, the size of the Viewport is
// relative to the area being painted,
// so a value of 0.5 indicates 50% of the output
// area.
relativeTileSizeImageBrush.Viewport = new Rect(0, 0, 0.5, 0.5);

// Create a rectangle and paint it with the ImageBrush.


Rectangle relativeTileSizeExampleRectangle = new Rectangle();
relativeTileSizeExampleRectangle.Width = 200;
relativeTileSizeExampleRectangle.Height = 150;
relativeTileSizeExampleRectangle.Stroke = Brushes.LimeGreen;
relativeTileSizeExampleRectangle.StrokeThickness = 1;
relativeTileSizeExampleRectangle.Fill = relativeTileSizeImageBrush;
El ejemplo siguiente se crea un ImageBrush, establece su Viewport a 0,0,25,25 y su ViewportUnits a Absolutey lo
usa para pintar otro rectángulo. Como resultado, el pincel genera iconos que tienen un ancho de 25 píxeles y un
alto de 25 píxeles.
La siguiente ilustración muestra la salida que genera el ejemplo:

//
// Create an ImageBrush and set the size of each
// tile to 25 by 25 pixels.
//
ImageBrush absoluteTileSizeImageBrush = new ImageBrush();
absoluteTileSizeImageBrush.ImageSource =
new BitmapImage(new Uri(@"sampleImages\cherries_larger.jpg", UriKind.Relative));
absoluteTileSizeImageBrush.TileMode = TileMode.Tile;

// Specify that the Viewport is to be interpreted as


// an absolute value.
absoluteTileSizeImageBrush.ViewportUnits = BrushMappingMode.Absolute;

// Set the size of the base tile. Had we left ViewportUnits set
// to RelativeToBoundingBox (the default value),
// each tile would be 25 times the size of the area being
// painted. Because ViewportUnits is set to Absolute,
// the following line creates tiles that are 25 by 25 pixels.
absoluteTileSizeImageBrush.Viewport = new Rect(0, 0, 25, 25);

// Create a rectangle and paint it with the ImageBrush.


Rectangle absoluteTileSizeExampleRectangle = new Rectangle();
absoluteTileSizeExampleRectangle.Width = 200;
absoluteTileSizeExampleRectangle.Height = 150;
absoluteTileSizeExampleRectangle.Stroke = Brushes.LimeGreen;
absoluteTileSizeExampleRectangle.StrokeThickness = 1;
absoluteTileSizeExampleRectangle.Fill = absoluteTileSizeImageBrush;

Los ejemplos anteriores forman parte de un ejemplo mayor. Para obtener un ejemplo completo, vea ejemplo de
ImageBrush.
Aunque este ejemplo usa el ImageBrush (clase), el Viewport y ViewportUnits propiedades se comportan
exactamente igual para los demás TileBrush objetos, es decir, para DrawingBrush y VisualBrush. Para obtener más
información acerca de ImageBrush y el otro TileBrush objetos, vea pintar con imágenes, dibujos y elementos
visuales.

Vea también
TileBrush
Pintar con imágenes, dibujos y elementos visuales
Crear patrones de mosaico diferentes con un objeto TileBrush
Procedimiento Transformar un pincel
23/10/2019 • 4 minutes to read • Edit Online

En este ejemplo se muestra cómo transformar Brush objetos mediante el uso de sus dos propiedades de
transformación: RelativeTransform y Transform.
Los ejemplos siguientes usan una RotateTransform para girar el contenido de un ImageBrush 45 grados.
La siguiente ilustración muestra el ImageBrush sin un RotateTransform, con el RotateTransform aplicado a la
RelativeTransform propiedad y con el RotateTransform aplicado a la Transform propiedad.

Ejemplo
El primer ejemplo se aplica un RotateTransform a la RelativeTransform propiedad de un ImageBrush. El CenterX y
CenterY las propiedades de un RotateTransform objeto se establecen en 0,5, que es la coordenada relativa del
punto central de este contenido. Como resultado, el ImageBrush contenido gira sobre su centro.
//
// Create an ImageBrush with a relative transform and
// use it to paint a rectangle.
//
ImageBrush relativeTransformImageBrush = new ImageBrush();
relativeTransformImageBrush.ImageSource =
new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative));

// Create a 45 rotate transform about the brush's center


// and apply it to the brush's RelativeTransform property.
RotateTransform aRotateTransform = new RotateTransform();
aRotateTransform.CenterX = 0.5;
aRotateTransform.CenterY = 0.5;
aRotateTransform.Angle = 45;
relativeTransformImageBrush.RelativeTransform = aRotateTransform;

// Use the brush to paint a rectangle.


Rectangle relativeTransformImageBrushRectangle = new Rectangle();
relativeTransformImageBrushRectangle.Width = 175;
relativeTransformImageBrushRectangle.Height = 90;
relativeTransformImageBrushRectangle.Stroke = Brushes.Black;
relativeTransformImageBrushRectangle.Fill = relativeTransformImageBrush;

'
' Create an ImageBrush with a relative transform and
' use it to paint a rectangle.
'
Dim relativeTransformImageBrush As New ImageBrush()
relativeTransformImageBrush.ImageSource = New BitmapImage(New Uri("sampleImages\pinkcherries.jpg",
UriKind.Relative))

' Create a 45 rotate transform about the brush's center


' and apply it to the brush's RelativeTransform property.
Dim aRotateTransform As New RotateTransform()
aRotateTransform.CenterX = 0.5
aRotateTransform.CenterY = 0.5
aRotateTransform.Angle = 45
relativeTransformImageBrush.RelativeTransform = aRotateTransform

' Use the brush to paint a rectangle.


Dim relativeTransformImageBrushRectangle As New Rectangle()
relativeTransformImageBrushRectangle.Width = 175
relativeTransformImageBrushRectangle.Height = 90
relativeTransformImageBrushRectangle.Stroke = Brushes.Black
relativeTransformImageBrushRectangle.Fill = relativeTransformImageBrush

<Rectangle Width="175" Height="90" Stroke="Black">


<Rectangle.Fill>
<ImageBrush ImageSource="sampleImages\pinkcherries.jpg">
<ImageBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="45" />
</ImageBrush.RelativeTransform>
</ImageBrush>
</Rectangle.Fill>
</Rectangle>

El segundo ejemplo también se aplica un RotateTransform a un ImageBrush; sin embargo, este ejemplo se usa el
Transform propiedad en lugar de la RelativeTransform propiedad.
Para girar el pincel sobre su centro, el ejemplo establece la CenterX y CenterY propiedades de la RotateTransform
objeto en coordenadas absolutas. Como el pincel pinta un rectángulo de 175 x 90 píxeles, el punto central del
rectángulo es (87,5, 45).

//
// Create an ImageBrush with a transform and
// use it to paint a rectangle.
//
ImageBrush transformImageBrush = new ImageBrush();
transformImageBrush.ImageSource =
new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative));

// Create a 45 rotate transform about the brush's center


// and apply it to the brush's Transform property.
RotateTransform anotherRotateTransform = new RotateTransform();
anotherRotateTransform.CenterX = 87.5;
anotherRotateTransform.CenterY = 45;
anotherRotateTransform.Angle = 45;
transformImageBrush.Transform = anotherRotateTransform;

// Use the brush to paint a rectangle.


Rectangle transformImageBrushRectangle = new Rectangle();
transformImageBrushRectangle.Width = 175;
transformImageBrushRectangle.Height = 90;
transformImageBrushRectangle.Stroke = Brushes.Black;
transformImageBrushRectangle.Fill = transformImageBrush;

'
' Create an ImageBrush with a transform and
' use it to paint a rectangle.
'
Dim transformImageBrush As New ImageBrush()
transformImageBrush.ImageSource = New BitmapImage(New Uri("sampleImages\pinkcherries.jpg", UriKind.Relative))

' Create a 45 rotate transform about the brush's center


' and apply it to the brush's Transform property.
Dim anotherRotateTransform As New RotateTransform()
anotherRotateTransform.CenterX = 87.5
anotherRotateTransform.CenterY = 45
anotherRotateTransform.Angle = 45
transformImageBrush.Transform = anotherRotateTransform

' Use the brush to paint a rectangle.


Dim transformImageBrushRectangle As New Rectangle()
transformImageBrushRectangle.Width = 175
transformImageBrushRectangle.Height = 90
transformImageBrushRectangle.Stroke = Brushes.Black
transformImageBrushRectangle.Fill = transformImageBrush

<Rectangle Width="175" Height="90" Stroke="Black">


<Rectangle.Fill>
<ImageBrush ImageSource="sampleImages\pinkcherries.jpg">
<ImageBrush.Transform>
<RotateTransform CenterX="87.5" CenterY="45" Angle="45" />
</ImageBrush.Transform>
</ImageBrush>
</Rectangle.Fill>
</Rectangle>

Para obtener una descripción de cómo el RelativeTransform y Transform propiedades de trabajo, consulte el
información general sobre la transformación de pinceles.
Para ver el ejemplo completo, consulte Brushes Sample (Ejemplo de pinceles). Para más información sobre los
pinceles, consulte Información general sobre el dibujo con colores sólidos y degradados.

Vea también
Información general sobre la transformación de pinceles
Información general sobre el dibujo con colores sólidos y degradados
Información general sobre transformaciones
Procedimiento Usar colores del sistema en un
degradado
23/10/2019 • 2 minutes to read • Edit Online

Para utilizar un color del sistema en un degradado, se utiliza el <SystemColor > Color y <SystemColor >
ColorKey propiedades estáticas de la SystemColors clase para obtener una referencia al color, donde
<SystemColor > es el nombre del color del sistema deseado. Use la <SystemColor > propiedades de ColorKey
cuando desee crear una referencia dinámica que se actualiza automáticamente a medida que cambia el tema del
sistema. En caso contrario, use el <SystemColor > propiedades de Color.

Ejemplo
En el siguiente ejemplo se usan recursos de color del sistema dinámico para crear un degradado.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Dynamic System Colors Example" Background="White">
<StackPanel Margin="20">

<!-- Uses dynamic references to system colors to set


the colors of gradient stops.
If these system colors change while this application
is running, the gradient will be updated
automatically. -->
<Button Content="Hello, World!">
<Button.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0"
Color="{DynamicResource {x:Static SystemColors.DesktopColorKey}}" />
<GradientStop Offset="1.0"
Color="{DynamicResource {x:Static SystemColors.ControlLightLightColorKey}}" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Button.Background>
</Button>

</StackPanel>
</Page>

En el siguiente ejemplo se usan recursos de color del sistema estático para crear un degradado.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Static System Colors Example" Background="White">
<StackPanel Margin="20">

<!-- Uses static references to system colors to set


the colors of gradient stops.
If these system colors change while this application
is running, this button will not be updated until
the page is loaded again. -->
<Button Content="Hello, World!">
<Button.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0"
Color="{x:Static SystemColors.DesktopColor}" />
<GradientStop Offset="1.0"
Color="{x:Static SystemColors.ControlLightLightColor}" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Button.Background>
</Button>

</StackPanel>
</Page>

Vea también
SystemColors
Pintar un área con un pincel del sistema
Información general sobre el dibujo con colores sólidos y degradados
Dibujos
23/10/2019 • 2 minutes to read • Edit Online

Drawing los objetos se usan para dibujar con eficacia formas, imágenes o texto. Dibujos se utilizan al pintar con un
DrawingBrush o programación con Visual objetos.

En esta sección
Información general sobre objetos Drawing
Temas "Cómo..."

Vea también
Drawing
Imágenes y gráficos 2D
Información general sobre la representación de gráficos en WPF
Información general sobre formas y dibujo básico en WPF
Gráficos y multimedia
Información general sobre objetos Drawing
04/11/2019 • 22 minutes to read • Edit Online

En este tema se presentan Drawing objetos y se describe cómo usarlos para dibujar eficazmente formas,
mapas de bits, texto y elementos multimedia. Utilice Drawing objetos al crear imágenes prediseñadas, pintar
con un DrawingBrusho usar Visual objetos.

¿Qué es un objeto Drawing?


Un objeto Drawing describe el contenido visible, como una forma, un mapa de bits, un vídeo o una línea de
texto. Distintos tipos de dibujo describen tipos de contenido diferentes. La siguiente lista muestra los distintos
tipos de objetos de dibujo.
GeometryDrawing: dibuja una forma.
ImageDrawing: dibuja una imagen.
GlyphRunDrawing: dibuja texto.
VideoDrawing: reproduce un archivo de audio o de vídeo.
DrawingGroup: dibuja otros dibujos. Use un grupo de dibujo para combinar otros dibujos en un único
dibujo compuesto.
Drawing objetos son versátiles; Hay muchas maneras de utilizar un objeto de Drawing.
Puede mostrarlo como una imagen mediante un DrawingImage y un control Image.
Puede utilizarlo con un DrawingBrush para pintar un objeto, como el Background de una Page.
Puede utilizarlo para describir la apariencia de una DrawingVisual.
Se puede utilizar para enumerar el contenido de un Visual.
WPF ofrece otros tipos de objetos capaces de dibujar formas, mapas de bits, texto y elementos multimedia. Por
ejemplo, también puede usar objetos Shape para dibujar formas y el control MediaElement proporciona otra
manera de agregar vídeo a la aplicación. ¿Cuándo se debe usar Drawing objetos? Cuando se pueden sacrificar
características de nivel de marco para obtener ventajas de rendimiento o cuando se necesitan Freezable
características. Dado que Drawing objetos no admiten el diseño, la entrada y el foco, proporcionan ventajas de
rendimiento que hacen que sean ideales para describir los terrenos, imágenes prediseñadas y dibujos de bajo
nivel con objetos Visual.
Dado que son un tipo Freezable objeto, Drawing objetos obtienen varias características especiales, entre las
que se incluyen las siguientes: se pueden declarar como recursos, compartirse entre varios objetos, convertirse
en de solo lectura para mejorar el rendimiento, clonarse y realizarse seguro para subprocesos. Para obtener
más información sobre las diferentes características proporcionadas por los objetos Freezable, consulte la
información general sobre objetos Freezable.

Dibujar una forma


Para dibujar una forma, se usa un GeometryDrawing. La propiedad Geometry de un dibujo de geometría
describe la forma que se va a dibujar, su propiedad Brush describe cómo se debe pintar el interior de la forma
y su propiedad Pen describe cómo debe dibujarse su contorno.
En el ejemplo siguiente se usa un GeometryDrawing para dibujar una forma. La forma se describe mediante
un GeometryGroup y dos objetos EllipseGeometry. El interior de la forma se pinta con un
LinearGradientBrush y su contorno se dibuja con un PenBlack.
En este ejemplo se crea el siguiente GeometryDrawing.

GeometryDrawing

//
// Create the Geometry to draw.
//
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(
new EllipseGeometry(new Point(50,50), 45, 20)
);
ellipses.Children.Add(
new EllipseGeometry(new Point(50, 50), 20, 45)
);

//
// Create a GeometryDrawing.
//
GeometryDrawing aGeometryDrawing = new GeometryDrawing();
aGeometryDrawing.Geometry = ellipses;

// Paint the drawing with a gradient.


aGeometryDrawing.Brush =
new LinearGradientBrush(
Colors.Blue,
Color.FromRgb(204,204,255),
new Point(0,0),
new Point(1,1));

// Outline the drawing with a solid color.


aGeometryDrawing.Pen = new Pen(Brushes.Black, 10);
<GeometryDrawing>
<GeometryDrawing.Geometry>

<!-- Create a composite shape. -->


<GeometryGroup>
<EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" />
<EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>

<!-- Paint the drawing with a gradient. -->


<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Blue" />
<GradientStop Offset="1.0" Color="#CCCCFF" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Pen>

<!-- Outline the drawing with a solid color. -->


<Pen Thickness="10" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>

Para obtener el ejemplo completo, vea Create a GeometryDrawing (Cómo: Crear un objeto
GeometryDrawing).
Otras clases de Geometry, como PathGeometry permiten crear formas más complejas creando curvas y arcos.
Para obtener más información sobre los objetos de Geometry, consulte la información general sobre
geometría.
Para obtener más información sobre otras formas de dibujar formas que no usan Drawing objetos, vea
información general sobre formas y dibujo básico en WPF.

Dibujar un objeto Image


Para dibujar una imagen, use un ImageDrawing. La propiedad ImageSource de un objeto ImageDrawing
describe la imagen que se va a dibujar y su propiedad Rect define la región donde se dibuja la imagen.
En el ejemplo siguiente se dibuja una imagen en un rectángulo situado en (75,75) que ocupa 100 por 100
píxeles. En la ilustración siguiente se muestra el ImageDrawing creado en el ejemplo. Se ha agregado un borde
gris para mostrar los límites del ImageDrawing.

ImageDrawing de 100 por 100

// Create a 100 by 100 image with an upper-left point of (75,75).


ImageDrawing bigKiwi = new ImageDrawing();
bigKiwi.Rect = new Rect(75, 75, 100, 100);
bigKiwi.ImageSource = new BitmapImage(
new Uri(@"sampleImages\kiwi.png", UriKind.Relative));
<!-- The Rect property specifies that the image only fill a 100 by 100
rectangular area. -->
<ImageDrawing Rect="75,75,100,100" ImageSource="sampleImages\kiwi.png"/>

Para más información sobre las imágenes, Información general sobre imágenes.

Reproducir elementos multimedia (solo código)


NOTE
Aunque puede declarar un VideoDrawing en Lenguaje XAML (Extensible Application Markup Language), solo puede
cargar y reproducir sus medios mediante código. Para reproducir vídeo en Lenguaje XAML (Extensible Application
Markup Language), use un MediaElement en su lugar.

Para reproducir un archivo de audio o vídeo, se usa un VideoDrawing y un MediaPlayer. Hay dos maneras de
cargar y reproducir elementos multimedia. La primera es usar una MediaPlayer y una VideoDrawing por sí
misma, y la segunda consiste en crear su propio MediaTimeline para usarlo con los MediaPlayer y
VideoDrawing.

NOTE
Al distribuir elementos multimedia con la aplicación, no puede utilizar un archivo multimedia como recurso del proyecto,
como haría con una imagen. En el archivo de proyecto, debe establecer en su lugar el tipo de elemento multimedia en
Content y establecer CopyToOutputDirectory en PreserveNewest o Always .

Para reproducir archivos multimedia sin crear su propio MediaTimeline, realice los pasos siguientes.
1. Crear un objeto MediaPlayer.

MediaPlayer player = new MediaPlayer();

2. Use el método Open para cargar el archivo multimedia.

player.Open(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));

3. Creará un control VideoDrawing.

VideoDrawing aVideoDrawing = new VideoDrawing();

4. Especifique el tamaño y la ubicación para dibujar el medio estableciendo la propiedad Rect de la


VideoDrawing.

aVideoDrawing.Rect = new Rect(0, 0, 100, 100);

5. Establezca la propiedad Player de la VideoDrawing con el MediaPlayer que creó.

aVideoDrawing.Player = player;

6. Use el método Play del MediaPlayer para empezar a reproducir el medio.


// Play the video once.
player.Play();

En el ejemplo siguiente se usa un VideoDrawing y un MediaPlayer para reproducir un archivo de vídeo una
vez.

//
// Create a VideoDrawing.
//
MediaPlayer player = new MediaPlayer();

player.Open(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));

VideoDrawing aVideoDrawing = new VideoDrawing();

aVideoDrawing.Rect = new Rect(0, 0, 100, 100);

aVideoDrawing.Player = player;

// Play the video once.


player.Play();

Para obtener un control de tiempo adicional sobre los medios, utilice un MediaTimeline con los objetos
MediaPlayer y VideoDrawing. El MediaTimeline le permite especificar si el vídeo debe repetirse. Para usar un
MediaTimeline con un VideoDrawing, realice los pasos siguientes:
1. Declare el MediaTimeline y establezca sus comportamientos de control de tiempo.

// Create a MediaTimeline.
MediaTimeline mTimeline =
new MediaTimeline(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));

// Set the timeline to repeat.


mTimeline.RepeatBehavior = RepeatBehavior.Forever;

2. Cree una MediaClock a partir de la MediaTimeline.

// Create a clock from the MediaTimeline.


MediaClock mClock = mTimeline.CreateClock();

3. Cree una MediaPlayer y utilice el MediaClock para establecer su propiedad Clock.

MediaPlayer repeatingVideoDrawingPlayer = new MediaPlayer();


repeatingVideoDrawingPlayer.Clock = mClock;

4. Cree un VideoDrawing y asigne el MediaPlayer a la propiedad Player del VideoDrawing.

VideoDrawing repeatingVideoDrawing = new VideoDrawing();


repeatingVideoDrawing.Rect = new Rect(150, 0, 100, 100);
repeatingVideoDrawing.Player = repeatingVideoDrawingPlayer;

En el ejemplo siguiente se usa un MediaTimeline con un MediaPlayer y un VideoDrawing para reproducir un


vídeo repetidamente.
//
// Create a VideoDrawing that repeats.
//

// Create a MediaTimeline.
MediaTimeline mTimeline =
new MediaTimeline(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));

// Set the timeline to repeat.


mTimeline.RepeatBehavior = RepeatBehavior.Forever;

// Create a clock from the MediaTimeline.


MediaClock mClock = mTimeline.CreateClock();

MediaPlayer repeatingVideoDrawingPlayer = new MediaPlayer();


repeatingVideoDrawingPlayer.Clock = mClock;

VideoDrawing repeatingVideoDrawing = new VideoDrawing();


repeatingVideoDrawing.Rect = new Rect(150, 0, 100, 100);
repeatingVideoDrawing.Player = repeatingVideoDrawingPlayer;

Tenga en cuenta que, cuando se usa un MediaTimeline, se usa la ClockController interactiva devuelta desde la
propiedad Controller del MediaClock para controlar la reproducción multimedia en lugar de los métodos
interactivos de MediaPlayer.

Dibujar texto
Para dibujar texto, se usa un GlyphRunDrawing y un GlyphRun. En el ejemplo siguiente se usa un
GlyphRunDrawing para dibujar el texto "Hola mundo".

GlyphRun theGlyphRun = new GlyphRun(


new GlyphTypeface(new Uri(@"C:\WINDOWS\Fonts\TIMES.TTF")),
0,
false,
13.333333333333334,
new ushort[]{43, 72, 79, 79, 82, 3, 58, 82, 85, 79, 71},
new Point(0, 12.29),
new double[]{
9.62666666666667, 7.41333333333333, 2.96,
2.96, 7.41333333333333, 3.70666666666667,
12.5866666666667, 7.41333333333333,
4.44, 2.96, 7.41333333333333},
null,
null,
null,
null,
null,
null

);

GlyphRunDrawing gDrawing = new GlyphRunDrawing(Brushes.Black, theGlyphRun);


<GlyphRunDrawing ForegroundBrush="Black">
<GlyphRunDrawing.GlyphRun>
<GlyphRun
CaretStops="{x:Null}"
ClusterMap="{x:Null}"
IsSideways="False"
GlyphOffsets="{x:Null}"
GlyphIndices="43 72 79 79 82 3 58 82 85 79 71"
BaselineOrigin="0,12.29"
FontRenderingEmSize="13.333333333333334"
DeviceFontName="{x:Null}"
AdvanceWidths="9.62666666666667 7.41333333333333 2.96 2.96 7.41333333333333 3.70666666666667
12.5866666666667 7.41333333333333 4.44 2.96 7.41333333333333"
BidiLevel="0">
<GlyphRun.GlyphTypeface>
<GlyphTypeface FontUri="C:\WINDOWS\Fonts\TIMES.TTF" />
</GlyphRun.GlyphTypeface>
</GlyphRun>
</GlyphRunDrawing.GlyphRun>
</GlyphRunDrawing>

Un GlyphRun es un objeto de bajo nivel diseñado para su uso con escenarios de impresión y presentación de
documentos de formato fijo. Una manera más sencilla de dibujar texto en la pantalla es usar un Label o un
TextBlock. Para obtener más información acerca de GlyphRun, vea la Introducción al objeto GlyphRun y al
elemento glyphs .

Dibujos compuestos
Un DrawingGroup permite combinar varios dibujos en un solo dibujo compuesto. Mediante el uso de un
DrawingGroup, puede combinar formas, imágenes y texto en un solo Drawing objeto.
En el ejemplo siguiente se usa un DrawingGroup para combinar dos objetos GeometryDrawing y un objeto
ImageDrawing. Este ejemplo produce el siguiente resultado:

Un dibujo compuesto
//
// Create three drawings.
//
GeometryDrawing ellipseDrawing =
new GeometryDrawing(
new SolidColorBrush(Color.FromArgb(102, 181, 243, 20)),
new Pen(Brushes.Black, 4),
new EllipseGeometry(new Point(50,50), 50, 50)
);

ImageDrawing kiwiPictureDrawing =
new ImageDrawing(
new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative)),
new Rect(50,50,100,100));

GeometryDrawing ellipseDrawing2 =
new GeometryDrawing(
new SolidColorBrush(Color.FromArgb(102,181,243,20)),
new Pen(Brushes.Black, 4),
new EllipseGeometry(new Point(150, 150), 50, 50)
);

// Create a DrawingGroup to contain the drawings.


DrawingGroup aDrawingGroup = new DrawingGroup();
aDrawingGroup.Children.Add(ellipseDrawing);
aDrawingGroup.Children.Add(kiwiPictureDrawing);
aDrawingGroup.Children.Add(ellipseDrawing2);

<DrawingGroup>

<GeometryDrawing Brush="#66B5F314">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="4" />
</GeometryDrawing.Pen>
</GeometryDrawing>
<ImageDrawing ImageSource="sampleImages\kiwi.png" Rect="50,50,100,100"/>
<GeometryDrawing Brush="#66B5F314">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="150,150" RadiusX="50" RadiusY="50"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="4" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingGroup>

Un DrawingGroup también le permite aplicar máscaras de opacidad, transformaciones, efectos de imagen y


otras operaciones a su contenido. las operaciones de DrawingGroup se aplican en el orden siguiente:
OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSety Transform.
En la ilustración siguiente se muestra el orden en que se aplican las operaciones de DrawingGroup.
Orden de las operaciones de DrawingGroup
En la tabla siguiente se describen las propiedades que se pueden utilizar para manipular el contenido de un
objeto DrawingGroup.

PROPIEDAD. DESCRIPCIÓN ILUSTRACIÓN

OpacityMask Modifica la opacidad de las partes


seleccionadas del contenido del
DrawingGroup. Para obtener un
ejemplo, vea How to: Control the
Opacity of a Drawing (Cómo:
Controlar la opacidad de un dibujo).

Opacity Cambia uniformemente la opacidad


del contenido del DrawingGroup.
Utilice esta propiedad para hacer que
un Drawing sea transparente o
parcialmente transparente. Para
obtener un ejemplo, vea How to:
Apply an Opacity Mask to a Drawing
(Cómo: Aplicar una máscara de
opacidad a un dibujo).

BitmapEffect Aplica un BitmapEffect al contenido


del DrawingGroup. Para obtener un
ejemplo, vea How to: Apply a
BitmapEffect to a Drawing (Cómo:
Aplicar un objeto BitmapEffect a un
dibujo).

ClipGeometry Recorta el contenido de la


DrawingGroup a una región que se
describe mediante un Geometry. Para
obtener un ejemplo, vea How to: Clip
a Drawing (Cómo: Recortar un dibujo).
PROPIEDAD. DESCRIPCIÓN ILUSTRACIÓN

GuidelineSet Ajusta los píxeles independientes del


dispositivo a los píxeles del dispositivo
según las directrices especificadas. Esta
propiedad resulta útil para garantizar
que los gráficos muy detallados se
representan nítidamente en pantallas
de baja resolución. Para obtener un
ejemplo, vea Apply a GuidelineSet to a
Drawing (Aplicar un objeto
GuidelineSet a un dibujo).

Transform Transforma el contenido de la


DrawingGroup. Para obtener un
ejemplo, vea How to: Apply a
Transform to a Drawing (Cómo:
Aplicar una transformación a un
dibujo).

Mostrar un dibujo como imagen


Para mostrar un Drawing con un control Image, utilice un DrawingImage como Source del control Image y
establezca la propiedad DrawingImage del objeto DrawingImage.Drawing en el dibujo que desea mostrar.
En el ejemplo siguiente se usa un DrawingImage y un control Image para mostrar un GeometryDrawing. Este
ejemplo produce el siguiente resultado:

DrawingImage

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SDKSample
{
public class DrawingImageExample : Page
{

public DrawingImageExample()
{

//
// Create the Geometry to draw.
//
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(
new EllipseGeometry(new Point(50,50), 45, 20)
);
ellipses.Children.Add(
new EllipseGeometry(new Point(50, 50), 20, 45)
);
//
// Create a GeometryDrawing.
//
GeometryDrawing aGeometryDrawing = new GeometryDrawing();
aGeometryDrawing.Geometry = ellipses;

// Paint the drawing with a gradient.


aGeometryDrawing.Brush =
new LinearGradientBrush(
Colors.Blue,
Color.FromRgb(204,204,255),
new Point(0,0),
new Point(1,1));

// Outline the drawing with a solid color.


aGeometryDrawing.Pen = new Pen(Brushes.Black, 10);

//
// Use a DrawingImage and an Image control
// to display the drawing.
//
DrawingImage geometryImage = new DrawingImage(aGeometryDrawing);

// Freeze the DrawingImage for performance benefits.


geometryImage.Freeze();

Image anImage = new Image();


anImage.Source = geometryImage;
anImage.HorizontalAlignment = HorizontalAlignment.Left;

//
// Place the image inside a border and
// add it to the page.
//
Border exampleBorder = new Border();
exampleBorder.Child = anImage;
exampleBorder.BorderBrush = Brushes.Gray;
exampleBorder.BorderThickness = new Thickness(1);
exampleBorder.HorizontalAlignment = HorizontalAlignment.Left;
exampleBorder.VerticalAlignment = VerticalAlignment.Top;
exampleBorder.Margin = new Thickness(10);

this.Margin = new Thickness(20);


this.Background = Brushes.White;
this.Content = exampleBorder;
}
}
}
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Background="White" Margin="20">

<Border BorderBrush="Gray" BorderThickness="1"


HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="10">

<!-- This image uses a Drawing object for its source. -->
<Image>
<Image.Source>
<DrawingImage PresentationOptions:Freeze="True">
<DrawingImage.Drawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" />
<EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Blue" />
<GradientStop Offset="1.0" Color="#CCCCFF" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Pen>
<Pen Thickness="10" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Border>

</Page>

Pintar un objeto con un dibujo


Un DrawingBrush es un tipo de pincel que pinta un área con un objeto de dibujo. Puede usarlo para pintar casi
cualquier objeto gráfico con un dibujo. La propiedad Drawing de una DrawingBrush describe su Drawing. Para
representar un Drawing con un DrawingBrush, agréguelo al pincel mediante la propiedad Drawing del pincel y
use el pincel para pintar un objeto gráfico, como un control o un panel.
En los ejemplos siguientes se usa un DrawingBrush para pintar el Fill de una Rectangle con un patrón creado a
partir de un GeometryDrawing. Este ejemplo produce el siguiente resultado:

Uso de GeometryDrawing con un objeto DrawingBrush

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SDKSample
{
public class DrawingBrushExample : Page
{

public DrawingBrushExample()
{

//
// Create the Geometry to draw.
//
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(
new EllipseGeometry(new Point(50,50), 45, 20)
);
ellipses.Children.Add(
new EllipseGeometry(new Point(50, 50), 20, 45)
);

//
// Create a GeometryDrawing.
//
GeometryDrawing aGeometryDrawing = new GeometryDrawing();
aGeometryDrawing.Geometry = ellipses;

// Paint the drawing with a gradient.


aGeometryDrawing.Brush =
new LinearGradientBrush(
Colors.Blue,
Color.FromRgb(204,204,255),
new Point(0,0),
new Point(1,1));

// Outline the drawing with a solid color.


aGeometryDrawing.Pen = new Pen(Brushes.Black, 10);

DrawingBrush patternBrush = new DrawingBrush(aGeometryDrawing);


patternBrush.Viewport = new Rect(0, 0, 0.25, 0.25);
patternBrush.TileMode = TileMode.Tile;
patternBrush.Freeze();

//
// Create an object to paint.
//
Rectangle paintedRectangle = new Rectangle();
paintedRectangle.Width = 100;
paintedRectangle.Height = 100;
paintedRectangle.Fill = patternBrush;

//
// Place the image inside a border and
// add it to the page.
//
Border exampleBorder = new Border();
exampleBorder.Child = paintedRectangle;
exampleBorder.BorderBrush = Brushes.Gray;
exampleBorder.BorderThickness = new Thickness(1);
exampleBorder.HorizontalAlignment = HorizontalAlignment.Left;
exampleBorder.VerticalAlignment = VerticalAlignment.Top;
exampleBorder.Margin = new Thickness(10);

this.Margin = new Thickness(20);


this.Background = Brushes.White;
this.Content = exampleBorder;
}
}
}
}

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Margin="20" Background="White">

<Border BorderBrush="Gray" BorderThickness="1"


HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="10">
<Rectangle Width="100" Height="100">
<Rectangle.Fill>
<DrawingBrush PresentationOptions:Freeze="True"
Viewport="0,0,0.25,0.25" TileMode="Tile">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" />
<EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Blue" />
<GradientStop Offset="1.0" Color="#CCCCFF" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Pen>
<Pen Thickness="10" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>

</Rectangle>
</Border>

</Page>

La clase DrawingBrush proporciona una variedad de opciones para ajustar y segmentar su contenido. Para
obtener más información sobre DrawingBrush, consulte la información general sobre el dibujo con imágenes,
dibujos y objetos visuales .

Representar un dibujo con un objeto Visual


Un DrawingVisual es un tipo de objeto visual diseñado para representar un dibujo. Una posibilidad para los
desarrolladores que quieran crear un entorno gráfico muy personalizado es trabajar directamente en la capa
visual, que no se describe en esta información general. Para más información, consulte la página de
información general Usar objetos DrawingVisual.

Objetos DrawingContext
La clase DrawingContext le permite rellenar un Visual o un Drawing con contenido visual. Muchos objetos
gráficos de nivel inferior usan una DrawingContext porque describe el contenido gráfico de forma muy eficaz.
Aunque los métodos de DrawingContext Draw parecen similares a los métodos de dibujo del tipo
System.Drawing.Graphics, son realmente diferentes. DrawingContext se usa con un sistema de gráficos de
modo retenido, mientras que el tipo de System.Drawing.Graphics se usa con un sistema de gráficos de modo
inmediato. Cuando se usa el comando Draw de un objeto DrawingContext, en realidad se almacena un
conjunto de instrucciones de representación (aunque el mecanismo de almacenamiento exacto depende del
tipo de objeto que proporciona el DrawingContext) que se utilizará posteriormente en el sistema de gráficos.
no está dibujando en la pantalla en tiempo real. Para obtener más información sobre cómo funciona el sistema
de gráficos de Windows Presentation Foundation (WPF ), consulte información general sobre la representación
de gráficos en WPF.
Nunca se crean instancias de un DrawingContextdirectamente; sin embargo, puede adquirir un contexto de
dibujo de determinados métodos, como DrawingGroup.Open y DrawingVisual.RenderOpen.

Enumerar el contenido de un objeto Visual


Además de sus otros usos, los objetos Drawing también proporcionan un modelo de objetos para enumerar el
contenido de un Visual.
En el ejemplo siguiente se usa el método GetDrawing para recuperar el valor DrawingGroup de un Visual y
enumerarlo.

public void RetrieveDrawing(Visual v)


{
DrawingGroup drawingGroup = VisualTreeHelper.GetDrawing(v);
EnumDrawingGroup(drawingGroup);
}

// Enumerate the drawings in the DrawingGroup.


public void EnumDrawingGroup(DrawingGroup drawingGroup)
{
DrawingCollection dc = drawingGroup.Children;

// Enumerate the drawings in the DrawingCollection.


foreach (Drawing drawing in dc)
{
// If the drawing is a DrawingGroup, call the function recursively.
if (drawing is DrawingGroup group)
{
EnumDrawingGroup(group);
}
else if (drawing is GeometryDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is ImageDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is GlyphRunDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is VideoDrawing)
{
// Perform action based on drawing type.
}
}
}
Vea también
Drawing
DrawingGroup
Imágenes y gráficos 2D
Pintar con imágenes, dibujos y elementos visuales
Información general sobre geometría
Información general sobre formas y dibujo básico en WPF
Información general sobre la representación de gráficos en WPF
Información general sobre objetos Freezable
Temas "Cómo..."
Temas "Cómo..." de dibujo
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección describen cómo usar Drawing objetos que se va a dibujar formas, imágenes o texto.

En esta sección
Aplicar un objeto GuidelineSet a un dibujo
Crear un dibujo compuesto
Crear un objeto GeometryDrawing
Dibujar una imagen usando un objeto ImageDrawing
Reproducir elementos multimedia con un objeto VideoDrawing
Usar un dibujo como el origen de una imagen

Vea también
Drawing
Información general sobre la representación de gráficos en WPF
Información general sobre formas y dibujo básico en WPF
Gráficos y multimedia
Procedimiento Aplicar un objeto GuidelineSet a un
dibujo
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo aplicar un GuidelineSet a un DrawingGroup.


El DrawingGroup clase es el único tipo de Drawing que tiene un GuidelineSet propiedad. Para aplicar un
GuidelineSet a otro tipo de Drawing, agréguela a un DrawingGroup y, a continuación, aplicar el GuidelineSet a su
DrawingGroup.

Ejemplo
En el ejemplo siguiente se crean dos DrawingGroup objetos que son casi idénticos; la única diferencia es: el
segundo DrawingGroup tiene un GuidelineSet y no el primero.
En la siguiente ilustración se muestra el resultado del ejemplo. Dado que la representación de las diferencias entre
los dos DrawingGroup objetos es muy sutil, se amplían partes de los dibujos.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SDKSample
{
/// <summary>
/// This example shows how to apply a GuidelineSet to
/// a drawing.
/// </summary>
public class DrawingGroupGuidelineSetExample : Page
{
public DrawingGroupGuidelineSetExample()
{

//
// Create a DrawingGroup
// that has no guideline set
//
//
GeometryDrawing drawing1 = new GeometryDrawing(
Brushes.Black,
null,
new RectangleGeometry(new Rect(0,20,30,80))
);

GeometryGroup whiteRectangles = new GeometryGroup();


whiteRectangles.Children.Add(new RectangleGeometry(new Rect(5.5, 25, 20, 20)));
whiteRectangles.Children.Add(new RectangleGeometry(new Rect(5.5, 50, 20, 20)));
whiteRectangles.Children.Add(new RectangleGeometry(new Rect(5.5, 75, 20, 20)));

GeometryDrawing drawing2 = new GeometryDrawing(


Brushes.White,
null,
whiteRectangles
);

// Create a DrawingGroup
DrawingGroup drawingGroupWithoutGuidelines = new DrawingGroup();
drawingGroupWithoutGuidelines.Children.Add(drawing1);
drawingGroupWithoutGuidelines.Children.Add(drawing2);

// Use an Image control and a DrawingImage to


// display the drawing.
DrawingImage drawingImage01 = new DrawingImage(drawingGroupWithoutGuidelines);

// Freeze the DrawingImage for performance benefits.


drawingImage01.Freeze();

Image image01 = new Image();


image01.Source = drawingImage01;
image01.Stretch = Stretch.None;
image01.HorizontalAlignment = HorizontalAlignment.Left;
image01.Margin = new Thickness(10);

//
// Create another DrawingGroup and apply
// a blur effect to it.
//

// Create a clone of the first DrawingGroup.


DrawingGroup drawingGroupWithGuidelines =
drawingGroupWithoutGuidelines.Clone();

// Create a guideline set.


GuidelineSet guidelines = new GuidelineSet();
guidelines.GuidelinesX.Add(5.5);
guidelines.GuidelinesX.Add(25.5);
guidelines.GuidelinesY.Add(25);
guidelines.GuidelinesY.Add(50);
guidelines.GuidelinesY.Add(75);

// Apply it to the drawing group.


drawingGroupWithGuidelines.GuidelineSet = guidelines;

// Use another Image control and DrawingImage


// to display the drawing.
DrawingImage drawingImage02 = new DrawingImage(drawingGroupWithGuidelines);

// Freeze the DrawingImage for performance benefits.


drawingImage02.Freeze();

Image image02 = new Image();


image02.Source = drawingImage02;
image02.Stretch = Stretch.None;
image02.HorizontalAlignment = HorizontalAlignment.Left;
image02.Margin = new Thickness(50, 10, 10, 10);

StackPanel mainPanel = new StackPanel();


StackPanel mainPanel = new StackPanel();
mainPanel.Orientation = Orientation.Horizontal;
mainPanel.HorizontalAlignment = HorizontalAlignment.Left;
mainPanel.Margin = new Thickness(20);
mainPanel.Children.Add(image01);
mainPanel.Children.Add(image02);

//
// Use a DrawingBrush to create a grid background.
//
GeometryDrawing backgroundRectangleDrawing =
new GeometryDrawing(
Brushes.White,
null,
new RectangleGeometry(new Rect(0,0,1,1))
);
PolyLineSegment backgroundLine1 = new PolyLineSegment();
backgroundLine1.Points.Add(new Point(1, 0));
backgroundLine1.Points.Add(new Point(1, 0.1));
backgroundLine1.Points.Add(new Point(0, 0.1));
PathFigure line1Figure = new PathFigure();
line1Figure.Segments.Add(backgroundLine1);
PathGeometry backgroundLine1Geometry = new PathGeometry();
backgroundLine1Geometry.Figures.Add(line1Figure);
GeometryDrawing backgroundLineDrawing1 = new GeometryDrawing(
new SolidColorBrush(Color.FromArgb(255,204,204,255)),
null,
backgroundLine1Geometry
);
PolyLineSegment backgroundLine2 = new PolyLineSegment();
backgroundLine2.Points.Add(new Point(0, 1));
backgroundLine2.Points.Add(new Point(0.1, 1));
backgroundLine2.Points.Add(new Point(0.1, 0));
PathFigure line2Figure = new PathFigure();
line2Figure.Segments.Add(backgroundLine2);
PathGeometry backgroundLine2Geometry = new PathGeometry();
backgroundLine2Geometry.Figures.Add(line2Figure);
GeometryDrawing backgroundLineDrawing2 = new GeometryDrawing(
new SolidColorBrush(Color.FromArgb(255, 204, 204, 255)),
null,
backgroundLine2Geometry
);

DrawingGroup backgroundGroup = new DrawingGroup();


backgroundGroup.Children.Add(backgroundRectangleDrawing);
backgroundGroup.Children.Add(backgroundLineDrawing1);
backgroundGroup.Children.Add(backgroundLineDrawing2);

DrawingBrush gridPatternBrush = new DrawingBrush(backgroundGroup);


gridPatternBrush.Viewport = new Rect(0, 0, 10, 10);
gridPatternBrush.ViewportUnits = BrushMappingMode.Absolute;
gridPatternBrush.TileMode = TileMode.Tile;
gridPatternBrush.Freeze();

Border mainBorder = new Border();


mainBorder.Background = gridPatternBrush;
mainBorder.BorderThickness = new Thickness(1);
mainBorder.BorderBrush = Brushes.Gray;
mainBorder.HorizontalAlignment = HorizontalAlignment.Left;
mainBorder.VerticalAlignment = VerticalAlignment.Top;
mainBorder.Margin = new Thickness(20);
mainBorder.Child = mainPanel;

//
// Add the items to the page.
//
this.Content = mainBorder;
this.Background = Brushes.White;
}
}
}
}

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions">
<Border BorderThickness="1" BorderBrush="Gray"
HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="20">
<StackPanel Margin="20" Orientation="Horizontal">

<Image Stretch="None" Margin="10">


<Image.Source>
<DrawingImage PresentationOptions:Freeze="True">
<DrawingImage.Drawing>

<!-- This DrawingGroup has no GuidelineSet. -->


<DrawingGroup>
<GeometryDrawing Brush="Black">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,20,30,80" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="5.5,25, 20,20" />
<RectangleGeometry Rect="5.5,50, 20,20" />
<RectangleGeometry Rect="5.5,75, 20,20" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>

<Image Stretch="None" Margin="50,10,10,10">


<Image.Source>
<DrawingImage PresentationOptions:Freeze="True">
<DrawingImage.Drawing>

<!-- This DrawingGroup has a GuidelineSet. -->


<DrawingGroup>
<GeometryDrawing Brush="Black">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,20,30,80" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="5.5,25, 20,20" />
<RectangleGeometry Rect="5.5,50, 20,20" />
<RectangleGeometry Rect="5.5,75, 20,20" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
<DrawingGroup.GuidelineSet>

<!-- The GuidelineSet -->


<GuidelineSet
GuidelinesX="5.5,25.5" GuidelinesY="25,50,75" />
GuidelinesX="5.5,25.5" GuidelinesY="25,50,75" />
</DrawingGroup.GuidelineSet>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</StackPanel>

<Border.Background>
<DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile"
PresentationOptions:Freeze="True">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
<GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>
</Border>
</Page>

Vea también
DrawingGroup
GuidelineSet
Información general sobre objetos Drawing
Procedimiento Crear un dibujo compuesto
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un DrawingGroup para crear dibujos complejos combinando varias
Drawing objetos en un solo dibujo compuesto.

Ejemplo
En el ejemplo siguiente se usa un DrawingGroup para crear un dibujo compuesto a partir del GeometryDrawing y
ImageDrawing objetos. En la ilustración siguiente se muestra el resultado que genera el ejemplo.

Un dibujo compuesto que se crea mediante el uso de DrawingGroup


Tenga en cuenta el borde gris, que muestra los límites del dibujo.

//
// Create three drawings.
//
GeometryDrawing ellipseDrawing =
new GeometryDrawing(
new SolidColorBrush(Color.FromArgb(102, 181, 243, 20)),
new Pen(Brushes.Black, 4),
new EllipseGeometry(new Point(50,50), 50, 50)
);

ImageDrawing kiwiPictureDrawing =
new ImageDrawing(
new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative)),
new Rect(50,50,100,100));

GeometryDrawing ellipseDrawing2 =
new GeometryDrawing(
new SolidColorBrush(Color.FromArgb(102,181,243,20)),
new Pen(Brushes.Black, 4),
new EllipseGeometry(new Point(150, 150), 50, 50)
);

// Create a DrawingGroup to contain the drawings.


DrawingGroup aDrawingGroup = new DrawingGroup();
aDrawingGroup.Children.Add(ellipseDrawing);
aDrawingGroup.Children.Add(kiwiPictureDrawing);
aDrawingGroup.Children.Add(ellipseDrawing2);
<DrawingGroup>

<GeometryDrawing Brush="#66B5F314">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="4" />
</GeometryDrawing.Pen>
</GeometryDrawing>
<ImageDrawing ImageSource="sampleImages\kiwi.png" Rect="50,50,100,100"/>
<GeometryDrawing Brush="#66B5F314">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="150,150" RadiusX="50" RadiusY="50"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="4" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingGroup>

Puede usar un DrawingGroup para aplicar un Transform, Opacity establecer, OpacityMask, BitmapEffect,
ClipGeometry, o GuidelineSet a la contiene los dibujos. Dado que un DrawingGroup es también un Drawing,
pueden contener otros DrawingGroup objetos.
El ejemplo siguiente es similar al ejemplo anterior, salvo que usa adicionales DrawingGroup objetos que se va a
aplicar efectos de imagen y una máscara de opacidad a algunos de sus planos. En la ilustración siguiente se
muestra el resultado que genera el ejemplo.

Dibujo compuesto que tiene varios objetos de DrawingGroup


Tenga en cuenta el borde gris, que muestra los límites del dibujo.

// Create a DrawingGroup.
DrawingGroup mainGroup = new DrawingGroup();

//
// Create a GeometryDrawing
//
GeometryDrawing ellipseDrawing =
new GeometryDrawing(
new SolidColorBrush(Color.FromArgb(102, 181, 243, 20)),
new Pen(Brushes.Black, 4),
new EllipseGeometry(new Point(50, 50), 50, 50)
);

//
// Use a DrawingGroup to apply a blur
// bitmap effect to the drawing.
//
DrawingGroup blurGroup = new DrawingGroup();
blurGroup.Children.Add(ellipseDrawing);
blurGroup.Children.Add(ellipseDrawing);
BlurBitmapEffect blurEffect = new BlurBitmapEffect();
blurEffect.Radius = 5;
blurGroup.BitmapEffect = blurEffect;

// Add the DrawingGroup to the main DrawingGroup.


mainGroup.Children.Add(blurGroup);

//
// Create an ImageDrawing.
//
ImageDrawing kiwiPictureDrawing =
new ImageDrawing(
new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative)),
new Rect(50, 50, 100, 100));

//
// Use a DrawingGroup to apply an opacity mask
// and a bevel.
//
DrawingGroup maskedAndBeveledGroup = new DrawingGroup();
maskedAndBeveledGroup.Children.Add(kiwiPictureDrawing);

// Create an opacity mask.


RadialGradientBrush rgBrush =new RadialGradientBrush();
rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(0,0,0,0), 0.55));
rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(255,0,0,0), 0.65));
rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(0,0,0,0), 0.75));
rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(255,0,0,0), 0.80));
rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(0,0,0,0), 0.90));
rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(255,0,0,0), 1.0));
maskedAndBeveledGroup.OpacityMask = rgBrush;

// Apply a bevel.
maskedAndBeveledGroup.BitmapEffect = new BevelBitmapEffect();

// Add the DrawingGroup to the main group.


mainGroup.Children.Add(maskedAndBeveledGroup);

//
// Create another GeometryDrawing.
//
GeometryDrawing ellipseDrawing2 =
new GeometryDrawing(
new SolidColorBrush(Color.FromArgb(102, 181, 243, 20)),
new Pen(Brushes.Black, 4),
new EllipseGeometry(new Point(150, 150), 50, 50)
);

// Add the DrawingGroup to the main group.


mainGroup.Children.Add(ellipseDrawing2);
<DrawingGroup>

<DrawingGroup>
<GeometryDrawing Brush="#66B5F314">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="4" />
</GeometryDrawing.Pen>
</GeometryDrawing>
<DrawingGroup.BitmapEffect>
<BlurBitmapEffect Radius="5" />
</DrawingGroup.BitmapEffect>
</DrawingGroup>

<DrawingGroup>
<ImageDrawing ImageSource="sampleImages\kiwi.png" Rect="50,50,100,100"/>
<DrawingGroup.BitmapEffect>
<BevelBitmapEffect />
</DrawingGroup.BitmapEffect>
<DrawingGroup.OpacityMask>
<RadialGradientBrush>
<GradientStop Offset="0.55" Color="#00000000" />
<GradientStop Offset="0.65" Color="#FF000000" />
<GradientStop Offset="0.75" Color="#00000000" />
<GradientStop Offset="0.80" Color="#FF000000" />
<GradientStop Offset="0.90" Color="#00000000" />
<GradientStop Offset="1.0" Color="#FF000000" />
</RadialGradientBrush>
</DrawingGroup.OpacityMask>
</DrawingGroup>

<GeometryDrawing Brush="#66B5F314">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="150,150" RadiusX="50" RadiusY="50"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="4" />
</GeometryDrawing.Pen>
</GeometryDrawing>

</DrawingGroup>

Para obtener más información acerca de Drawing objetos, vea información general sobre objetos de dibujo.

Vea también
BitmapEffect
Transform
OpacityMask
Opacity
ClipGeometry
GuidelineSet
Información general sobre objetos Drawing
Procedimiento Crear un objeto GeometryDrawing
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo crear y mostrar un GeometryDrawing. Un GeometryDrawing le permite crear
de forma con un relleno y el contorno asociando un Pen y un Brush con un Geometry. El Geometry describe la
estructura de la forma, el Brush describe el relleno de la forma y el Pen describe el contorno de la forma.

Ejemplo
En el ejemplo siguiente se usa un GeometryDrawing para representar una forma. Se describe la forma mediante
una GeometryGroup y dos EllipseGeometry objetos. Se pinta el interior de la forma con un LinearGradientBrush y
el contorno se dibuja con un Black Pen. El GeometryDrawing se muestra mediante un ImageDrawing y un Image
elemento.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SDKSample
{
public class GeometryDrawingExample : Page
{
public GeometryDrawingExample()
{

//
// Create the Geometry to draw.
//
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(
new EllipseGeometry(new Point(50,50), 45, 20)
);
ellipses.Children.Add(
new EllipseGeometry(new Point(50, 50), 20, 45)
);

//
// Create a GeometryDrawing.
//
GeometryDrawing aGeometryDrawing = new GeometryDrawing();
aGeometryDrawing.Geometry = ellipses;

// Paint the drawing with a gradient.


aGeometryDrawing.Brush =
new LinearGradientBrush(
Colors.Blue,
Color.FromRgb(204,204,255),
new Point(0,0),
new Point(1,1));

// Outline the drawing with a solid color.


aGeometryDrawing.Pen = new Pen(Brushes.Black, 10);

//
// Use a DrawingImage and an Image control
// to display the drawing.
//
//
DrawingImage geometryImage = new DrawingImage(aGeometryDrawing);

// Freeze the DrawingImage for performance benefits.


geometryImage.Freeze();

Image anImage = new Image();


anImage.Source = geometryImage;
anImage.Stretch = Stretch.None;
anImage.HorizontalAlignment = HorizontalAlignment.Left;

//
// Place the image inside a border and
// add it to the page.
//
Border exampleBorder = new Border();
exampleBorder.Child = anImage;
exampleBorder.BorderBrush = Brushes.Gray;
exampleBorder.BorderThickness = new Thickness(1);
exampleBorder.HorizontalAlignment = HorizontalAlignment.Left;
exampleBorder.VerticalAlignment = VerticalAlignment.Top;
exampleBorder.Margin = new Thickness(10);

this.Margin = new Thickness(20);


this.Background = Brushes.White;
this.Content = exampleBorder;
}
}
}
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Margin="20" Background="White">

<Border BorderBrush="Gray" BorderThickness="1"


HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="10">
<Image Stretch="None" HorizontalAlignment="Left">
<Image.Source>
<DrawingImage PresentationOptions:Freeze="True">
<DrawingImage.Drawing>

<GeometryDrawing>
<GeometryDrawing.Geometry>

<!-- Create a composite shape. -->


<GeometryGroup>
<EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" />
<EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>

<!-- Paint the drawing with a gradient. -->


<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Blue" />
<GradientStop Offset="1.0" Color="#CCCCFF" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Pen>

<!-- Outline the drawing with a solid color. -->


<Pen Thickness="10" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Border>

</Page>

La siguiente ilustración muestra resultante GeometryDrawing.

Para crear dibujos más complejos, puede combinar varios objetos de dibujo en un elemento compuesto de dibujo
utilizando un DrawingGroup.

Vea también
DrawingGroup
Información general sobre objetos Drawing
Información general sobre geometría
Crear un dibujo compuesto
Procedimiento Dibujar una imagen mediante un
objeto ImageDrawing
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un ImageDrawing para dibujar una imagen. Un ImageDrawing permite
mostrar un ImageSource con un DrawingBrush, DrawingImage, o Visual. Para dibujar una imagen, se crea un
ImageDrawing y establezca su ImageDrawing.ImageSource y ImageDrawing.Rect propiedades. El
ImageDrawing.ImageSource propiedad especifica la imagen para dibujar y la ImageDrawing.Rect propiedad
especifica la posición y tamaño de cada imagen.

Ejemplo
En el ejemplo siguiente se crea un dibujo compuesto mediante cuatro ImageDrawing objetos. Este ejemplo genera
la siguiente imagen:

Cuatro objetos de un objeto ImageDrawing

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;

namespace SDKSample
{
public class ImageDrawingExample : Page
{
public ImageDrawingExample()
{
// Create a DrawingGroup to combine the ImageDrawing objects.
DrawingGroup imageDrawings = new DrawingGroup();

// Create a 100 by 100 image with an upper-left point of (75,75).


ImageDrawing bigKiwi = new ImageDrawing();
bigKiwi.Rect = new Rect(75, 75, 100, 100);
bigKiwi.ImageSource = new BitmapImage(
new Uri(@"sampleImages\kiwi.png", UriKind.Relative));

imageDrawings.Children.Add(bigKiwi);

// Create a 25 by 25 image with an upper-left point of (0,150).


ImageDrawing smallKiwi1 = new ImageDrawing();
smallKiwi1.Rect = new Rect(0, 150, 25, 25);
smallKiwi1.ImageSource = new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative));
imageDrawings.Children.Add(smallKiwi1);
// Create a 25 by 25 image with an upper-left point of (150,0).
ImageDrawing smallKiwi2 = new ImageDrawing();
smallKiwi2.Rect = new Rect(150, 0, 25, 25);
smallKiwi2.ImageSource = new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative));
imageDrawings.Children.Add(smallKiwi2);

// Create a 75 by 75 image with an upper-left point of (0,0).


ImageDrawing wholeKiwi = new ImageDrawing();
wholeKiwi.Rect = new Rect(0, 0, 75, 75);
wholeKiwi.ImageSource = new BitmapImage(new Uri(@"sampleImages\wholekiwi.png", UriKind.Relative));
imageDrawings.Children.Add(wholeKiwi);

//
// Use a DrawingImage and an Image control to
// display the drawings.
//
DrawingImage drawingImageSource = new DrawingImage(imageDrawings);

// Freeze the DrawingImage for performance benefits.


drawingImageSource.Freeze();

Image imageControl = new Image();


imageControl.Stretch = Stretch.None;
imageControl.Source = drawingImageSource;

// Create a border to contain the Image control.


Border imageBorder = new Border();
imageBorder.BorderBrush = Brushes.Gray;
imageBorder.BorderThickness = new Thickness(1);
imageBorder.HorizontalAlignment = HorizontalAlignment.Left;
imageBorder.VerticalAlignment = VerticalAlignment.Top;
imageBorder.Margin = new Thickness(20);
imageBorder.Child = imageControl;

this.Background = Brushes.White;
this.Margin = new Thickness(20);
this.Content = imageBorder;
}
}
}
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Background="White" Margin="20">
<Border BorderBrush="Gray" BorderThickness="1"
HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="20">
<Image Stretch="None">
<Image.Source>
<DrawingImage PresentationOptions:Freeze="True">
<DrawingImage.Drawing>
<DrawingGroup>

<!-- The Rect property specifies that the image only fill a 100 by 100
rectangular area. -->
<ImageDrawing Rect="75,75,100,100" ImageSource="sampleImages\kiwi.png"/>

<!-- This image is set to fill a 25 by 25 rectangular area. -->


<ImageDrawing Rect="0,150,25,25" ImageSource="sampleImages\kiwi.png"/>

<!-- This image is set to fill a 25 by 25 rectangular area. -->


<ImageDrawing Rect="150,0,25,25" ImageSource="sampleImages\kiwi.png"/>

<!-- This image is set to fill a 75 by 75 rectangular area. -->


<ImageDrawing Rect="0,0,75,75" ImageSource="sampleImages\wholekiwi.png"/>

</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Border>
</Page>

Para obtener un ejemplo que muestra una manera sencilla de mostrar una imagen sin utilizar ImageDrawing,
consulte usar el elemento de imagen.

Vea también
Freeze
Image
Información general sobre objetos Drawing
Información general sobre objetos Freezable
PresentationOptions:Freeze (Atributo)
Procedimiento Reproducir elementos multimedia con
un objeto VideoDrawing
23/10/2019 • 2 minutes to read • Edit Online

Para reproducir un archivo de audio o vídeo, use VideoDrawing MediaPlayery. Hay dos maneras de cargar y
reproducir elementos multimedia. La MediaPlayer primera es usar una y una VideoDrawing por sí MediaPlayer
misma, y la segunda consiste en crear la suya propia MediaTimeline para usarla con y VideoDrawing.

NOTE
Al distribuir elementos multimedia con la aplicación, no puede utilizar un archivo multimedia como recurso del proyecto,
como haría con una imagen. En el archivo de proyecto, debe establecer en su lugar el tipo de elemento multimedia en
Content y establecer CopyToOutputDirectory en PreserveNewest o Always .

Ejemplo
En el ejemplo siguiente se VideoDrawing usa un MediaPlayer y un para reproducir un archivo de vídeo una vez.

//
// Create a VideoDrawing.
//
MediaPlayer player = new MediaPlayer();

player.Open(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));

VideoDrawing aVideoDrawing = new VideoDrawing();

aVideoDrawing.Rect = new Rect(0, 0, 100, 100);

aVideoDrawing.Player = player;

// Play the video once.


player.Play();

Para obtener un MediaTimeline control de tiempo adicional sobre los medios, utilice con MediaPlayer los
VideoDrawing objetos y. MediaTimeline Permite especificar si el vídeo debe repetirse.

Ejemplo
En el ejemplo siguiente se MediaTimeline usa con MediaPlayer los VideoDrawing objetos y para reproducir un
vídeo repetidamente.
//
// Create a VideoDrawing that repeats.
//

// Create a MediaTimeline.
MediaTimeline mTimeline =
new MediaTimeline(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));

// Set the timeline to repeat.


mTimeline.RepeatBehavior = RepeatBehavior.Forever;

// Create a clock from the MediaTimeline.


MediaClock mClock = mTimeline.CreateClock();

MediaPlayer repeatingVideoDrawingPlayer = new MediaPlayer();


repeatingVideoDrawingPlayer.Clock = mClock;

VideoDrawing repeatingVideoDrawing = new VideoDrawing();


repeatingVideoDrawing.Rect = new Rect(150, 0, 100, 100);
repeatingVideoDrawing.Player = repeatingVideoDrawingPlayer;

Tenga MediaClock en cuenta que, cuando se MediaTimelineusa un, se usa ClockController la interactiva Controller
devuelta desde la propiedad de para controlar la reproducción multimedia en lugar de MediaPlayerlos métodos
interactivos de.

Vea también
VideoDrawing
Información general sobre objetos Drawing
Procedimiento Usar un dibujo como el origen de una
imagen
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un Drawing como el Source para un Image control. Para mostrar un
Drawing con un Image controlar, use un DrawingImage como el Image del control Source y establezca el
DrawingImage del objeto DrawingImage.Drawing propiedad para el dibujo que desea mostrar.

Ejemplo
En el ejemplo siguiente se usa un DrawingImage y un Image control para mostrar un GeometryDrawing. Este
ejemplo produce el siguiente resultado:

DrawingImage

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SDKSample
{
public class DrawingImageExample : Page
{

public DrawingImageExample()
{

//
// Create the Geometry to draw.
//
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(
new EllipseGeometry(new Point(50,50), 45, 20)
);
ellipses.Children.Add(
new EllipseGeometry(new Point(50, 50), 20, 45)
);

//
// Create a GeometryDrawing.
//
GeometryDrawing aGeometryDrawing = new GeometryDrawing();
aGeometryDrawing.Geometry = ellipses;

// Paint the drawing with a gradient.


aGeometryDrawing.Brush =
new LinearGradientBrush(
Colors.Blue,
Color.FromRgb(204,204,255),
new Point(0,0),
new Point(1,1));

// Outline the drawing with a solid color.


aGeometryDrawing.Pen = new Pen(Brushes.Black, 10);

//
// Use a DrawingImage and an Image control
// to display the drawing.
//
DrawingImage geometryImage = new DrawingImage(aGeometryDrawing);

// Freeze the DrawingImage for performance benefits.


geometryImage.Freeze();

Image anImage = new Image();


anImage.Source = geometryImage;
anImage.HorizontalAlignment = HorizontalAlignment.Left;

//
// Place the image inside a border and
// add it to the page.
//
Border exampleBorder = new Border();
exampleBorder.Child = anImage;
exampleBorder.BorderBrush = Brushes.Gray;
exampleBorder.BorderThickness = new Thickness(1);
exampleBorder.HorizontalAlignment = HorizontalAlignment.Left;
exampleBorder.VerticalAlignment = VerticalAlignment.Top;
exampleBorder.Margin = new Thickness(10);

this.Margin = new Thickness(20);


this.Background = Brushes.White;
this.Content = exampleBorder;
}
}
}
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Background="White" Margin="20">

<Border BorderBrush="Gray" BorderThickness="1"


HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="10">

<!-- This image uses a Drawing object for its source. -->
<Image>
<Image.Source>
<DrawingImage PresentationOptions:Freeze="True">
<DrawingImage.Drawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" />
<EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Blue" />
<GradientStop Offset="1.0" Color="#CCCCFF" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Pen>
<Pen Thickness="10" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Border>

</Page>

Vea también
Freeze
Dibujar una imagen usando un objeto ImageDrawing
Información general sobre objetos Drawing
Información general sobre objetos Freezable
PresentationOptions:Freeze (Atributo)
Geometrías
23/10/2019 • 2 minutes to read • Edit Online

Geometry es una clase versátil, que se utiliza para representar gráficos 2D, objetos de la prueba de
posicionamiento y definir regiones de recorte

En esta sección
Sintaxis de marcado de trazados
Información general sobre geometría
Temas "Cómo..."

Vea también
Brushes
Shape
Imágenes y gráficos 2D
Información general sobre formas y dibujo básico en WPF
Gráficos y multimedia
Sintaxis de marcado de trazados
23/10/2019 • 16 minutes to read • Edit Online

Las rutas de acceso se tratan en formas y dibujo básico en WPF Overview y información general sobre
geometría, sin embargo, este tema describe en detalle el eficaz y complejo minilenguaje puede usar para
especificar la ruta de acceso geometrías de manera más compacta con Lenguaje XAML (Extensible Application
Markup Language).

Requisitos previos
Para entender este tema, debe estar familiarizado con las características básicas de Geometry objetos. Para
obtener más información, consulte el información general sobre geometría.

Minilenguajes StreamGeometry y PathFigureCollection


WPF proporciona dos clases que proporcionan minilenguajes para describir los trazados geométricos:
StreamGeometry y PathFigureCollection.
Usa el StreamGeometry minilenguaje al establecer una propiedad de tipo Geometry, como el Clip
propiedad de un UIElement o el Data propiedad de un Path elemento. En el ejemplo siguiente se usa la
sintaxis de atributo para crear un StreamGeometry.

<Path Stroke="Black" Fill="Gray"


Data="M 10,100 C 10,300 300,-200 300,100" />

Usa el PathFigureCollection minilenguaje al establecer el Figures propiedad de un PathGeometry. En el


ejemplo siguiente se usa una sintaxis de atributo para crear un PathFigureCollection para un
PathGeometry.

<Path Stroke="Black" Fill="Gray">


<Path.Data>
<PathGeometry Figures="M 10,100 C 10,300 300,-200 300,100" />
</Path.Data>
</Path>

Como puede ver en los ejemplos anteriores, los dos minilenguajes son muy similares. ¿Siempre es posible usar
un PathGeometry en cualquier situación donde podría usar un StreamGeometry; por lo que debe cuál usar?
Usar un StreamGeometry cuando no es necesario modificar la ruta de acceso después de crearla; utilice un
PathGeometry si tiene que modificar la ruta de acceso.
Para obtener más información sobre las diferencias entre PathGeometry y StreamGeometry objetos, vea el
información general sobre geometría.
Nota sobre los espacios en blanco
Por razones de brevedad, se muestra un solo espacio en las secciones de sintaxis siguientes, pero también se
aceptan varios espacios cada vez que se muestra uno solo.
Dos números realmente no tienen que estar separados por comas o espacios en blanco, pero esto solo se puede
hacer cuando la cadena resultante no es ambigua. Por ejemplo, 2..3 es realmente de dos números: "2." y ".3".
De forma similar, 2-3 es "2" y "-3". Tampoco se necesitan espacios antes o después de los comandos.
Sintaxis
El Lenguaje XAML (Extensible Application Markup Language) atributo sintaxis de uso para un StreamGeometry
se compone de un elemento opcional FillRule valor y uno o más descripciones de figura.

USO DEL ATRIBUTO XAML STREAMGEOMETRY

< object property =" [ fillRule ] figureDescription [ figureDescription ]* " ... />

El Lenguaje XAML (Extensible Application Markup Language) atributo sintaxis de uso para un
PathFigureCollection se compone de uno o más descripciones de figura.

USO DEL ATRIBUTO XAML PATHFIGURECOLLECTION

< object property =" figureDescription [ figureDescription ]* " ... />

TÉRMINO DESCRIPCIÓN

fillRule System.Windows.Media.FillRule

Especifica si el StreamGeometry usa el EvenOdd o Nonzero


FillRule.

- F0 Especifica el EvenOdd regla de relleno.


- F1 Especifica el Nonzero regla de relleno.

Si se omite este comando, el subtrazado usa el


comportamiento predeterminado, que es EvenOdd. Si
especifica el comando, debe colocarlo primero.

figureDescription Figura compuesta de un comando de movimiento,


comandos de dibujo y un comando de cierre opcional.

moveCommand drawCommands [ closeCommand ]

moveCommand Comando de movimiento que especifica el punto inicial de la


figura. Consulte la comando Move sección.

drawCommands Uno o más comandos de dibujo que describe el contenido


de la figura. Consulte la comandos de dibujo sección.

closeCommand Comando opcional de cierre que cierra la figura. Consulte la


comando Cerrar sección.

Comando de movimiento
Especificar el punto inicial de una figura nueva.

SINTAXIS

M startPoint

o bien

m startPoint
TÉRMINO DESCRIPCIÓN

startPoint System.Windows.Point

El punto inicial de una figura nueva.

En mayúscula M indica que startPoint es un valor absoluto; una minúscula m indica que startPoint es un
desplazamiento hasta el punto anterior, o bien (0,0) si no existe ninguno. Si enumera varios puntos después del
comando de movimiento, se dibuja una línea a esos puntos si especificó el comando de línea.

Comandos de dibujo
Un comando de dibujo puede constar de varios comandos de forma. Están disponibles los siguientes comandos
de forma: línea, línea horizontal, línea vertical, curva Bézier cúbica, curva Bézier cuadrática, curva Bézier cúbica
suavizada, curva Bézier cuadrática suavizada y arco elíptico.
Puede escribir cada comando con una letra mayúscula o una minúscula, donde las letras mayúsculas indican
valores absolutos y las minúsculas, valores relativos: los puntos de control de ese segmento son relativos al
punto final del ejemplo anterior. Cuando escriba secuencialmente más de un comando del mismo tipo, puede
omitir la entrada de comando duplicada; Por ejemplo, L 100,200 300,400 es equivalente a L 100,200 L 300,400 .
La tabla siguiente se describen los mover y dibujar comandos.
Comando de línea
Crea una línea recta entre el punto actual y el punto final especificado. l 20 30 y L 20,30 son ejemplos de
línea comandos.

SINTAXIS

L endPoint

o bien

l endPoint

TÉRMINO DESCRIPCIÓN

endPoint System.Windows.Point

Punto de conexión de la línea.

En mayúscula L indica que endPoint es un valor absoluto; una minúscula l indica que endPoint es un
desplazamiento hasta el punto anterior, o bien (0,0) si no existe ninguno.
Comando de línea horizontal
Crea una línea horizontal entre el punto actual y la coordenada x especificada. H 90 es un ejemplo de un
comando de línea horizontal válido.

SINTAXIS

H x

o bien

h x
TÉRMINO DESCRIPCIÓN

x System.Double

Coordenada x del punto final de la línea.

En mayúscula H indica que x es un valor absoluto; una minúscula h indica que x es un desplazamiento
hasta el punto anterior, o bien (0,0) si no existe ninguno.
Comando de línea vertical
Crea una línea vertical entre el punto actual y la coordenada y especificada. v 90 es un ejemplo de comando de
línea vertical válido.

SINTAXIS

V y

o bien

v y

TÉRMINO DESCRIPCIÓN

y System.Double

Coordenada y del punto final de la línea.

En mayúscula V indica que y es un valor absoluto; una minúscula v indica que y es un desplazamiento
hasta el punto anterior, o bien (0,0) si no existe ninguno.
Comando de curva Bézier cúbica
Crea una curva Bézier cúbica entre el punto actual y el punto final especificado mediante el uso de los dos
puntos de control especificado ( controlPoint 1 y controlPoint 2). C 100,200 200,400 300,200 es un ejemplo de
un comando de curva válido.

SINTAXIS

C controlPoint 1 controlPoint 2 endPoint

o bien

c controlPoint 1 controlPoint 2 endPoint

TÉRMINO DESCRIPCIÓN

controlPoint 1 System.Windows.Point

El primer punto de control de la curva, que determina la


tangente de inicio de la misma.

controlPoint 2 System.Windows.Point

El segundo punto de control de la curva, que determina la


tangente final de la misma.
TÉRMINO DESCRIPCIÓN

endPoint System.Windows.Point

Punto en el que se dibuja la curva.

Comando de curva Bézier cuadrática


Crea una curva Bézier cuadrática entre el punto actual y el punto final especificado utilizando el punto de control
especificado ( controlPoint ). q 100,200 300,200 es un ejemplo de un comando de curva Bézier cuadrática
válido.

SINTAXIS

Q controlPoint endPoint

o bien

q controlPoint endPoint

TÉRMINO DESCRIPCIÓN

controlPoint System.Windows.Point

El punto de control de la curva, que determina las tangentes


de inicio y final de la misma.

endPoint System.Windows.Point

Punto en el que se dibuja la curva.

Comando de curva Bézier cúbica suavizada


Crea una curva Bézier cúbica entre el punto actual y el punto final especificado. El primer punto de control se
supone que es el reflejo del segundo punto de control del comando anterior en relación al punto actual. Si no
hay un comando anterior o si el comando anterior no fuera un comando de curva Bézier cúbica o un comando
de curva Bézier cúbica suavizada, el primer punto de control se supone coincidente con el punto actual. El
segundo punto de control, especificado por el punto de control para el final de la curva, controlPoint 2. Por
ejemplo, S 100,200 200,300 es un válido comando Bézier cúbica suavizada curva.

SINTAXIS

S controlPoint 2 endPoint

o bien

s controlPoint 2 endPoint

TÉRMINO DESCRIPCIÓN

controlPoint 2 System.Windows.Point

El punto de control de la curva, que determina la tangente


final de la misma.
TÉRMINO DESCRIPCIÓN

endPoint System.Windows.Point

Punto en el que se dibuja la curva.

Comando de curva Bézier cuadrática suavizada


Crea una curva Bézier cuadrática entre el punto actual y el punto final especificado. El punto de control se
supone que es el reflejo del punto de control del comando anterior en relación al punto actual. Si no hay un
comando anterior o si el comando anterior no fuera un comando de curva Bézier cuadrática o un comando de
curva Bézier cuadrática suavizada, el punto de control coincide con el punto actual.

SINTAXIS

T controlPoint endPoint

o bien

t controlPoint endPoint

TÉRMINO DESCRIPCIÓN

controlPoint System.Windows.Point

El punto de control de la curva, que determina el inicio y la


tangente de la curva.

endPoint System.Windows.Point

Punto en el que se dibuja la curva.

Comando de arco elíptico


Crea un arco elíptico entre el punto actual y el punto final especificado.

SINTAXIS

A size rotationAngle isLargeArcFlag sweepDirectionFlag endPoint

o bien

a size rotationAngle isLargeArcFlag sweepDirectionFlag endPoint

TÉRMINO DESCRIPCIÓN

size System.Windows.Size

Los radios X e Y del arco.

rotationAngle System.Double

La rotación de la elipse, en grados.

isLargeArcFlag Establezca el valor en 1 si el ángulo del arco debe ser de 180


grados o más; de lo contrario, establézcalo en 0.
TÉRMINO DESCRIPCIÓN

sweepDirectionFlag Establezca el valor en 1 si se dibuja en una dirección con


ángulo positivo; de lo contrario, establézcalo en 0.

endPoint System.Windows.Point

Punto en el que está dibujado el arco.

Comando de cierre
Finaliza la figura actual y crea una línea que conecta el punto actual con el punto inicial de la figura. Este
comando crea una unión de líneas (esquina) entre el último y el primer segmento de la figura.

SINTAXIS

o bien

Sintaxis de punto
Describe las coordenadas x e y de un punto donde (0,0) es la esquina superior izquierda.

SINTAXIS

x , y

o bien

x y

TÉRMINO DESCRIPCIÓN

x System.Double

La coordenada x del punto.

y System.Double

La coordenada y del punto.

Valores especiales
En lugar de un valor numérico estándar, también puede usar los valores especiales siguientes. Estos valores
distinguen mayúsculas de minúsculas.
Infinito
Representa Double.PositiveInfinity.
-Infinity
Representa Double.NegativeInfinity.
NaN
Representa Double.NaN.
También puede usar la notación científica. Por ejemplo, +1.e17 es un valor válido.

Vea también
Path
StreamGeometry
PathGeometry
PathFigureCollection
Información general sobre formas y dibujo básico en WPF
Información general sobre geometría
Temas "Cómo..."
Información general sobre geometría
04/11/2019 • 24 minutes to read • Edit Online

En esta información general se describe cómo usar las clases de Geometry de Windows Presentation
Foundation (WPF ) para describir las formas. En este tema también se contrastan las diferencias entre
Geometry objetos y elementos de Shape.

¿Qué es una geometría?


La clase Geometry y las clases que derivan de ella, como EllipseGeometry, PathGeometryy
CombinedGeometry, permiten describir la geometría de una forma 2D. Estas descripciones geométricas
tiene muchos usos, como definir una forma para pintarla en la pantalla o definir regiones de recorte y
pruebas de posicionamiento. Incluso se puede usar una geometría para definir un trazado de animación.
Geometry objetos pueden ser simples, como rectángulos y círculos, o compuesto, creados a partir de dos o
más objetos Geometry. Se pueden crear geometrías más complejas mediante las clases PathGeometry y
StreamGeometry, que permiten describir arcos y curvas.
Dado que un Geometry es un tipo de Freezable, los objetos Geometry proporcionan varias características
especiales: se pueden declarar como recursos, compartirse entre varios objetos, convertirse en de solo
lectura para mejorar el rendimiento, clonarse y hacer que sea segura para subprocesos. Para obtener más
información sobre las diferentes características proporcionadas por los objetos Freezable, consulte la
información general sobre objetos Freezable.

Geometrías frente a formas


Las clases Geometry y Shape parecen ser similares en que describen las formas 2D (Compare
EllipseGeometry y Ellipse por ejemplo), pero hay diferencias importantes.
En el caso de uno, la clase Geometry hereda de la clase Freezable, mientras que la clase Shape hereda de
FrameworkElement. Dado que son elementos, Shape objetos se pueden representar y participar en el
sistema de diseño, mientras que los objetos Geometry no.
Aunque Shape objetos se pueden usar más fácilmente que los objetos de Geometry, los objetos de
Geometry son más versátiles. Mientras que un objeto de Shape se usa para representar gráficos 2D, se
puede usar un objeto Geometry para definir la región geométrica de los gráficos 2D, definir una región para
recortar o definir una región para la prueba de posicionamiento, por ejemplo.
La forma del trazado
Una Shape, la clase Path, utiliza realmente un Geometry para describir su contenido. Si establece la
propiedad Data de la Path con un Geometry y establece sus propiedades Fill y Stroke, puede representar una
Geometry.

Propiedades comunes que aceptan un objeto Geometry


En las secciones anteriores se menciona que se pueden usar objetos Geometry con otros objetos con
diversos fines, como dibujar formas, crear animaciones y efectuar recortes. En la tabla siguiente se
enumeran varias clases que tienen propiedades que toman un objeto Geometry.
TYPE PROPIEDAD.

DoubleAnimationUsingPath PathGeometry

DrawingGroup ClipGeometry

GeometryDrawing Geometry

Path Data

UIElement Clip

Tipos de objeto Geometry simples


La clase base para todas las geometrías es la clase abstracta Geometry. Las clases que derivan de la clase
Geometry se pueden agrupar más o menos en tres categorías: geometrías simples, geometrías de trazado y
geometrías compuestas.
Entre las clases de geometría simples se incluyen LineGeometry, RectangleGeometryy EllipseGeometry y
que se usan para crear formas geométricas básicas, como líneas, rectángulos y círculos.
Un LineGeometry se define especificando el punto inicial de la línea y el punto final.
Un RectangleGeometry se define con una estructura de Rect que especifica su posición relativa y su
alto y ancho. Puede crear un rectángulo redondeado estableciendo las propiedades RadiusX y
RadiusY.
Un EllipseGeometry se define mediante un punto central, un radio x y un radio y. En los ejemplos
siguientes se muestra cómo crear geometrías simples de representación y recorte.
Estas mismas formas, así como las formas más complejas, se pueden crear mediante una PathGeometry o
combinando objetos Geometry juntos, pero estas clases proporcionan un medio más sencillo para generar
estas formas geométricas básicas.
En el ejemplo siguiente se muestra cómo crear y representar un LineGeometry. Como se indicó
anteriormente, un objeto de Geometry no puede dibujarse a sí mismo, por lo que en el ejemplo se usa una
forma Path para representar la línea. Dado que una línea no tiene área, establecer la propiedad Fill del Path
no tendría ningún efecto; en su lugar, solo se especifican las propiedades Stroke y StrokeThickness. En la
siguiente ilustración se muestra el resultado del ejemplo.

Objeto LineGeometry dibujado desde (10,20) hasta (100,130)

<Path Stroke="Black" StrokeThickness="1" >


<Path.Data>
<LineGeometry StartPoint="10,20" EndPoint="100,130" />
</Path.Data>
</Path>
LineGeometry myLineGeometry = new LineGeometry();
myLineGeometry.StartPoint = new Point(10,20);
myLineGeometry.EndPoint = new Point(100,130);

Path myPath = new Path();


myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myLineGeometry;

Dim myLineGeometry As New LineGeometry()


myLineGeometry.StartPoint = New Point(10,20)
myLineGeometry.EndPoint = New Point(100,130)

Dim myPath As New Path()


myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myLineGeometry

En el ejemplo siguiente se muestra cómo crear y representar un EllipseGeometry. En los ejemplos se


establece el Center de la EllipseGeometry se establece en el punto 50,50 y el radio x y el radio y se
establecen en 50 , lo que crea un círculo con un diámetro de 100. El interior de la elipse se dibuja asignando
un valor a la propiedad Fill del elemento Path, en este caso Gold. En la siguiente ilustración se muestra el
resultado del ejemplo.

Objeto EllipseGeometry dibujado en (50,50)

<Path Fill="Gold" Stroke="Black" StrokeThickness="1">


<Path.Data>
<EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50" />
</Path.Data>
</Path>

EllipseGeometry myEllipseGeometry = new EllipseGeometry();


myEllipseGeometry.Center = new Point(50, 50);
myEllipseGeometry.RadiusX = 50;
myEllipseGeometry.RadiusY = 50;

Path myPath = new Path();


myPath.Fill = Brushes.Gold;
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myEllipseGeometry;
Dim myEllipseGeometry As New EllipseGeometry()
myEllipseGeometry.Center = New Point(50, 50)
myEllipseGeometry.RadiusX = 50
myEllipseGeometry.RadiusY = 50

Dim myPath As New Path()


myPath.Fill = Brushes.Gold
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myEllipseGeometry

En el ejemplo siguiente se muestra cómo crear y representar un RectangleGeometry. La posición y las


dimensiones del rectángulo se definen mediante una estructura de Rect. La posición es 50,50 y el alto y
ancho son ambos 25 , lo que crea un cuadrado. En la siguiente ilustración se muestra el resultado del
ejemplo.

Objeto RectangleGeometry dibujado en 50,50

<Path Fill="LemonChiffon" Stroke="Black" StrokeThickness="1">


<Path.Data>
<RectangleGeometry Rect="50,50,25,25" />
</Path.Data>
</Path>

RectangleGeometry myRectangleGeometry = new RectangleGeometry();


myRectangleGeometry.Rect = new Rect(50,50,25,25);

Path myPath = new Path();


myPath.Fill = Brushes.LemonChiffon;
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myRectangleGeometry;

Dim myRectangleGeometry As New RectangleGeometry()


myRectangleGeometry.Rect = New Rect(50,50,25,25)

Dim myPath As New Path()


myPath.Fill = Brushes.LemonChiffon
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myRectangleGeometry

En el ejemplo siguiente se muestra cómo usar un EllipseGeometry como la región de recorte de una imagen.
Un objeto de Image se define con un Width de 200 y un Height de 150. Un EllipseGeometry con un valor de
RadiusX de 100, un valor de RadiusY de 75 y un valor de Center de 100, 75 se establece en la propiedad
Clip de la imagen. Solo se mostrará la parte de la imagen que queda dentro del área de la elipse. En la
siguiente ilustración se muestra el resultado del ejemplo.
Objeto EllipseGeometry usado para recortar un control Image

<Image
Source="sampleImages\Waterlilies.jpg"
Width="200" Height="150" HorizontalAlignment="Left">
<Image.Clip>
<EllipseGeometry
RadiusX="100"
RadiusY="75"
Center="100,75"/>
</Image.Clip>
</Image>

// Create the image to clip.


Image myImage = new Image();
Uri imageUri =
new Uri(@"C:\\Documents and Settings\\All Users\\Documents\My Pictures\\Sample Pictures\\Water
lilies.jpg", UriKind.Relative);
myImage.Source = new BitmapImage(imageUri);
myImage.Width = 200;
myImage.Height = 150;
myImage.HorizontalAlignment = HorizontalAlignment.Left;

// Use an EllipseGeometry to define the clip region.


EllipseGeometry myEllipseGeometry = new EllipseGeometry();
myEllipseGeometry.Center = new Point(100, 75);
myEllipseGeometry.RadiusX = 100;
myEllipseGeometry.RadiusY = 75;
myImage.Clip = myEllipseGeometry;
' Create the image to clip.
Dim myImage As New Image()
Dim imageUri As New Uri("C:\\Documents and Settings\\All Users\\Documents\My Pictures\\Sample
Pictures\\Water lilies.jpg", UriKind.Relative)
myImage.Source = New BitmapImage(imageUri)
myImage.Width = 200
myImage.Height = 150
myImage.HorizontalAlignment = HorizontalAlignment.Left

' Use an EllipseGeometry to define the clip region.


Dim myEllipseGeometry As New EllipseGeometry()
myEllipseGeometry.Center = New Point(100, 75)
myEllipseGeometry.RadiusX = 100
myEllipseGeometry.RadiusY = 75
myImage.Clip = myEllipseGeometry

Geometrías de trazado
La clase PathGeometry y su equivalente ligero, la clase StreamGeometry, proporcionan los medios para
describir varias figuras complejas que se componen de arcos, curvas y líneas.
En el corazón de un PathGeometry se trata de una colección de objetos PathFigure, de modo que cada figura
describe una forma discreta en el PathGeometry. Cada PathFigure se compone de uno o varios objetos
PathSegment, cada uno de los cuales describe un segmento de la figura.
Hay muchos tipos de segmentos.

TIPO DE SEGMENTO DESCRIPCIÓN EJEMPLO

ArcSegment Crea un arco elíptico entre dos Crear un arco elíptico.


puntos.

BezierSegment Crea una curva Bézier cúbica entre Crear una curva Bézier cúbica.
dos puntos.

LineSegment Crea una línea entre dos puntos. Crear un LineSegment en una clase
PathGeometry

PolyBezierSegment Crea una serie de curvas Bézier Vea la página tipo de


cúbicas. PolyBezierSegment.

PolyLineSegment Crea una serie de líneas. Vea la página tipo de


PolyLineSegment.

PolyQuadraticBezierSegment Crea una serie de curvas Bézier Vea la página


cuadráticas. PolyQuadraticBezierSegment.

QuadraticBezierSegment Crea una curva Bézier cuadrática. Crear una curva Bézier cuadrática.

Los segmentos de un PathFigure se combinan en una sola forma geométrica con el punto final de cada
segmento que es el punto inicial del segmento siguiente. La propiedad StartPoint de una PathFigure
especifica el punto desde el que se dibuja el primer segmento. Cada segmento posterior comienza en el
punto final del segmento anterior. Por ejemplo, se puede definir una línea vertical de 10,50 a 10,150
estableciendo la propiedad StartPoint en 10,50 y creando un LineSegment con un valor de propiedad Point
de 10,150 .
En el ejemplo siguiente se crea un PathGeometry simple que consta de un PathFigure único con un
LineSegment y se muestra mediante un elemento de Path. El StartPoint del objeto de PathFigure se
establece en 10,20 y se define un LineSegment con un punto final de 100,130 . En la ilustración siguiente se
muestra el PathGeometry creado en este ejemplo.

Objeto PathGeometry que contiene un solo LineSegment

<Path Stroke="Black" StrokeThickness="1">


<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="10,20">
<PathFigure.Segments>
<LineSegment Point="100,130"/>
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>

// Create a figure that describes a


// line from (10,20) to (100,130).
PathFigure myPathFigure = new PathFigure();
myPathFigure.StartPoint = new Point(10,20);
myPathFigure.Segments.Add(
new LineSegment(new Point(100,130),
true /* IsStroked */ ));

/// Create a PathGeometry to contain the figure.


PathGeometry myPathGeometry = new PathGeometry();
myPathGeometry.Figures.Add(myPathFigure);

// Display the PathGeometry.


Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myPathGeometry;
' Create a figure that describes a
' line from (10,20) to (100,130).
Dim myPathFigure As New PathFigure()
myPathFigure.StartPoint = New Point(10,20)
myPathFigure.Segments.Add(New LineSegment(New Point(100,130), True)) ' IsStroked

''' Create a PathGeometry to contain the figure.


Dim myPathGeometry As New PathGeometry()
myPathGeometry.Figures.Add(myPathFigure)

' Display the PathGeometry.


Dim myPath As New Path()
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myPathGeometry

Merece la pena comparar este ejemplo con el ejemplo anterior LineGeometry. La sintaxis usada para una
PathGeometry es mucho más detallada que la que se usa para un LineGeometrysimple y puede tener más
sentido usar la clase LineGeometry en este caso, pero la sintaxis detallada de la PathGeometry permite
regiones geométricas muy intrincadas y complejas.
Se pueden crear geometrías más complejas mediante una combinación de objetos de PathSegment.
En el ejemplo siguiente se usa un BezierSegment, un LineSegmenty un ArcSegment para crear la forma. En
primer lugar, el ejemplo crea una curva Bézier cúbica definiendo cuatro puntos: un punto inicial, que es el
punto final del segmento anterior, un punto final (Point3) y dos puntos de control (Point1 y Point2). Los dos
puntos de control de una curva Bézier cúbica se comportan como imanes, atraen hacia ellos partes de lo que
de otra manera sería una línea recta y generan una curva. El primer punto de control, Point1, afecta a la
parte inicial de la curva. el segundo punto de control, Point2, afecta a la parte final de la curva.
A continuación, en el ejemplo se agrega un LineSegment, que se dibuja entre el punto final del
BezierSegment anterior que lo precede al punto especificado por su propiedad LineSegment.
A continuación, en el ejemplo se agrega un ArcSegment, que se dibuja desde el punto final de la
LineSegment anterior hasta el punto especificado por su propiedad Point. En el ejemplo también se
especifica el radio x-e y (Size) del arco, un ángulo de giro (RotationAngle), un marcador que indica el tamaño
del ángulo del arco resultante (IsLargeArc) y un valor que indica en qué dirección se dibuja el arco
(SweepDirection). En la ilustración siguiente se muestra cómo se representa este ejemplo.

PathGeometry
<Path Stroke="Black" StrokeThickness="1" >
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="10,50">
<PathFigure.Segments>
<BezierSegment
Point1="100,0"
Point2="200,200"
Point3="300,100"/>
<LineSegment Point="400,100" />
<ArcSegment
Size="50,50" RotationAngle="45"
IsLargeArc="True" SweepDirection="Clockwise"
Point="200,100"/>
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>

// Create a figure.
PathFigure myPathFigure = new PathFigure();
myPathFigure.StartPoint = new Point(10,50);
myPathFigure.Segments.Add(
new BezierSegment(
new Point(100,0),
new Point(200,200),
new Point(300,100),
true /* IsStroked */ ));
myPathFigure.Segments.Add(
new LineSegment(
new Point(400,100),
true /* IsStroked */ ));
myPathFigure.Segments.Add(
new ArcSegment(
new Point(200,100),
new Size(50,50),
45,
true, /* IsLargeArc */
SweepDirection.Clockwise,
true /* IsStroked */ ));

/// Create a PathGeometry to contain the figure.


PathGeometry myPathGeometry = new PathGeometry();
myPathGeometry.Figures.Add(myPathFigure);

// Display the PathGeometry.


Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myPathGeometry;
' Create a figure.
Dim myPathFigure As New PathFigure()
myPathFigure.StartPoint = New Point(10,50)
myPathFigure.Segments.Add(New BezierSegment(New Point(100,0), New Point(200,200), New Point(300,100),
True)) ' IsStroked
myPathFigure.Segments.Add(New LineSegment(New Point(400,100), True)) ' IsStroked
myPathFigure.Segments.Add(New ArcSegment(New Point(200,100), New Size(50,50), 45, True,
SweepDirection.Clockwise, True)) ' IsStroked - IsLargeArc

''' Create a PathGeometry to contain the figure.


Dim myPathGeometry As New PathGeometry()
myPathGeometry.Figures.Add(myPathFigure)

' Display the PathGeometry.


Dim myPath As New Path()
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myPathGeometry

Se pueden crear geometrías incluso más complejas mediante el uso de varios objetos PathFigure dentro de
un PathGeometry.
En el ejemplo siguiente se crea un PathGeometry con dos objetos PathFigure, cada uno de los cuales
contiene varios objetos PathSegment. Se utiliza el PathFigure del ejemplo anterior y un PathFigure con un
PolyLineSegment y un QuadraticBezierSegment. Un PolyLineSegment se define con una matriz de puntos y
el QuadraticBezierSegment se define con un punto de control y un punto final. En la ilustración siguiente se
muestra cómo se representa este ejemplo.

Objeto PathGeometry con varias figuras


<Path Stroke="Black" StrokeThickness="1" >
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="10,50">
<PathFigure.Segments>
<BezierSegment
Point1="100,0"
Point2="200,200"
Point3="300,100"/>
<LineSegment Point="400,100" />
<ArcSegment
Size="50,50" RotationAngle="45"
IsLargeArc="True" SweepDirection="Clockwise"
Point="200,100"/>
</PathFigure.Segments>
</PathFigure>

<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PolyLineSegment Points="50,100 50,150" />
<QuadraticBezierSegment Point1="200,200" Point2="300,100"/>
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
PathGeometry myPathGeometry = new PathGeometry();

// Create a figure.
PathFigure pathFigure1 = new PathFigure();
pathFigure1.StartPoint = new Point(10,50);
pathFigure1.Segments.Add(
new BezierSegment(
new Point(100,0),
new Point(200,200),
new Point(300,100),
true /* IsStroked */ ));
pathFigure1.Segments.Add(
new LineSegment(
new Point(400,100),
true /* IsStroked */ ));
pathFigure1.Segments.Add(
new ArcSegment(
new Point(200,100),
new Size(50,50),
45,
true, /* IsLargeArc */
SweepDirection.Clockwise,
true /* IsStroked */ ));
myPathGeometry.Figures.Add(pathFigure1);

// Create another figure.


PathFigure pathFigure2 = new PathFigure();
pathFigure2.StartPoint = new Point(10,100);
Point[] polyLinePointArray =
new Point[]{ new Point(50, 100), new Point(50, 150)};
PolyLineSegment myPolyLineSegment = new PolyLineSegment();
myPolyLineSegment.Points =
new PointCollection(polyLinePointArray);
pathFigure2.Segments.Add(myPolyLineSegment);
pathFigure2.Segments.Add(
new QuadraticBezierSegment(
new Point(200,200),
new Point(300,100),
true /* IsStroked */ ));
myPathGeometry.Figures.Add(pathFigure2);

// Display the PathGeometry.


Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myPathGeometry;
Dim myPathGeometry As New PathGeometry()

' Create a figure.


Dim pathFigure1 As New PathFigure()
pathFigure1.StartPoint = New Point(10,50)
pathFigure1.Segments.Add(New BezierSegment(New Point(100,0), New Point(200,200), New Point(300,100),
True)) ' IsStroked
pathFigure1.Segments.Add(New LineSegment(New Point(400,100), True)) ' IsStroked
pathFigure1.Segments.Add(New ArcSegment(New Point(200,100), New Size(50,50), 45, True,
SweepDirection.Clockwise, True)) ' IsStroked - IsLargeArc
myPathGeometry.Figures.Add(pathFigure1)

' Create another figure.


Dim pathFigure2 As New PathFigure()
pathFigure2.StartPoint = New Point(10,100)
Dim polyLinePointArray() As Point = { New Point(50, 100), New Point(50, 150)}
Dim myPolyLineSegment As New PolyLineSegment()
myPolyLineSegment.Points = New PointCollection(polyLinePointArray)
pathFigure2.Segments.Add(myPolyLineSegment)
pathFigure2.Segments.Add(New QuadraticBezierSegment(New Point(200,200), New Point(300,100), True)) '
IsStroked
myPathGeometry.Figures.Add(pathFigure2)

' Display the PathGeometry.


Dim myPath As New Path()
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myPathGeometry

StreamGeometry
Al igual que la clase PathGeometry, un StreamGeometry define una forma geométrica compleja que puede
contener curvas, arcos y líneas. A diferencia de un PathGeometry, el contenido de un StreamGeometry no
admite enlaces de datos, animaciones ni modificaciones. Use una StreamGeometry cuando necesite describir
una geometría compleja pero no desee la sobrecarga que supone la compatibilidad con el enlace de datos, la
animación o la modificación. Debido a su eficacia, la clase StreamGeometry es una buena opción para
describir los adornos.
Para obtener un ejemplo, vea Create a Shape Using a StreamGeometry (Cómo: Crear una forma con un
objeto StreamGeometry).
Sintaxis de marcado de trazados
Los tipos PathGeometry y StreamGeometry admiten una sintaxis de atributo Lenguaje XAML (Extensible
Application Markup Language) mediante una serie especial de comandos de movimiento y dibujo. Para más
información, consulte Sintaxis de marcado de trazados.

Geometrías compuestas
Los objetos de geometría compuestos se pueden crear mediante un GeometryGroup, un
CombinedGeometryo llamando al método estático Geometry Combine.
El objeto CombinedGeometry y el método Combine realiza una operación booleana para combinar el
área definida por dos geometrías. Geometry los objetos que no tienen área se descartan. Solo se
pueden combinar dos objetos Geometry (aunque estas dos geometrías también pueden ser
geometrías compuestas).
La clase GeometryGroup crea una fusión de los objetos Geometry que contiene sin combinar su área.
Se puede agregar cualquier número de objetos Geometry a un GeometryGroup. Para obtener un
ejemplo, vea Create a Composite Shape (Cómo: Crear una forma compuesta).
Dado que no realizan una operación de combinación, el uso de objetos de GeometryGroup proporciona
ventajas de rendimiento sobre el uso de objetos de CombinedGeometry o el método Combine.

Geometrías combinadas
En la sección anterior se menciona el objeto CombinedGeometry y el método Combine combinan el área
definida por las geometrías que contienen. La enumeración GeometryCombineMode especifica cómo se
combinan las geometrías. Los valores posibles para la propiedad GeometryCombineMode son: Union,
Intersect, Excludey Xor.
En el ejemplo siguiente, se define un CombinedGeometry con un modo de combinación de Union. Tanto
Geometry1 como la Geometry2 se definen como círculos del mismo radio, pero con el desplazamiento de
los centros por 50.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">


<Path.Data>

<!-- Combines two geometries using the union combine mode. -->
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>

En el ejemplo siguiente, se define un CombinedGeometry con un modo de combinación de Xor. Tanto


Geometry1 como la Geometry2 se definen como círculos del mismo radio, pero con el desplazamiento de
los centros por 50.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">


<Path.Data>

<!-- Combines two geometries using the XOR combine mode. -->
<CombinedGeometry GeometryCombineMode="Xor">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
Para obtener otros ejemplos, vea Create a Composite Shape (Cómo: Crear una forma compuesta) y Create a
Combined Geometry (Cómo: Crear una geometría combinada).

Características de los objetos Freezable


Dado que hereda de la clase Freezable, la clase Geometry proporciona varias características especiales: los
objetos Geometry se pueden declarar como recursos XAML, compartidos entre varios objetos, convertidos
en solo lectura para mejorar el rendimiento, clonarse y realizarse seguro para subprocesos. Para obtener
más información sobre las diferentes características proporcionadas por los objetos Freezable, consulte la
información general sobre objetos Freezable.

Otras características de objeto Geometry


La clase Geometry también proporciona métodos de utilidad útiles, como los siguientes:
GetArea: obtiene el área de la Geometry.
FillContains: determina si la geometría contiene otro Geometry.
StrokeContains: determina si el trazo de un Geometry contiene un punto especificado.
Vea la clase Geometry para obtener una lista completa de sus métodos.

Vea también
Geometry
PathGeometry
Path
GeometryDrawing
Imágenes y gráficos 2D
Sintaxis de marcado de trazados
Temas "Cómo..."
Información general sobre animaciones
Información general sobre formas y dibujo básico en WPF
Información general sobre objetos Drawing
Temas "Cómo..." de objetos de geometría
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección muestran cómo usar Geometry objetos en sus aplicaciones.

En esta sección
Animar un EllipseGeometry
Animar el tamaño de un objeto ArcSegment
Controlar el relleno de una forma compuesta
Crear una geometría combinada
Crear una forma compuesta
Crear una curva Bézier cúbica
Crear una línea mediante la clase LineGeometry
Crear un LineSegment en una clase PathGeometry
Crear una forma mediante una clase PathGeometry
Crear una forma utilizando StreamGeometry
Crear una curva Bézier cuadrática
Crear un arco elíptico
Crear varios subtrazados en un PathGeometry
Definir un rectángulo usando una clase RectangleGeometry
Redondear las esquinas de un RectangleGeometry

Vea también
Brushes
Shape
Información general sobre formas y dibujo básico en WPF
Gráficos y multimedia
Procedimiento Animar un objeto EllipseGeometry
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo animar una Geometry dentro de un Path elemento. En el ejemplo siguiente, un
PointAnimation sirve para animar la Center de un EllipseGeometry.

Ejemplo
<!-- EllipseGeometryExample.xaml
This example shows how to animate an EllipseGeometry. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="EllipseGeometry Animation Example">
<Canvas Height="400" Width="400" Margin="20">

<Path Name="myPathShape"
Fill="Blue" Stroke="Black" StrokeThickness="5">
<Path.Data>
<EllipseGeometry x:Name="MyEllipseGeometry"
Center="200,200" RadiusX="25" RadiusY="50" />
</Path.Data>
<Path.Triggers>

<!-- Animates the Center position of the


EllipseGeometry. -->
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<PointAnimation
Storyboard.TargetName="MyEllipseGeometry"
Storyboard.TargetProperty="Center"
From="200,200" To="50,50" Duration="0:0:5"
AutoReverse="true" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Canvas>
</Page>

// EllipseGeometryExample.cs
//
// This sample demonstrates how to animate the center
// position of an EllipseGeometry using a PointAnimation.

using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls;

namespace Microsoft.Samples.Animation.AnimatePathShapeSample
{

public class EllipseGeometryExample : Page {


public EllipseGeometryExample()
{

NameScope.SetNameScope(this, new NameScope());

WindowTitle = "EllipseGeometry Animation Example";

Canvas myCanvas = new Canvas();


myCanvas.Width = 400;
myCanvas.Height = 400;
myCanvas.Margin = new Thickness(20);

// Create a Path object to contain the geometry.


System.Windows.Shapes.Path myPath =
new System.Windows.Shapes.Path();
myPath.Fill = System.Windows.Media.Brushes.Blue;
myPath.Stroke = System.Windows.Media.Brushes.Black;
myPath.StrokeThickness = 5;

// Create an EllipseGeometry.
System.Windows.Media.EllipseGeometry myEllipseGeometry =
new System.Windows.Media.EllipseGeometry();
myEllipseGeometry.Center = new System.Windows.Point(200, 200);
myEllipseGeometry.RadiusX = 25;
myEllipseGeometry.RadiusY = 50;

// Register a name for the geometry so that it can


// be targeted by animations.
this.RegisterName("MyEllipseGeometry", myEllipseGeometry);

// Add the geometry to the Path.


myPath.Data = myEllipseGeometry;
myCanvas.Children.Add(myPath);
this.Content = myCanvas;

// Create a PointAnimation to animate the center of the ellipse.


PointAnimation myPointAnimation = new PointAnimation();
myPointAnimation.From = new System.Windows.Point(200, 200);
myPointAnimation.To = new System.Windows.Point(50, 50);
myPointAnimation.Duration =
new Duration(TimeSpan.FromMilliseconds(5000));
myPointAnimation.AutoReverse = true;
myPointAnimation.RepeatBehavior = RepeatBehavior.Forever;

Storyboard.SetTargetName(myPointAnimation, "MyEllipseGeometry");
Storyboard.SetTargetProperty(myPointAnimation,
new PropertyPath(EllipseGeometry.CenterProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myPointAnimation);

// Use an anonymous event handler to begin the animation


// when the path is loaded.
myPath.Loaded += delegate(object sender, RoutedEventArgs args)
{
myStoryboard.Begin(myPath);
};
}
}
}

' EllipseGeometryExample.cs
'
' This sample demonstrates how to animate the center
' position of an EllipseGeometry using a PointAnimation.

Imports System.Windows
Imports System.Windows.Navigation
Imports System.Windows.Navigation
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Imports System.Windows.Controls

Namespace Microsoft.Samples.Animation.AnimatePathShapeSample

' Create the demonstration.


Public Class PathElementAnimationExample
Inherits Page

Private Dim WithEvents myPath As Path


Private Dim myStoryboard As Storyboard

Public Sub New()

NameScope.SetNameScope(Me, new NameScope())

Me.WindowTitle = "EllipseGeometry Animation Example"

Dim myCanvas As New Canvas()


myCanvas.Width = 400
myCanvas.Height = 400
myCanvas.Margin = New Thickness(20)

' Create a Path object to contain the geometry.


myPath = New Path()
myPath.Fill = Brushes.Blue
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 5

' Create an EllipseGeometry.


Dim myEllipseGeometry As New EllipseGeometry()
myEllipseGeometry.Center = New System.Windows.Point(200, 200)
myEllipseGeometry.RadiusX = 25
myEllipseGeometry.RadiusY = 50

' Register a name for the geometry so that it can


' be targeted by animations.
Me.RegisterName("MyEllipseGeometry", myEllipseGeometry)

' Add the geometry to the Path.


myPath.Data = myEllipseGeometry
myCanvas.Children.Add(myPath)
Me.Content = myCanvas

' Create a PointAnimation to animate the center of the Ellipse.


Dim myPointAnimation As New PointAnimation()
myPointAnimation.From = New System.Windows.Point(200, 200)
myPointAnimation.To = New System.Windows.Point(50, 50)
myPointAnimation.Duration = _
New Duration(TimeSpan.FromMilliseconds(5000))
myPointAnimation.AutoReverse = True
myPointAnimation.RepeatBehavior = RepeatBehavior.Forever

Storyboard.SetTargetName(myPointAnimation, "MyEllipseGeometry")
Storyboard.SetTargetProperty(myPointAnimation, _
new PropertyPath(EllipseGeometry.CenterProperty))
myStoryboard = New Storyboard()
myStoryboard.Children.Add(myPointAnimation)

End Sub

' Start the animation when the path is loaded.


Private Sub myPath_Loaded(ByVal sender as object, ByVal args as RoutedEventArgs) Handles myPath.Loaded

myStoryboard.Begin(myPath)
End Sub

End Class
End Namespace

Vea también
Información general sobre animaciones
Información general sobre geometría
Cómo: Animar el tamaño de un objeto ArcSegment
20/02/2020 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo animar la propiedad Size de una ArcSegment.

Ejemplo
En el ejemplo siguiente se crea una ArcSegment que anima su Size cuando se carga en la pantalla.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;

namespace SDKSamples
{
public class SizeAnimationExample : Page
{
public SizeAnimationExample()
{

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

// Create an ArcSegment to define the geometry of the path.


// The Size property of this segment is animated.
ArcSegment myArcSegment = new ArcSegment();
myArcSegment.Size = new Size(90, 80);
myArcSegment.SweepDirection = SweepDirection.Clockwise;
myArcSegment.Point = new Point(500, 200);

// Assign the segment a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"myArcSegment", myArcSegment);

PathSegmentCollection myPathSegmentCollection = new PathSegmentCollection();


myPathSegmentCollection.Add(myArcSegment);

// Create a PathFigure to be used for the PathGeometry of myPath.


PathFigure myPathFigure = new PathFigure();

// Set the starting point for the PathFigure specifying that the
// geometry starts at point 100,200.
myPathFigure.StartPoint = new Point(100, 200);

myPathFigure.Segments = myPathSegmentCollection;

PathFigureCollection myPathFigureCollection = new PathFigureCollection();


myPathFigureCollection.Add(myPathFigure);

PathGeometry myPathGeometry = new PathGeometry();


myPathGeometry.Figures = myPathFigureCollection;

// Create a path to draw a geometry with.


Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
// specify the shape of the path using the path geometry.
myPath.Data = myPathGeometry;

SizeAnimation mySizeAnimation = new SizeAnimation();


mySizeAnimation.Duration = TimeSpan.FromSeconds(2);

// Set the animation to repeat forever.


mySizeAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the From and To properties of the animation.


mySizeAnimation.From = new Size(90, 80);
mySizeAnimation.To = new Size(200, 200);

// Set the animation to target the Size property


// of the object named "myArcSegment."
Storyboard.SetTargetName(mySizeAnimation, "myArcSegment");
Storyboard.SetTargetProperty(
mySizeAnimation, new PropertyPath(ArcSegment.SizeProperty));

// Create a storyboard to apply the animation.


Storyboard ellipseStoryboard = new Storyboard();
ellipseStoryboard.Children.Add(mySizeAnimation);

// Start the storyboard when the Path loads.


myPath.Loaded += delegate(object sender, RoutedEventArgs e)
{
ellipseStoryboard.Begin(this);
};

Canvas containerCanvas = new Canvas();


containerCanvas.Children.Add(myPath);

Content = containerCanvas;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation
Imports System.Windows.Media

Namespace SDKSamples
Public Class SizeAnimationExample
Inherits Page
Public Sub New()

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

' Create an ArcSegment to define the geometry of the path.


' The Size property of this segment is animated.
Dim myArcSegment As New ArcSegment()
With myArcSegment
.Size = New Size(90, 80)
.SweepDirection = SweepDirection.Clockwise
.Point = New Point(500, 200)
End With

' Assign the segment a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("myArcSegment", myArcSegment)

Dim myPathSegmentCollection As New PathSegmentCollection()


Dim myPathSegmentCollection As New PathSegmentCollection()
myPathSegmentCollection.Add(myArcSegment)

' Create a PathFigure to be used for the PathGeometry of myPath.


Dim myPathFigure As New PathFigure()

' Set the starting point for the PathFigure specifying that the
' geometry starts at point 100,200.
myPathFigure.StartPoint = New Point(100, 200)

myPathFigure.Segments = myPathSegmentCollection

Dim myPathFigureCollection As New PathFigureCollection()


myPathFigureCollection.Add(myPathFigure)

Dim myPathGeometry As New PathGeometry()


myPathGeometry.Figures = myPathFigureCollection

' Create a path to draw a geometry with.


Dim myPath As New Path()
With myPath
.Stroke = Brushes.Black
.StrokeThickness = 1

' specify the shape of the path using the path geometry.
.Data = myPathGeometry
End With

Dim mySizeAnimation As New SizeAnimation()


With mySizeAnimation
.Duration = TimeSpan.FromSeconds(2)

' Set the animation to repeat forever.


.RepeatBehavior = RepeatBehavior.Forever

' Set the From and To properties of the animation.


.From = New Size(90, 80)
.To = New Size(200, 200)
End With

' Set the animation to target the Size property


' of the object named "myArcSegment."
Storyboard.SetTargetName(mySizeAnimation, "myArcSegment")
Storyboard.SetTargetProperty(mySizeAnimation, New PropertyPath(ArcSegment.SizeProperty))

' Create a storyboard to apply the animation.


Dim ellipseStoryboard As New Storyboard()
ellipseStoryboard.Children.Add(mySizeAnimation)

' Start the storyboard when the Path loads.


AddHandler myPath.Loaded, Sub(sender As Object, e As RoutedEventArgs) ellipseStoryboard.Begin(Me)

Dim containerCanvas As New Canvas()


containerCanvas.Children.Add(myPath)

Content = containerCanvas
End Sub
End Class
End Namespace

Para obtener ejemplos adicionales de geometría y animación, vea el ejemplo de geometrías.

Consulte también
Size
ArcSegment
Información general sobre animaciones
Información general sobre geometría
Temas de procedimientos de las geometrías
Temas de procedimientos de animación y control de tiempo
Procedimiento Controlar el relleno de una forma
compuesta
23/10/2019 • 7 minutes to read • Edit Online

La FillRule propiedad GeometryGroup de oPathGeometry, especifica una "regla" que la forma compuesta utiliza
para determinar si un punto determinado forma parte de la geometría. Existen dos valores posibles para FillRule:
EvenOdd y Nonzero. En las secciones siguientes se describe cómo usar estas dos reglas.
EvenOdd: Esta regla determina si un punto está en la región de relleno dibujando un rayo desde ese punto hasta
el infinito en cualquier dirección y contando el número de segmentos de trazado dentro de la forma especificada
que cruza el rayo. Si este número es impar, el punto está dentro; si es par, el punto está fuera.
Por ejemplo, el código XAML siguiente crea una forma compuesta formada por una serie de anillos concéntricos
(destino) FillRule con un EvenOddestablecido en.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">


<Path.Data>
<GeometryGroup FillRule="EvenOdd">
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
<EllipseGeometry RadiusX="70" RadiusY="70" Center="75,75" />
<EllipseGeometry RadiusX="100" RadiusY="100" Center="75,75" />
<EllipseGeometry RadiusX="120" RadiusY="120" Center="75,75" />
</GeometryGroup>
</Path.Data>
</Path>

La siguiente ilustración muestra la forma creada en el ejemplo anterior.

En la ilustración anterior, observe que no se rellenan el centro y el tercer anillo. Esto se debe a que un radio
dibujado desde cualquier punto dentro de esos dos anillos pasa a través de un número par de segmentos. Vea la
ilustración siguiente:

NonZero: Esta regla determina si un punto está en la región de relleno del trazado dibujando un rayo desde ese
punto hasta el infinito en cualquier dirección y examinando después los lugares donde un segmento de la forma
cruza el rayo. Partiendo de cero, sume una ubicación cada vez que un segmento cruce el radio de izquierda a
derecha y reste una ubicación cada vez que un segmento de trazado cruce el radio de derecha a izquierda.
Después de contar el número de veces que cruza, si el resultado es cero, el punto está fuera del trazado. De lo
contrario, está dentro.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">


<Path.Data>
<GeometryGroup FillRule="NonZero">
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
<EllipseGeometry RadiusX="70" RadiusY="70" Center="75,75" />
<EllipseGeometry RadiusX="100" RadiusY="100" Center="75,75" />
<EllipseGeometry RadiusX="120" RadiusY="120" Center="75,75" />
</GeometryGroup>
</Path.Data>
</Path>

Con el ejemplo anterior, un valor de Nonzero para FillRule proporciona la siguiente ilustración como resultado:

Como puede ver, se rellenan todos los anillos. Esto es porque todos los segmentos se ejecutan en la misma
dirección de modo que un radio dibujado desde cualquier punto cruzará uno o más segmentos y la suma de las
veces que cruza no será igual a cero. Por ejemplo, en la siguiente ilustración, las flechas rojas representan la
dirección en la que se dibujan los segmentos y la flecha blanca representa un rayo arbitrario que se ejecuta desde
un punto en el anillo más interno. A partir de un valor de cero, para cada segmento que cruza el radio, se agrega
un valor de uno porque el segmento cruza el radio de izquierda a derecha.

Para demostrar mejor el comportamiento de Nonzero la regla, se requiere una forma más compleja con
segmentos que se ejecuten en diferentes direcciones. En el código XAML siguiente se crea una forma similar
PathGeometry EllipseGeometry a la del ejemplo anterior, salvo que se crea con un en su lugar, que crea cuatro
arcos concéntricos en lugar de círculos concéntricos totalmente cerrados.
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<GeometryGroup FillRule="NonZero">
<PathGeometry>
<PathGeometry.Figures>

<!-- Inner Ring -->


<PathFigure StartPoint="10,120">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="50,50" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,120" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>

<!-- Second Ring -->


<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="70,70" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,100" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>

<!-- Third Ring (Not part of path) -->


<PathFigure StartPoint="10,70">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="100,100" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,70"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>

<!-- Outer Ring -->


<PathFigure StartPoint="10,300">
<PathFigure.Segments>
<ArcSegment Size="130,130" IsLargeArc="True" SweepDirection="Clockwise" Point="25,300" />
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</GeometryGroup>
</Path.Data>
</Path>

La siguiente ilustración muestra la forma creada en el ejemplo anterior.

Observe que no se rellena el tercer arco contando desde el centro. En la ilustración siguiente se muestra por qué
es. En la ilustración, las flechas rojas representan la dirección en que se dibujan los segmentos. Las dos flechas
blancas representan dos radios arbitrarios que parten desde un punto en la región "no rellena". Como puede
observarse en la ilustración, la suma de los valores de un radio determinado que cruza los segmentos en su
trazado es cero. Como se ha definido anteriormente, una suma de cero significa que el punto no forma parte de la
geometría (no es parte del relleno), mientras que la suma que no es igual a cero, incluido un valor negativo, sí
forma parte de la geometría.

NOTE
Para los fines de FillRule, todas las formas se consideran cerradas. Si hay un hueco en un segmento, dibuje una línea
imaginaria para cerrarlo. En el ejemplo anterior, hay huecos pequeños en los anillos. Por tanto, se podría esperar que un
radio que atraviesa el hueco ofrezca un resultado distinto al de un radio que se ejecuta en otra dirección. A continuación se
muestra una ilustración ampliada de uno de estos huecos y el "segmento imaginario" (segmento que se dibuja con el
FillRulefin de aplicar el) que lo cierra.

Ejemplo
Vea también
Crear una forma compuesta
Información general sobre geometría
Procedimiento Crear una geometría combinada
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo se combinan las geometrías. Para combinar dos geometrías, utilice un
CombinedGeometry objeto. Establezca su Geometry1 y Geometry2 propiedades con las dos geometrías para
combinar y establecer el GeometryCombineMode propiedad, que determina cómo se se combinan las geometrías
juntos, para Union , Intersect , Exclude , o Xor .
Para crear una geometría compuesta de dos o más geometrías, utilice un GeometryGroup.

Ejemplo
En el ejemplo siguiente, un CombinedGeometry se define con el modo de combinación de geometría Exclude .
Ambos Geometry1 y Geometry2 se definen como círculos del mismo radio, pero con los centros desplazados en
50.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">


<Path.Data>

<!-- Combines two geometries using the exclude combine mode. -->
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>

Exclusión de geometría combinada


En el marcado siguiente, un CombinedGeometry se define con el modo de combinación Intersect . Ambos
Geometry1 y Geometry2 se definen como círculos del mismo radio, pero con los centros desplazados en 50.
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>

<!-- Combines two geometries using the intersect combine mode. -->
<CombinedGeometry GeometryCombineMode="Intersect">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>

Geometría combinada forman una intersección


En el marcado siguiente, un CombinedGeometry se define con el modo de combinación Union . Ambos
Geometry1 y Geometry2 se definen como círculos del mismo radio, pero con los centros desplazados en 50.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">


<Path.Data>

<!-- Combines two geometries using the union combine mode. -->
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>

Unión de geometría combinada


En el marcado siguiente, un CombinedGeometry se define con el modo de combinación Xor . Ambos Geometry1
y Geometry2 se definen como círculos del mismo radio, pero con los centros desplazados en 50.
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>

<!-- Combines two geometries using the XOR combine mode. -->
<CombinedGeometry GeometryCombineMode="Xor">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>

Xor geometría combinada


Cómo: Crear una forma compuesta
20/02/2020 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo crear formas compuestas mediante Geometry objetos y cómo mostrarlas
mediante un elemento Path. En el ejemplo siguiente, se usa un LineGeometry, EllipseGeometryy un
RectangleGeometry con un GeometryGroup para crear una forma compuesta. A continuación, las geometrías se
dibujan utilizando un elemento Path.

Ejemplo
<!-- Displays the geometry. -->
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>

<!-- Creates a composite shape from three geometries. -->


<GeometryGroup FillRule="EvenOdd">
<LineGeometry StartPoint="10,10" EndPoint="50,30" />
<EllipseGeometry Center="40,70" RadiusX="30" RadiusY="30" />
<RectangleGeometry Rect="30,55 100 30" />
</GeometryGroup>
</Path.Data>
</Path>
// Create a Path to be drawn to the screen.
Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(255, 204, 204, 255);
myPath.Fill = mySolidColorBrush;

// Create the line geometry to add to the Path


LineGeometry myLineGeometry = new LineGeometry();
myLineGeometry.StartPoint = new Point(10, 10);
myLineGeometry.EndPoint = new Point(50, 30);

// Create the ellipse geometry to add to the Path


EllipseGeometry myEllipseGeometry = new EllipseGeometry();
myEllipseGeometry.Center = new Point(40, 70);
myEllipseGeometry.RadiusX = 30;
myEllipseGeometry.RadiusY = 30;

// Create a rectangle geometry to add to the Path


RectangleGeometry myRectGeometry = new RectangleGeometry();
myRectGeometry.Rect = new Rect(30, 55, 100, 30);

// Add all the geometries to a GeometryGroup.


GeometryGroup myGeometryGroup = new GeometryGroup();
myGeometryGroup.Children.Add(myLineGeometry);
myGeometryGroup.Children.Add(myEllipseGeometry);
myGeometryGroup.Children.Add(myRectGeometry);

myPath.Data = myGeometryGroup;

// Add path shape to the UI.


StackPanel mainPanel = new StackPanel();
mainPanel.Children.Add(myPath);
this.Content = mainPanel;
' Create a Path to be drawn to the screen.
Dim myPath As New Path()
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
Dim mySolidColorBrush As New SolidColorBrush()
mySolidColorBrush.Color = Color.FromArgb(255, 204, 204, 255)
myPath.Fill = mySolidColorBrush

' Create the line geometry to add to the Path


Dim myLineGeometry As New LineGeometry()
myLineGeometry.StartPoint = New Point(10, 10)
myLineGeometry.EndPoint = New Point(50, 30)

' Create the ellipse geometry to add to the Path


Dim myEllipseGeometry As New EllipseGeometry()
myEllipseGeometry.Center = New Point(40, 70)
myEllipseGeometry.RadiusX = 30
myEllipseGeometry.RadiusY = 30

' Create a rectangle geometry to add to the Path


Dim myRectGeometry As New RectangleGeometry()
myRectGeometry.Rect = New Rect(30, 55, 100, 30)

' Add all the geometries to a GeometryGroup.


Dim myGeometryGroup As New GeometryGroup()
myGeometryGroup.Children.Add(myLineGeometry)
myGeometryGroup.Children.Add(myEllipseGeometry)
myGeometryGroup.Children.Add(myRectGeometry)

myPath.Data = myGeometryGroup

' Add path shape to the UI.


Dim mainPanel As New StackPanel()
mainPanel.Children.Add(myPath)
Me.Content = mainPanel

La siguiente ilustración muestra la forma creada en el ejemplo anterior.

Geometría compuesta
Las formas más complejas, como polígonos y formas con segmentos curvos, se pueden crear con un
PathGeometry. Para ver un ejemplo en el que se muestra cómo crear una forma mediante un PathGeometry, vea
crear una forma mediante una PathGeometry. Aunque en este ejemplo se representa una forma en la pantalla
mediante un elemento Path, Geometry objetos también se pueden usar para describir el contenido de un
GeometryDrawing o de un DrawingContext. También se pueden usar para el recorte y la prueba de
posicionamiento.
Este ejemplo forma parte de un ejemplo más extenso; para obtener el ejemplo completo, vea Ejemplo de
geometrías.
Cómo: Crear una curva Bézier cúbica
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo crear una curva Bézier cúbica. Para crear una curva Bézier cúbica, utilice las
clases PathGeometry, PathFigurey BezierSegment. Para mostrar la geometría resultante, use un elemento Path o
Úselo con un GeometryDrawing o un DrawingContext. En los ejemplos siguientes, se dibuja una curva Bézier
cúbica de (10, 100) a (300, 100). La curva tiene puntos de control de (100, 0) y (200, 200).

Ejemplo
[xaml]
En Lenguaje XAML (Extensible Application Markup Language), puede usar la sintaxis de marcado abreviada para
describir una ruta de acceso.

<Path Stroke="Black" StrokeThickness="1"


Data="M 10,100 C 100,0 200,200 300,100" />

[xaml]
En XAML, también puede dibujar una curva Bézier cúbica mediante etiquetas de objeto. El siguiente ejemplo es
equivalente al ejemplo anterior de XAML.

<Path Stroke="Black" StrokeThickness="1">


<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<BezierSegment Point1="100,0" Point2="200,200" Point3="300,100" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>

Este ejemplo forma parte de un ejemplo más extenso; para obtener el ejemplo completo, vea Ejemplo de
geometrías.

Consulte también
Crear un arco elíptico
Crear un LineSegment en una clase PathGeometry
Crear una curva Bézier cúbica
Crear una curva Bézier cuadrática
Procedimiento Crear una línea mediante la clase
LineGeometry
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el LineGeometry clase para describir una línea. Un LineGeometry se define
por sus puntos inicial y final.

Ejemplo
El ejemplo siguiente muestra cómo crear y representar un LineGeometry. Un Path elemento se usa para
representar la línea. Dado que una línea no tiene ninguna área, el Path del objeto Fill no se ha especificado; en su
lugar el Stroke y StrokeThickness se usan las propiedades.

<Path Stroke="Black" StrokeThickness="1" >


<Path.Data>
<LineGeometry StartPoint="10,20" EndPoint="100,130" />
</Path.Data>
</Path>

LineGeometry myLineGeometry = new LineGeometry();


myLineGeometry.StartPoint = new Point(10,20);
myLineGeometry.EndPoint = new Point(100,130);

Path myPath = new Path();


myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myLineGeometry;

Dim myLineGeometry As New LineGeometry()


myLineGeometry.StartPoint = New Point(10,20)
myLineGeometry.EndPoint = New Point(100,130)

Dim myPath As New Path()


myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myLineGeometry

Objeto LineGeometry dibujado desde (10,20) hasta (100,130)


Otras clases de geometría simple incluyen LineGeometry y EllipseGeometry. Estas geometrías, así como otras más
complejas, también se pueden crear mediante un PathGeometry o StreamGeometry. Para obtener más
información, consulte el información general sobre geometría.

Vea también
Información general sobre geometría
Crear una forma compuesta
Crear una forma mediante una clase PathGeometry
Cómo: Crear un segmento de línea en una clase
PathGeometry
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo crear un segmento de línea. Para crear un segmento de línea, use las clases
PathGeometry, PathFigurey LineSegment.

Ejemplo
En los ejemplos siguientes se dibuja una LineSegment de (10, 50) a (200, 70). En la ilustración siguiente se
muestra el LineSegmentresultante; se ha agregado un fondo de cuadrícula para mostrar el sistema de
coordenadas.

Un LineSegment dibujado de (10, 50) a (200, 70)


[xaml]
En Lenguaje XAML (Extensible Application Markup Language), puede utilizar la sintaxis de atributo para describir
un trazado.

<Path Stroke="Black" StrokeThickness="1"


Data="M 10,50 L 200,70" />

[xaml]
(Tenga en cuenta que esta sintaxis de atributo crea realmente un StreamGeometry, una versión más ligera de un
PathGeometry. Para más información, consulte la página Sintaxis de marcado de trazados).
En XAML, también puede dibujar un segmento de línea con la sintaxis de elemento de objeto. El siguiente ejemplo
es equivalente al ejemplo anterior de XAML.

<Path Stroke="Black" StrokeThickness="1">


<Path.Data>
<PathGeometry>
<PathFigure StartPoint="10,50">
<LineSegment Point="200,70" />
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
PathFigure myPathFigure = new PathFigure();
myPathFigure.StartPoint = new Point(10, 50);

LineSegment myLineSegment = new LineSegment();


myLineSegment.Point = new Point(200, 70);

PathSegmentCollection myPathSegmentCollection = new PathSegmentCollection();


myPathSegmentCollection.Add(myLineSegment);

myPathFigure.Segments = myPathSegmentCollection;

PathFigureCollection myPathFigureCollection = new PathFigureCollection();


myPathFigureCollection.Add(myPathFigure);

PathGeometry myPathGeometry = new PathGeometry();


myPathGeometry.Figures = myPathFigureCollection;

Path myPath = new Path();


myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myPathGeometry;

Dim myPathFigure As New PathFigure()


myPathFigure.StartPoint = New Point(10, 50)

Dim myLineSegment As New LineSegment()


myLineSegment.Point = New Point(200, 70)

Dim myPathSegmentCollection As New PathSegmentCollection()


myPathSegmentCollection.Add(myLineSegment)

myPathFigure.Segments = myPathSegmentCollection

Dim myPathFigureCollection As New PathFigureCollection()


myPathFigureCollection.Add(myPathFigure)

Dim myPathGeometry As New PathGeometry()


myPathGeometry.Figures = myPathFigureCollection

Dim myPath As New Path()


myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myPathGeometry

Este ejemplo forma parte de un ejemplo más extenso; para obtener el ejemplo completo, vea Ejemplo de
geometrías.

Consulte también
PathFigure
PathGeometry
GeometryDrawing
Path
Información general sobre geometría
Cómo: Crear una forma mediante una clase
PathGeometry
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo crear una forma mediante la clase PathGeometry. PathGeometry objetos se
componen de uno o varios objetos PathFigure; cada PathFigure representa una "figura" o forma diferente. Cada
PathFigure se compone de uno o varios objetos PathSegment, cada uno de los cuales representa una parte
conectada de la figura o forma. Los tipos de segmento incluyen LineSegment, ArcSegmenty BezierSegment.

Ejemplo
En el ejemplo siguiente se usa una PathGeometry para crear un triángulo. El PathGeometry se muestra utilizando
un elemento Path.

<Path Stroke="Black" StrokeThickness="1">


<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure IsClosed="True" StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="100,100" />
<LineSegment Point="100,50" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>

La siguiente ilustración muestra la forma creada en el ejemplo anterior.

Triángulo creado con PathGeometry


En el ejemplo anterior se mostró cómo crear una forma relativamente simple, un triángulo. También se puede
utilizar una PathGeometry para crear formas más complejas, como arcos y curvas. Para obtener ejemplos, vea
crear un arco elíptico, crear una curva Bézier cúbicay crear una curva Bézier cuadrática.
Este ejemplo forma parte de un ejemplo más extenso; para obtener el ejemplo completo, vea Ejemplo de
geometrías.
Consulte también
Path
GeometryDrawing
Información general sobre geometría
Ejemplo de geometrías
Procedimiento Crear una forma mediante un objeto
StreamGeometry
23/10/2019 • 6 minutes to read • Edit Online

StreamGeometry es una alternativa ligera a PathGeometry para crear formas geométricas. Use un
StreamGeometry cuando necesite describir una geometría compleja pero no desea la sobrecarga de admitir el
enlace de datos, animaciones ni modificaciones. Por ejemplo, debido a su eficacia, la StreamGeometry clase es una
buena elección para describir adornos.

Ejemplo
En el ejemplo siguiente se usa la sintaxis de atributo para crear un triangular StreamGeometry en XAML.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>

<Path Data="F0 M10,100 L100,100 100,50Z"


StrokeThickness="1" Stroke="Black"/>

</StackPanel>
</Page>

Para obtener más información acerca de StreamGeometry sintaxis de atributo, vea el sintaxis de marcado de
trazados página.

Ejemplo
El ejemplo siguiente se usa un StreamGeometry para definir un triángulo en el código. En primer lugar, el ejemplo
se crea un StreamGeometry, a continuación, obtiene un StreamGeometryContext y lo usa para describir el
triángulo.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace SDKSample
{
// Use StreamGeometry with StreamGeometryContext to define a triangle shape.
public partial class StreamGeometryTriangleExample : Page
{
public StreamGeometryTriangleExample()
{
// Create a path to draw a geometry with.
Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;

// Create a StreamGeometry to use to specify myPath.


StreamGeometry geometry = new StreamGeometry();
geometry.FillRule = FillRule.EvenOdd;

// Open a StreamGeometryContext that can be used to describe this StreamGeometry


// object's contents.
using (StreamGeometryContext ctx = geometry.Open())
{

// Begin the triangle at the point specified. Notice that the shape is set to
// be closed so only two lines need to be specified below to make the triangle.
ctx.BeginFigure(new Point(10, 100), true /* is filled */, true /* is closed */);

// Draw a line to the next specified point.


ctx.LineTo(new Point(100, 100), true /* is stroked */, false /* is smooth join */);

// Draw another line to the next specified point.


ctx.LineTo(new Point(100, 50), true /* is stroked */, false /* is smooth join */);
}

// Freeze the geometry (make it unmodifiable)


// for additional performance benefits.
geometry.Freeze();

// Specify the shape (triangle) of the Path using the StreamGeometry.


myPath.Data = geometry;

// Add path shape to the UI.


StackPanel mainPanel = new StackPanel();
mainPanel.Children.Add(myPath);
this.Content = mainPanel;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes

Namespace SDKSample
' Use StreamGeometry with StreamGeometryContext to define a triangle shape.
Partial Public Class StreamGeometryTriangleExample
Inherits Page
Public Sub New()
' Create a path to draw a geometry with.
Dim myPath As New Path()
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1

' Create a StreamGeometry to use to specify myPath.


Dim geometry As New StreamGeometry()
geometry.FillRule = FillRule.EvenOdd

' Open a StreamGeometryContext that can be used to describe this StreamGeometry


' object's contents.
Using ctx As StreamGeometryContext = geometry.Open()

' Begin the triangle at the point specified. Notice that the shape is set to
' be closed so only two lines need to be specified below to make the triangle.
ctx.BeginFigure(New Point(10, 100), True, True) ' is closed - is filled

' Draw a line to the next specified point.


ctx.LineTo(New Point(100, 100), True, False) ' is smooth join - is stroked

' Draw another line to the next specified point.


ctx.LineTo(New Point(100, 50), True, False) ' is smooth join - is stroked
End Using

' Freeze the geometry (make it unmodifiable)


' for additional performance benefits.
geometry.Freeze()

' Specify the shape (triangle) of the Path using the StreamGeometry.
myPath.Data = geometry

' Add path shape to the UI.


Dim mainPanel As New StackPanel()
mainPanel.Children.Add(myPath)
Me.Content = mainPanel
End Sub
End Class
End Namespace

Ejemplo
En el ejemplo siguiente se crea un método que utiliza un StreamGeometry y StreamGeometryContext para definir
una forma geométrica según los parámetros especificados.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace SDKSample
{
public partial class StreamGeometryExample : Page
{
public StreamGeometryExample()
{
// Create a path to draw a geometry with.
Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;

// Create a StreamGeometry to use to specify myPath.


StreamGeometry theGeometry = BuildRegularPolygon(new Point(200, 200), 200, 8, 0);
theGeometry.FillRule = FillRule.EvenOdd;

// Freeze the geometry (make it unmodifiable)


// for additional performance benefits.
theGeometry.Freeze();

// Use the StreamGeometry returned by the BuildRegularPolygon to


// specify the shape of the path.
myPath.Data = theGeometry;

// Add path shape to the UI.


StackPanel mainPanel = new StackPanel();
mainPanel.Children.Add(myPath);
this.Content = mainPanel;
}

StreamGeometry BuildRegularPolygon(Point c, double r, int numSides, double offsetDegree)


{
// c is the center, r is the radius,
// numSides the number of sides, offsetDegree the offset in Degrees.
// Do not add the last point.

StreamGeometry geometry = new StreamGeometry();

using (StreamGeometryContext ctx = geometry.Open())


{
ctx.BeginFigure(new Point(), true /* is filled */, true /* is closed */);

double step = 2 * Math.PI / Math.Max(numSides, 3);


Point cur = c;

double a = Math.PI * offsetDegree / 180.0;


for (int i = 0; i < numSides; i++, a += step)
{
cur.X = c.X + r * Math.Cos(a);
cur.Y = c.Y + r * Math.Sin(a);
ctx.LineTo(cur, true /* is stroked */, false /* is smooth join */);
}
}

return geometry;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes

Namespace SDKSample
Partial Public Class StreamGeometryExample
Inherits Page
Public Sub New()
' Create a path to draw a geometry with.
Dim myPath As New Path()
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1

' Create a StreamGeometry to use to specify myPath.


Dim theGeometry As StreamGeometry = BuildRegularPolygon(New Point(200, 200), 200, 8, 0)
theGeometry.FillRule = FillRule.EvenOdd

' Freeze the geometry (make it unmodifiable)


' for additional performance benefits.
theGeometry.Freeze()

' Use the StreamGeometry returned by the BuildRegularPolygon to


' specify the shape of the path.
myPath.Data = theGeometry

' Add path shape to the UI.


Dim mainPanel As New StackPanel()
mainPanel.Children.Add(myPath)
Me.Content = mainPanel
End Sub

Private Function BuildRegularPolygon(ByVal c As Point, ByVal r As Double, ByVal numSides As Integer,


ByVal offsetDegree As Double) As StreamGeometry
' c is the center, r is the radius,
' numSides the number of sides, offsetDegree the offset in Degrees.
' Do not add the last point.

Dim geometry As New StreamGeometry()

Using ctx As StreamGeometryContext = geometry.Open()


ctx.BeginFigure(New Point(), True, True) ' is closed - is filled

Dim [step] As Double = 2 * Math.PI / Math.Max(numSides, 3)


Dim cur As Point = c

Dim a As Double = Math.PI * offsetDegree / 180.0


Dim i As Integer = 0
Do While i < numSides
cur.X = c.X + r * Math.Cos(a)
cur.Y = c.Y + r * Math.Sin(a)
ctx.LineTo(cur, True, False) ' is smooth join - is stroked
i += 1
a += [step]
Loop
End Using

Return geometry
End Function
End Class
End Namespace

Vea también
PathGeometry
StreamGeometry
StreamGeometryContext
Crear una forma mediante una clase PathGeometry
Información general sobre geometría
Cómo: Crear una curva Bézier cuadrática
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo crear una curva Bézier cuadrática. Para crear una curva Bézier cuadrática, utilice
las clases PathGeometry, PathFigurey QuadraticBezierSegment.

Ejemplo
En los ejemplos siguientes, se dibuja una curva Bézier cuadrática de (10.100) a (300.100). La curva tiene un punto
de control de (200.200).
[xaml]
En Lenguaje XAML (Extensible Application Markup Language), puede utilizar la sintaxis de atributo para describir
una ruta de acceso.

<Path Stroke="Black" StrokeThickness="1"


Data="M 10,100 Q 200,200 300,100" />

[xaml]
(Tenga en cuenta que esta sintaxis de atributo crea realmente un StreamGeometry, una versión más ligera de un
PathGeometry. Para más información, consulte la página Sintaxis de marcado de trazados).
En XAML, también puede dibujar una curva Bézier cuadrática mediante la sintaxis del elemento de objeto. El
siguiente ejemplo es equivalente al ejemplo anterior de XAML.

<Path Stroke="Black" StrokeThickness="1">


<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment Point1="200,200" Point2="300,100" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>

Este ejemplo forma parte de un ejemplo más extenso; para obtener el ejemplo completo, vea Ejemplo de
geometrías.

Consulte también
Crear un arco elíptico
Crear una curva Bézier cúbica
Cómo: Crear un arco elíptico
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo dibujar un arco elíptico. Para crear un arco elíptico, utilice las clases
PathGeometry, PathFigurey ArcSegment.

Ejemplo
En los ejemplos siguientes, se dibuja un arco elíptico de (10.100) a (200.100). El arco tiene una Size de 100 por
píxeles independientes del dispositivo 50, una RotationAngle de 45 grados, una IsLargeArc configuración de
true y una SweepDirection de Counterclockwise.

[xaml]
En Lenguaje XAML (Extensible Application Markup Language), puede utilizar la sintaxis de atributo para
describir una ruta de acceso.

<Path Stroke="Black" StrokeThickness="1"


Data="M 10,100 A 100,50 45 1 0 200,100" />

[xaml]
(Tenga en cuenta que esta sintaxis de atributo crea realmente un StreamGeometry, una versión más ligera de un
PathGeometry. Para más información, consulte la página Sintaxis de marcado de trazados).
En XAML, también puede dibujar un arco elíptico mediante etiquetas de objeto explícitamente. Lo siguiente es
equivalente al marcado de XAML anterior.

<Path Stroke="Black" StrokeThickness="1">


<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="100,50" RotationAngle="45" IsLargeArc="True"
SweepDirection="CounterClockwise" Point="200,100" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>

Este ejemplo forma parte de un ejemplo mayor. Para obtener el ejemplo completo, vea el ejemplo de geometrías.

Consulte también
Crear una curva Bézier cuadrática
Crear una curva Bézier cúbica
Procedimiento Crear varios subtrazados en un objeto
PathGeometry
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo crear varios subtrazados en un PathGeometry. Para crear varios subtrazados,
cree un PathFigure para cada subtrazado.

Ejemplo
El ejemplo siguiente crea dos subtrazados, cada uno de ellos un triángulo.

<Path Stroke="Black" StrokeThickness="1">


<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure IsClosed="True" StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="100,100" />
<LineSegment Point="100,50" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
<PathFigure IsClosed="True" StartPoint="10,10">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="100,10" />
<LineSegment Point="100,40" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>

El ejemplo siguiente muestra cómo crear varios subtrazados mediante un Path y XAML sintaxis de atributo. Cada
M crea una subruta de acceso nuevo para que el ejemplo crea dos subtrazados cada dibuja un triángulo.

<Path Stroke="Black" StrokeThickness="1"


Data="M 10,100 L 100,100 100,50 Z M 10,10 100,10 100,40 Z" />

(Tenga en cuenta que esta sintaxis de atributo se crea en realidad un StreamGeometry, una versión ligera de un
PathGeometry. Para más información, consulte la página Sintaxis de marcado de trazados).

Vea también
Información general sobre geometría
Procedimiento Definir un rectángulo mediante una
clase RectangleGeometry
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se describe cómo usar el RectangleGeometry clase para describir un rectángulo.

Ejemplo
El ejemplo siguiente muestra cómo crear y representar un RectangleGeometry. La posición relativa y las
dimensiones del rectángulo se definen mediante un Rect estructura. Es la posición relativa 50,50 y el alto y ancho
son ambos 25 creación de un cuadrado. El interior del rectángulo se pinta con un LemonChiffon pincel y su
contorno se dibuja con un Black con un grosor de trazo de 1 .

<Path Fill="LemonChiffon" Stroke="Black" StrokeThickness="1">


<Path.Data>
<RectangleGeometry Rect="50,50,25,25" />
</Path.Data>
</Path>

RectangleGeometry myRectangleGeometry = new RectangleGeometry();


myRectangleGeometry.Rect = new Rect(50,50,25,25);

Path myPath = new Path();


myPath.Fill = Brushes.LemonChiffon;
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myRectangleGeometry;

Dim myRectangleGeometry As New RectangleGeometry()


myRectangleGeometry.Rect = New Rect(50,50,25,25)

Dim myPath As New Path()


myPath.Fill = Brushes.LemonChiffon
myPath.Stroke = Brushes.Black
myPath.StrokeThickness = 1
myPath.Data = myRectangleGeometry

RectangleGeometry
Aunque este ejemplo usa un Path elemento para representar el RectangleGeometry, hay muchas otras formas de
usar RectangleGeometry objetos. Por ejemplo, un RectangleGeometry puede utilizarse para especificar el Clip de
un UIElement o Geometry de un GeometryDrawing.
Otras clases de geometría simple incluyen LineGeometry y EllipseGeometry. Estas geometrías, así como otras más
complejas, también se pueden crear mediante un PathGeometry o StreamGeometry.
Vea también
Información general sobre geometría
Crear una forma compuesta
Crear una forma mediante una clase PathGeometry
Procedimiento Redondear las esquinas de un
RectangleGeometry
23/10/2019 • 2 minutes to read • Edit Online

Para redondear los vértices de un RectangleGeometry, establezca su RadiusX y RadiusY propiedades en un valor
mayor que cero. Cuanto mayor sea el valores, más redondeadas serán las esquinas del rectángulo.

Ejemplo
El ejemplo siguiente se muestra varias RectangleGeometry objetos con diferentes RadiusX y RadiusY
configuración. El RectangleGeometry objetos se muestran mediante Path elementos.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="GeoOvwSample.RectangleGeometryRoundedCornerExample">

<Page.Resources>

<!-- Create a grid background to highlight the


coordinate system. -->
<DrawingBrush x:Key="GridDrawingBrushResource"
Viewport="0,0,10,10"
ViewportUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z" Brush="#CCCCFF" />
<GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>

<!-- Create a graph paper style border to frame the rectangles. -->
<Style x:Key="GraphPaperBorderStyle" TargetType="{x:Type Border}">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Background"
Value="{StaticResource GridDrawingBrushResource}" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Margin" Value="10" />
<Setter Property="Width" Value="190" />
<Setter Property="Height" Value="90" />
</Style>
</Page.Resources>

<StackPanel Name="MainStackPanel">

<Border Style="{StaticResource GraphPaperBorderStyle}">


<Path Stroke="Black"
StrokeThickness="1"
Fill="#99CCCCFF">
<Path.Data>
<!-- Create a rectangle without rounded corners. -->
<RectangleGeometry
Rect="20,20,150,50" />
</Path.Data>
</Path>
</Border>

<Border Style="{StaticResource GraphPaperBorderStyle}">


<Path Stroke="Black"
StrokeThickness="1"
Fill="#99CCCCFF">
<Path.Data>

<!-- Create a rectangle with rounded corners


by giving the RectangleGeometry a RadiusX
and a RadiusY of 10. -->
<RectangleGeometry
Rect="20,20,150,50" RadiusX="10" RadiusY="10" />
</Path.Data>
</Path>
</Border>

<Border Style="{StaticResource GraphPaperBorderStyle}" >


<Path Stroke="Black"
StrokeThickness="1"
Fill="#99CCCCFF">
<Path.Data>

<!-- Set RadiusX and RadiusY to their maximum values


(half the rectangle's width and
half the rectangle's height). -->
<RectangleGeometry
Rect="20,20,150,50" RadiusX="75" RadiusY="25" />
</Path.Data>
</Path>
</Border>

</StackPanel>
</Page>

Rectángulos con esquinas redondeadas

Vea también
Información general sobre geometría
Crear una forma compuesta
Crear una forma mediante una clase PathGeometry
Imágenes
23/10/2019 • 2 minutes to read • Edit Online

Windows Presentation Foundation (WPF ) proporciona compatibilidad integrada con varios formatos de imagen,
representación de imágenes de alta fidelidad y extensibilidad de códec.

En esta sección
Información general sobre imágenes
Temas "Cómo..."

Referencia
Image
BitmapImage
BitmapSource

Vea también
Imágenes y gráficos 2D
Gráficos y multimedia
Información general sobre imágenes
08/01/2020 • 25 minutes to read • Edit Online

En este tema se proporciona una introducción al componente de creación de imágenes de Microsoft Windows
Presentation Foundation. La creación de imágenes de WPF permite a los desarrolladores Mostrar, transformar
y dar formato a las imágenes.

Componente de creación de imágenes de WPF


La creación de imágenes de WPF proporciona mejoras significativas en las funciones de creación de imágenes
de Microsoft Windows. Las funciones de creación de imágenes, como mostrar un mapa de bits o usar una
imagen en un control común, se basaban previamente en las bibliotecas GDI+ de Microsoft Windows Interfaz
de dispositivo gráfico (GDI) o Microsoft Windows. Estas API proporcionan funcionalidad de creación de
imágenes de línea base, pero carecen de características como la compatibilidad con la extensibilidad de códecs
y la compatibilidad con imágenes de alta fidelidad. La creación de imágenes de WPF está diseñada para
superar las deficiencias de GDI e GDI+ y proporcionar un nuevo conjunto de API para mostrar y usar
imágenes en las aplicaciones.
Hay dos maneras de tener acceso a la API de creación de imágenes de WPF, un componente administrado y
un componente no administrado. El componente no administrado proporciona las siguientes características.
Modelo de extensibilidad para formatos de imagen nuevos o de propiedad.
Mejora en el rendimiento y la seguridad de los formatos de imagen nativas, incluido el mapa de bits
(BMP ), grupo de expertos de fotográficos (JPEG ), gráficos de red portátiles (PNG ), Tagged Image File
Format (TIFF ), Microsoft Windows Media Photo, formato de intercambio de gráficos (GIF ), y el icono (.
ico).
Conservación de datos de imagen de alta profundidad de bits de hasta 8 bits por canal (32 bits por
píxel).
Escalado, recorte y giros de imágenes no destructivos.
Administración del color simplificada.
Compatibilidad con metadatos de propiedad integrados.
El componente administrado emplea la infraestructura no administrada para proporcionar una
integración sin problemas de las imágenes con otras características de WPF como interfaz de usuario
(UI), animación y gráficos. El componente administrado también se beneficia del modelo de
extensibilidad de códec de imágenes de Windows Presentation Foundation (WPF ), que permite el
reconocimiento automático de nuevos formatos de imagen en aplicaciones WPF.
La mayoría de la API de creación de imágenes de WPF administrada reside en el espacio de nombres
System.Windows.Media.Imaging, aunque varios tipos importantes, como ImageBrush y ImageDrawing
residen en el espacio de nombres System.Windows.Media y Image residen en el espacio de nombres
System.Windows.Controls.
En este tema se proporciona información adicional sobre el componente administrado. Para obtener más
información sobre la API no administrada, vea la documentación de componentes de imagen de WPF no
administrados .
Formatos de imagen de WPF
Un códec se usa para descodificar o codificar un formato de medios específico. La creación de imágenes de
WPF incluye un códec para formatos BMP, JPEG, PNG, TIFF, Windows Media Photo, GIF y de imagen de
iconos. Cada uno de estos códecs permiten a las aplicaciones descodificar y, con la excepción de ICON,
codificar sus formatos de imagen respectivos.
BitmapSource es una clase importante que se usa en la descodificación y codificación de imágenes. Es el
bloque de creación básico de la canalización de imágenes de WPF y representa un único conjunto constante
de píxeles con un tamaño y resolución determinados. Un BitmapSource puede ser un fotograma individual de
una imagen de varios marcos o puede ser el resultado de una transformación realizada en un BitmapSource.
Es el elemento primario de muchas de las clases principales que se usan en la creación de imágenes de WPF,
como BitmapFrame.
Un BitmapFrame se utiliza para almacenar los datos de mapa de bits reales de un formato de imagen. Muchos
formatos de imagen solo admiten un único BitmapFrame, aunque formatos como GIF y TIFF admiten varios
fotogramas por imagen. Los descodificadores usan los marcos como datos de entrada y se pasan a los
codificadores para crear archivos de imagen.
En el ejemplo siguiente se muestra cómo se crea un BitmapFrame a partir de un BitmapSource y, a
continuación, se agrega a una imagen TIFF.

BitmapSource image5 = BitmapSource.Create(


width,
height,
96,
96,
PixelFormats.Indexed1,
BitmapPalettes.WebPalette,
pixels,
stride);

FileStream stream5 = new FileStream("palette.tif", FileMode.Create);


TiffBitmapEncoder encoder5 = new TiffBitmapEncoder();
encoder5.Frames.Add(BitmapFrame.Create(image5));
encoder5.Save(stream5);

Dim image5 As BitmapSource = System.Windows.Media.Imaging.BitmapSource.Create(width, height, 96, 96,


PixelFormats.Indexed1, BitmapPalettes.WebPalette, pixels, stride)

Dim stream5 As New FileStream("palette.tif", FileMode.Create)


Dim encoder5 As New TiffBitmapEncoder()
encoder5.Frames.Add(BitmapFrame.Create(image5))
encoder5.Save(stream5)

Descodificación de formatos de imagen


La descodificación de imágenes es la traslación de un formato de imagen a datos de imagen que el sistema
puede usar. Los datos de imagen pueden usarse entonces para mostrar, procesar o codificar en otro formato.
La selección del descodificador se basa en el formato de imagen. La selección del códec es automática a menos
que se indique un descodificador específico. En los ejemplos de la sección Mostrar imágenes en WPF se
muestra la descodificación automática. Los descodificadores de formato personalizados desarrollados con las
interfaces de imagen de WPF no administradas y registrados con el sistema participan automáticamente en la
selección del descodificador. Esto permite que los formatos personalizados se muestren automáticamente en
las aplicaciones WPF.
En el ejemplo siguiente se muestra el uso de un descodificador de mapa de bits para descodificar una imagen
de formato BMP.
// Open a Uri and decode a BMP image
System::Uri^ myUri = gcnew System::Uri("tulipfarm.bmp", UriKind::RelativeOrAbsolute);
BmpBitmapDecoder^ decoder2 = gcnew BmpBitmapDecoder(myUri, BitmapCreateOptions::PreservePixelFormat,
BitmapCacheOption::Default);
BitmapSource^ bitmapSource2 = decoder2->Frames[0];

// Draw the Image


Image^ myImage2 = gcnew Image();
myImage2->Source = bitmapSource2;
myImage2->Stretch = Stretch::None;
myImage2->Margin = System::Windows::Thickness(20);

// Open a Uri and decode a BMP image


Uri myUri = new Uri("tulipfarm.bmp", UriKind.RelativeOrAbsolute);
BmpBitmapDecoder decoder2 = new BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapSource bitmapSource2 = decoder2.Frames[0];

// Draw the Image


Image myImage2 = new Image();
myImage2.Source = bitmapSource2;
myImage2.Stretch = Stretch.None;
myImage2.Margin = new Thickness(20);

' Open a Uri and decode a BMP image


Dim myUri As New Uri("tulipfarm.bmp", UriKind.RelativeOrAbsolute)
Dim decoder2 As New BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim bitmapSource2 As BitmapSource = decoder2.Frames(0)

' Draw the Image


Dim myImage2 As New Image()
myImage2.Source = bitmapSource2
myImage2.Stretch = Stretch.None
myImage2.Margin = New Thickness(20)

Codificación de formatos de imagen


La codificación de imágenes es la traslación de datos de imagen a un formato de imagen específico. Los datos
de imagen codificados pueden usarse entonces para crear nuevos archivos de imagen. La creación de
imágenes de WPF proporciona codificadores para cada uno de los formatos de imagen descritos
anteriormente.
En el siguiente ejemplo se muestra el uso de un codificador para guardar una imagen de mapa de bits recién
creada.

FileStream^ stream = gcnew FileStream("new.bmp", FileMode::Create);


BmpBitmapEncoder^ encoder = gcnew BmpBitmapEncoder();
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);
FileStream stream = new FileStream("new.bmp", FileMode.Create);
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);

Dim stream As New FileStream("new.bmp", FileMode.Create)


Dim encoder As New BmpBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)

Mostrar imágenes en WPF


Hay varias maneras de mostrar una imagen en una aplicación Windows Presentation Foundation (WPF ). Las
imágenes se pueden mostrar mediante un control de Image, pintados en un visual con un ImageBrusho
dibujadas con un ImageDrawing.
Usar el control de imagen
Image es un elemento de marco y la forma principal de mostrar imágenes en las aplicaciones. En XAML,
Image se pueden usar de dos maneras: Sintaxis de atributo o sintaxis de propiedad. En el siguiente ejemplo se
muestra cómo representar una imagen de 200 píxeles de ancho mediante la sintaxis de atributo y la sintaxis de
etiquetas de propiedad. Para más información sobre la sintaxis de atributo y la sintaxis de propiedad, consulte
Información general sobre las propiedades de dependencia.

<!-- Simple image rendering. However, rendering an image this way may not
result in the best use of application memory. See markup below which
creates the same end result but using less memory. -->
<Image Width="200"
Source="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg"/>

<Image Width="200">
<Image.Source>
<!-- To save significant application memory, set the DecodePixelWidth or
DecodePixelHeight of the BitmapImage value of the image source to the desired
height and width of the rendered image. If you don't do this, the application will
cache the image as though it were rendered as its normal size rather then just
the size that is displayed. -->
<!-- Note: In order to preserve aspect ratio, only set either DecodePixelWidth
or DecodePixelHeight but not both. -->
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water
Lilies.jpg" />
</Image.Source>
</Image>

Muchos de los ejemplos usan un objeto BitmapImage para hacer referencia a un archivo de imagen.
BitmapImage es un BitmapSource especializado que está optimizado para la carga de Lenguaje XAML
(Extensible Application Markup Language) y es una manera fácil de mostrar imágenes como Source de un
control de Image.
En el siguiente ejemplo se muestra cómo representar una imagen de 200 píxeles de ancho mediante código.
NOTE
BitmapImage implementa la interfaz ISupportInitialize para optimizar la inicialización en varias propiedades. Los cambios
en la propiedad solo se pueden producir durante la inicialización del objeto. Llame a BeginInit para indicar que la
inicialización ha comenzado y EndInit para indicar que la inicialización se ha completado. Una vez inicializado, se omiten
los cambios en la propiedad.

// Create Image Element


Image myImage = new Image();
myImage.Width = 200;

// Create source
BitmapImage myBitmapImage = new BitmapImage();

// BitmapImage.UriSource must be in a BeginInit/EndInit block


myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg");

// To save significant application memory, set the DecodePixelWidth or


// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
//set image source
myImage.Source = myBitmapImage;

' Create Image Element


Dim myImage As New Image()
myImage.Width = 200

' Create source


Dim myBitmapImage As New BitmapImage()

' BitmapImage.UriSource must be in a BeginInit/EndInit block


myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg")

' To save significant application memory, set the DecodePixelWidth or


' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()
'set image source
myImage.Source = myBitmapImage

Girar, convertir y recortar imágenes


WPF permite a los usuarios transformar imágenes mediante las propiedades de BitmapImage o mediante el
uso de objetos de BitmapSource adicionales como CroppedBitmap o FormatConvertedBitmap. Dichas
transformaciones de imágenes pueden escalar o girar una imagen, cambiar el formato de píxel de una imagen
o recortar una imagen.
Las rotaciones de imagen se realizan utilizando la propiedad Rotation de BitmapImage. Estos solo pueden
llevarse a cabo en incrementos de 90 grados. En el siguiente ejemplo, una imagen se gira 90 grados.

<Image Width="150" Margin="5" Grid.Column="0" Grid.Row="1">


<Image.Source>
<TransformedBitmap Source="/sampleImages/watermelon.jpg" >
<TransformedBitmap.Transform>
<RotateTransform Angle="90"/>
</TransformedBitmap.Transform>
</TransformedBitmap>
</Image.Source>
</Image>

// Create Image element.


Image rotated90 = new Image();
rotated90.Width = 150;

// Create the TransformedBitmap to use as the Image source.


TransformedBitmap tb = new TransformedBitmap();

// Create the source to use as the tb source.


BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(@"sampleImages/watermelon.jpg", UriKind.RelativeOrAbsolute);
bi.EndInit();

// Properties must be set between BeginInit and EndInit calls.


tb.BeginInit();
tb.Source = bi;
// Set image rotation.
RotateTransform transform = new RotateTransform(90);
tb.Transform = transform;
tb.EndInit();
// Set the Image source.
rotated90.Source = tb;

' Create Image element.


Dim rotated90 As New Image()
rotated90.Width = 150

' Create the TransformedBitmap to use as the Image source.


Dim tb As New TransformedBitmap()

' Create the source to use as the tb source.


Dim bi As New BitmapImage()
bi.BeginInit()
bi.UriSource = New Uri("sampleImages/watermelon.jpg", UriKind.RelativeOrAbsolute)
bi.EndInit()

' Properties must be set between BeginInit and EndInit calls.


tb.BeginInit()
tb.Source = bi
' Set image rotation.
Dim transform As New RotateTransform(90)
tb.Transform = transform
tb.EndInit()
' Set the Image source.
rotated90.Source = tb

La conversión de una imagen a un formato de píxel diferente, como la escala de grises, se realiza mediante
FormatConvertedBitmap. En los ejemplos siguientes, una imagen se convierte en Gray4.
<!-- Grayscale XAML Image -->
<Image Width="200" Grid.Column="0" Grid.Row="1">
<Image.Source>
<FormatConvertedBitmap Source="/sampleImages/rocks.jpg" DestinationFormat="Gray4" />
</Image.Source>
</Image>

//Create Image Element


Image grayImage = new Image();
grayImage.Width = 200;
grayImage.Margin = new Thickness(5);

//Create source using xaml defined resource.


FormatConvertedBitmap fcb = new FormatConvertedBitmap(
(BitmapImage)this.Resources["masterImage"],PixelFormats.Gray4,null,0);
//set image source
grayImage.Source = fcb;

'Create Image Element


Dim grayImage As New Image()
grayImage.Width = 200
grayImage.Margin = New Thickness(5)

'Create source using xaml defined resource.


Dim fcb As New FormatConvertedBitmap(CType(Me.Resources("masterImage"), BitmapImage), PixelFormats.Gray4,
Nothing, 0)
'set image source
grayImage.Source = fcb

Para recortar una imagen, se puede usar la propiedad Clip de Image o CroppedBitmap. Normalmente, si solo
desea mostrar una parte de una imagen, se debe usar Clip. Si necesita codificar y guardar una imagen
recortada, se debe usar el CroppedBitmap. En el ejemplo siguiente, se recorta una imagen utilizando la
propiedad clip mediante una EllipseGeometry.

<!-- Cropping an Image using Clip -->


<Image Width="200" Grid.Column="0" Grid.Row="5" Margin="5"
Source="/sampleImages/gecko.jpg">
<Image.Clip>
<EllipseGeometry Center="75,50" RadiusX="50" RadiusY="25" />
</Image.Clip>
</Image>

//Create the image for clipping


Image clipImage = new Image();
clipImage.Width = 200;
clipImage.Margin = new Thickness(5);

//Create & Set source


BitmapImage bi = new BitmapImage();
//BitmapImage.UriSource must be in a BeginInit/EndInit block
bi.BeginInit();
bi.UriSource = new Uri("pack://application:,,/sampleImages/gecko.jpg");
bi.EndInit();
clipImage.Source = bi;

//Clip the using an EllipseGeometry


EllipseGeometry clipGeometry = new EllipseGeometry(new Point(75, 50), 50, 25);
clipImage.Clip = clipGeometry;
' Create the image for clipping
Dim clipImage As New Image()
clipImage.Width = 200
clipImage.Margin = New Thickness(5)

'Create & Set source


Dim bi As New BitmapImage()
' BitmapImage properties must be in a BeginInit/EndInit block
bi.BeginInit()
bi.UriSource = New Uri("pack://application:,,/sampleImages/gecko.jpg")
bi.EndInit()
clipImage.Source = bi

' Clip the using an EllipseGeometry


Dim clipGeometry As New EllipseGeometry(New System.Windows.Point(75, 50), 50, 25)
clipImage.Clip = clipGeometry

Ajustar imágenes
La propiedad Stretch controla cómo se ajusta una imagen para rellenar su contenedor. La propiedad Stretch
acepta los siguientes valores, definidos por la enumeración Stretch:
None: la imagen no se ajusta para rellenar el área de salida. Si la imagen es más grande que el área de
salida, esta se dibujará en dicha área, recortando lo que no se ajuste.
Fill: la imagen se escala para ajustarse al área de salida. Como el alto y el ancho de las imágenes se
escalan de forma independiente, podría no conservarse la relación de aspecto original de la imagen. En
otras palabras, la imagen podría distorsionarse para rellenar por completo el contenedor de salida.
Uniform: la imagen se escala para que quepa completamente dentro del área de salida. Se conserva la
relación de aspecto de la imagen.
UniformToFill: la imagen se escala para que rellene completamente el área de salida, al mismo tiempo
que se conserva la relación de aspecto original de la imagen.
En el ejemplo siguiente se aplica cada una de las enumeraciones de Stretch disponibles a una Image.
En la imagen siguiente se muestra el resultado del ejemplo y se muestra el efecto que tienen las distintas
configuraciones de Stretch cuando se aplican a una imagen.

Diferentes valores de Stretch


<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>

<Border DockPanel.Dock="Top" Background="Black">


<TextBlock Foreground="White" HorizontalAlignment="Stretch" FontSize="20">
Stretching an Image
</TextBlock>
</Border>

<Grid Name="simpleGrid" Background="{StaticResource CheckeredBrushResource}"


Margin="10"
ShowGridLines="True"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="175" />
<ColumnDefinition Width="175" />
<ColumnDefinition Width="175" />
<ColumnDefinition Width="175" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="200"/>
</Grid.RowDefinitions>
<!-- Labels -->
<TextBlock Style="{StaticResource Header1}"
Grid.Column="0" Grid.Row="0">None</TextBlock>
<TextBlock Style="{StaticResource Header1}"
Grid.Column="1" Grid.Row="0">Uniform</TextBlock>
<TextBlock Style="{StaticResource Header1}"
Grid.Column="2" Grid.Row="0">UniformToFill</TextBlock>
<TextBlock Style="{StaticResource Header1}"
Grid.Column="3" Grid.Row="0">Fill</TextBlock>
<Border Grid.Column="0" Grid.Row="1" BorderThickness="1" BorderBrush="Black">
<!-- None: Image is not scaled. If image is larger than the
output area, the image will be cropped to the size of the output area.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="None" />
</Border>
<Border Grid.Column="1" Grid.Row="1" BorderThickness="1" BorderBrush="Black">
<!-- Uniform: Scale to fit output area.
Aspect ratio is preserved.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="Uniform" />
</Border>
<Border Grid.Column="2" Grid.Row="1" BorderThickness="1" BorderBrush="Black">
<!-- UniformToFill: Scale to completely fill output area.
Aspect ratio is preserved. Cropping may occur.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="UniformToFill" />
</Border>
<Border Grid.Column="3" Grid.Row="1" BorderThickness="1" BorderBrush="Black">
<!-- Fill: Scale to completely fill output area.
Aspect ratio may not be preserved.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="Fill" />
</Border>
</Grid>
</DockPanel>
</Page>
Pintar con imágenes
Las imágenes también se pueden mostrar en una aplicación pintando con un Brush. Los pinceles permiten
pintar objetos IU con cualquier cosa, desde colores simples y sólidos hasta conjuntos complejos de patrones e
imágenes. Para pintar con imágenes, use una ImageBrush. Un ImageBrush es un tipo de TileBrush que define
su contenido como una imagen de mapa de bits. Un ImageBrush muestra una sola imagen, que se especifica
mediante su propiedad ImageSource. Puede controlar cómo se ajusta, alinea y coloca en mosaico la imagen,
evitándose de este modo la distorsión y produciéndose patrones y otros efectos. En la ilustración siguiente se
muestran algunos efectos que se pueden lograr con un ImageBrush.

Los pinceles de imagen pueden rellenar formas, controles, texto, etc.


En el ejemplo siguiente se muestra cómo pintar el fondo de un botón con una imagen mediante un
ImageBrush.

<!-- Sets the button's Background property with an ImageBrush. The resulting
button has an image as its background. -->
<Button Grid.Row="3" Grid.Column="2"
Height="75" Width="100" Foreground="White" FontWeight="Bold"
HorizontalAlignment="Left">
A Button
<Button.Background>
<ImageBrush ImageSource="sampleImages\blueberries.jpg" />
</Button.Background>
</Button>

Para obtener más información sobre cómo ImageBrush y pintar imágenes , vea pintar con imágenes, dibujos y
objetos visuales.

Metadatos de imagen
Algunos archivos de imagen contienen metadatos que describen el contenido o las características del archivo.
Por ejemplo, la mayoría de las cámaras digitales crean imágenes que contienen metadatos sobre la marca y
modelo de la cámara empleada para capturar la imagen. Cada formato de imagen controla los metadatos de
manera diferente, pero la creación de imágenes de WPF proporciona una manera uniforme de almacenar y
recuperar los metadatos de cada formato de imagen compatible.
El acceso a los metadatos se proporciona a través de la propiedad Metadata de un objeto BitmapSource.
Metadata devuelve un objeto BitmapMetadata que incluye todos los metadatos que contiene la imagen. Estos
datos pueden estar en un esquema de metadatos o una combinación de diferentes esquemas. La creación de
imágenes de WPF admite los siguientes esquemas de metadatos de imagen: el archivo de imagen
intercambiable (EXIF ), el texto (datos de texto PNG ), el directorio de archivos de imagen (IFD ), el Consejo
Internacional de telecomunicaciones (IPTC ) y la plataforma de metadatos extensible (XMP ).
Con el fin de simplificar el proceso de lectura de metadatos, BitmapMetadata proporciona varias propiedades
con nombre a las que se puede tener acceso fácilmente, como Author, Titley CameraModel. Muchas de estas
propiedades con nombre también se pueden usar para escribir metadatos. El lector de consultas de metadatos
proporciona soporte técnico adicional para leer metadatos. El método GetQuery se utiliza para recuperar un
lector de consultas de metadatos proporcionando una consulta de cadena como "/APP1/Exif/" . En el ejemplo
siguiente, se usa GetQuery para obtener el texto almacenado en la ubicación "/Text/Description" .

// Add the metadata of the bitmap image to the text block.


TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "The Description metadata of this image is: " + pngInplace-
>GetQuery("/Text/Description")->ToString();

// Add the metadata of the bitmap image to the text block.


TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "The Description metadata of this image is: " +
pngInplace.GetQuery("/Text/Description").ToString();

' Add the metadata of the bitmap image to the text block.
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "The Description metadata of this image is: " +
pngInplace.GetQuery("/Text/Description").ToString()

Para escribir metadatos, se usa un escritor de consultas de metadatos. SetQuery obtiene el escritor de
consultas y establece el valor deseado. En el ejemplo siguiente, se usa SetQuery para escribir el texto
almacenado en la ubicación "/Text/Description" .

Stream^ pngStream = gcnew FileStream("smiley.png", FileMode::Open, FileAccess::ReadWrite,


FileShare::ReadWrite);
PngBitmapDecoder^ pngDecoder = gcnew PngBitmapDecoder(pngStream, BitmapCreateOptions::PreservePixelFormat,
BitmapCacheOption::Default);
BitmapFrame^ pngFrame = pngDecoder->Frames[0];
InPlaceBitmapMetadataWriter^ pngInplace = pngFrame->CreateInPlaceBitmapMetadataWriter();
if (pngInplace->TrySave() == true)
{
pngInplace->SetQuery("/Text/Description", "Have a nice day.");
}
pngStream->Close();

Stream pngStream = new System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite,


FileShare.ReadWrite);
PngBitmapDecoder pngDecoder = new PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapFrame pngFrame = pngDecoder.Frames[0];
InPlaceBitmapMetadataWriter pngInplace = pngFrame.CreateInPlaceBitmapMetadataWriter();
if (pngInplace.TrySave() == true)
{ pngInplace.SetQuery("/Text/Description", "Have a nice day."); }
pngStream.Close();
Dim pngStream As New System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite,
FileShare.ReadWrite)
Dim pngDecoder As New PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim pngFrame As BitmapFrame = pngDecoder.Frames(0)
Dim pngInplace As InPlaceBitmapMetadataWriter = pngFrame.CreateInPlaceBitmapMetadataWriter()
If pngInplace.TrySave() = True Then
pngInplace.SetQuery("/Text/Description", "Have a nice day.")
End If
pngStream.Close()

Extensibilidad de códec
Una característica fundamental de la creación de imágenes de WPF es el modelo de extensibilidad para los
nuevos códecs de imagen. Estas interfaces no administradas permiten a los desarrolladores de códec integrar
códecs con WPF para que las aplicaciones de WPF puedan usar automáticamente nuevos formatos de
imagen.
Para obtener un ejemplo de la API de extensibilidad, vea el ejemplo de códec de Win32. En este ejemplo se
muestra cómo crear un descodificador y un codificador para un formato de imagen personalizado.

NOTE
El códec se debe firmar digitalmente para que el sistema lo reconozca.

Vea también
BitmapSource
BitmapImage
Image
BitmapMetadata
Imágenes y gráficos 2D
Código de ejemplo Win32
Temas "Cómo..." de imágenes
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección muestran cómo usar Windows Presentation Foundation (WPF ) con el fin de mostrar o
modificar las imágenes de mapa de bits.

En esta sección
Usar BitmapImage en XAML
Cargar una imagen como una miniatura
Aplicar una transformación a un BitmapImage
Crear un mapa de bits desde un objeto visual
Codificar un objeto visual en un archivo de imagen
Crear un nuevo objeto BitmapSource
Encadenar objetos BitmapSource
Convertir un elemento BitmapSource a un formato de píxeles diferente
Convertir un elemento BitmapSource en un formato de píxeles indexado
Codificar y descodificar una imagen JPEG
Codificar y descodificar una imagen BMP
Codificar y descodificar una imagen PNG
Codificar y descodificar una imagen WDP
Codificar y descodificar una imagen GIF
Codificar y descodificar una imagen TIFF
Escribir metadatos en un mapa de bits
Leer metadatos de un mapa de bits

Referencia
Image
BitmapImage
BitmapSource

Vea también
Información general sobre imágenes
Procedimiento Usar un BitmapImage
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un BitmapImage como origen de un Image controlar en Lenguaje XAML
(Extensible Application Markup Language).

Ejemplo
<!-- Simple image rendering. However, rendering an image this way may not
result in the best use of application memory. See markup below which
creates the same end result but using less memory. -->
<Image Width="200"
Source="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg"/>

<Image Width="200">
<Image.Source>
<!-- To save significant application memory, set the DecodePixelWidth or
DecodePixelHeight of the BitmapImage value of the image source to the desired
height and width of the rendered image. If you don't do this, the application will
cache the image as though it were rendered as its normal size rather then just
the size that is displayed. -->
<!-- Note: In order to preserve aspect ratio, only set either DecodePixelWidth
or DecodePixelHeight but not both. -->
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>

// Create Image Element


Image myImage = new Image();
myImage.Width = 200;

// Create source
BitmapImage myBitmapImage = new BitmapImage();

// BitmapImage.UriSource must be in a BeginInit/EndInit block


myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg");

// To save significant application memory, set the DecodePixelWidth or


// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
//set image source
myImage.Source = myBitmapImage;
' Create Image Element
Dim myImage As New Image()
myImage.Width = 200

' Create source


Dim myBitmapImage As New BitmapImage()

' BitmapImage.UriSource must be in a BeginInit/EndInit block


myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg")

' To save significant application memory, set the DecodePixelWidth or


' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()
'set image source
myImage.Source = myBitmapImage

Vea también
Información general sobre imágenes
Procedimiento Cargar una imagen como una
miniatura
23/10/2019 • 2 minutes to read • Edit Online

Los ejemplos siguientes muestran cómo cargar un Image como una miniatura para conservar memoria de la
aplicación.

Ejemplo
El ejemplo siguiente se establece la DecodePixelWidth propiedad de un BitmapImage en Lenguaje XAML
(Extensible Application Markup Language) para reducir la memoria necesaria para cargar la imagen.

<!-- Simple image rendering. However, rendering an image this way may not
result in the best use of application memory. See markup below which
creates the same end result but using less memory. -->
<Image Width="200"
Source="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg"/>

<Image Width="200">
<Image.Source>
<!-- To save significant application memory, set the DecodePixelWidth or
DecodePixelHeight of the BitmapImage value of the image source to the desired
height and width of the rendered image. If you don't do this, the application will
cache the image as though it were rendered as its normal size rather then just
the size that is displayed. -->
<!-- Note: In order to preserve aspect ratio, only set either DecodePixelWidth
or DecodePixelHeight but not both. -->
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>

Ejemplo
El ejemplo siguiente se establece la DecodePixelWidth propiedad de un BitmapImage en el código para reducir la
memoria necesaria para cargar la imagen.
// Create Image Element
Image myImage = new Image();
myImage.Width = 200;

// Create source
BitmapImage myBitmapImage = new BitmapImage();

// BitmapImage.UriSource must be in a BeginInit/EndInit block


myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg");

// To save significant application memory, set the DecodePixelWidth or


// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
//set image source
myImage.Source = myBitmapImage;

' Create Image Element


Dim myImage As New Image()
myImage.Width = 200

' Create source


Dim myBitmapImage As New BitmapImage()

' BitmapImage.UriSource must be in a BeginInit/EndInit block


myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg")

' To save significant application memory, set the DecodePixelWidth or


' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()
'set image source
myImage.Source = myBitmapImage

Vea también
Información general sobre imágenes
Procedimiento Aplicar una transformación a un
BitmapImage
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo aplicar un Transform a un BitmapImage.

Ejemplo
///// Create a BitmapImage and set it's DecodePixelWidth to 200. Use /////
///// this BitmapImage as a source for other BitmapSource objects. /////

BitmapImage myBitmapImage = new BitmapImage();

// BitmapSource objects like BitmapImage can only have their properties


// changed within a BeginInit/EndInit block.
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg");

// To save significant application memory, set the DecodePixelWidth or


// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();

/////////////////// Create a BitmapSource that Rotates the image //////////////////////


// Use the BitmapImage created above as the source for a new BitmapSource object
// that will be scaled to a different size. Create a new BitmapSource by
// scaling the original one.
// Note: New BitmapSource does not cache. It is always pulled when required.

// Create the new BitmapSource that will be used to scale the size of the source.
TransformedBitmap myRotatedBitmapSource = new TransformedBitmap();

// BitmapSource objects like TransformedBitmap can only have their properties


// changed within a BeginInit/EndInit block.
myRotatedBitmapSource.BeginInit();

// Use the BitmapSource object defined above as the source for this BitmapSource.
// This creates a "chain" of BitmapSource objects which essentially inherit from each other.
myRotatedBitmapSource.Source = myBitmapImage;

// Flip the source 90 degrees.


myRotatedBitmapSource.Transform = new RotateTransform(90);
myRotatedBitmapSource.EndInit();
'/// Create a BitmapImage and set it's DecodePixelWidth to 200. Use /////
'/// this BitmapImage as a source for other BitmapSource objects. /////
Dim myBitmapImage As New BitmapImage()

' BitmapSource objects like BitmapImage can only have their properties
' changed within a BeginInit/EndInit block.
myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg")

' To save significant application memory, set the DecodePixelWidth or


' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()

'///////////////// Create a BitmapSource that Rotates the image //////////////////////


' Use the BitmapImage created above as the source for a new BitmapSource object
' that will be scaled to a different size. Create a new BitmapSource by
' scaling the original one.
' Note: New BitmapSource does not cache. It is always pulled when required.
' Create the new BitmapSource that will be used to scale the size of the source.
Dim myRotatedBitmapSource As New TransformedBitmap()

' BitmapSource objects like TransformedBitmap can only have their properties
' changed within a BeginInit/EndInit block.
myRotatedBitmapSource.BeginInit()

' Use the BitmapSource object defined above as the source for this BitmapSource.
' This creates a "chain" of BitmapSource objects which essentially inherit from each other.
myRotatedBitmapSource.Source = myBitmapImage

' Flip the source 90 degrees.


myRotatedBitmapSource.Transform = New RotateTransform(90)
myRotatedBitmapSource.EndInit()

Vea también
BitmapSource
Información general sobre imágenes
Girar una imagen
Procedimiento Crear un mapa de bits desde un
objeto visual
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo puede crear un mapa de bits desde un Visual. Un DrawingVisual se presenta con
FormattedText. El Visual , a continuación, se representa en el RenderTargetBitmap creación de un mapa de bits del
texto dado.

Ejemplo
Image myImage = new Image();
FormattedText text = new FormattedText("ABC",
new CultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(this.FontFamily, FontStyles.Normal, FontWeights.Normal, new FontStretch()),
this.FontSize,
this.Foreground);

DrawingVisual drawingVisual = new DrawingVisual();


DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawText(text, new Point(2, 2));
drawingContext.Close();

RenderTargetBitmap bmp = new RenderTargetBitmap(180, 180, 120, 96, PixelFormats.Pbgra32);


bmp.Render(drawingVisual);
myImage.Source = bmp;

Dim myImage As New Image()


Dim [text] As New FormattedText("ABC", New CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, New
Typeface(Me.FontFamily, FontStyles.Normal, FontWeights.Normal, New FontStretch()), Me.FontSize, Me.Foreground)

Dim drawingVisual As New DrawingVisual()


Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()
drawingContext.DrawText([text], New System.Windows.Point(2, 2))
drawingContext.Close()

Dim bmp As New RenderTargetBitmap(180, 180, 120, 96, PixelFormats.Pbgra32)


bmp.Render(drawingVisual)
myImage.Source = bmp

Vea también
DrawingContext
Información general sobre imágenes
Información general sobre objetos Drawing
Usar objetos DrawingVisual
Procedimiento Codificar un objeto visual en un
archivo de imagen
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo codificar Visual un objeto en un archivo de imagen RenderTargetBitmap
mediante y PngBitmapEncoder.

Ejemplo
Se crea RenderTargetBitmapmediante y queFormattedText se representa en un. BitmapImage DrawingVisual El
mapa de bits representado se usa para crear un BitmapFrame que se agrega PngBitmapEncoder a para crear un
nuevo archivo PNG (Portable Network Graphics).

// Base Image
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri("sampleImages/waterlilies.jpg",UriKind.Relative);
bi.DecodePixelWidth = 200;
bi.EndInit();

// Text to render on the image.


FormattedText text = new FormattedText("Waterlilies",
new CultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(this.FontFamily, FontStyles.Normal, FontWeights.Normal, new FontStretch()),
this.FontSize,
Brushes.White);

// The Visual to use as the source of the RenderTargetBitmap.


DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawImage(bi,new Rect(0,0,bi.Width,bi.Height));
drawingContext.DrawText(text, new Point(bi.Height/2, 0));
drawingContext.Close();

// The BitmapSource that is rendered with a Visual.


RenderTargetBitmap rtb = new RenderTargetBitmap(bi.PixelWidth, bi.PixelHeight, 96, 96, PixelFormats.Pbgra32);
rtb.Render(drawingVisual);

// Encoding the RenderBitmapTarget as a PNG file.


PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
using (Stream stm = File.Create("new.png"))
{
png.Save(stm);
}
' Base Image
Dim bi As New BitmapImage()
bi.BeginInit()
bi.UriSource = New Uri("sampleImages/waterlilies.jpg", UriKind.Relative)
bi.DecodePixelWidth = 200
bi.EndInit()

' Text to render on the image.


Dim [text] As New FormattedText("Waterlilies", New CultureInfo("en-us"),
System.Windows.FlowDirection.LeftToRight, New Typeface(Me.FontFamily, FontStyles.Normal, FontWeights.Normal,
New FontStretch()), Me.FontSize, Brushes.White)

' The Visual to use as the source of the RenderTargetBitmap.


Dim drawingVisual As New DrawingVisual()
Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()
drawingContext.DrawImage(bi, New Rect(0, 0, bi.Width, bi.Height))
drawingContext.DrawText([text], New System.Windows.Point(bi.Height / 2, 0))
drawingContext.Close()

' The BitmapSource that is rendered with a Visual.


Dim rtb As New RenderTargetBitmap(bi.PixelWidth, bi.PixelHeight, 96, 96, PixelFormats.Pbgra32)
rtb.Render(drawingVisual)

' Encoding the RenderBitmapTarget as a PNG file.


Dim png As New PngBitmapEncoder()
png.Frames.Add(BitmapFrame.Create(rtb))
Dim stm As Stream = File.Create("new.png")
Try
png.Save(stm)
Finally
stm.Dispose()
End Try

Se usó en este ejemplo, pero cualquiera de los objetos BitmapEncoder derivados podría haberse utilizado para
crear el archivo de imagen. PngBitmapEncoder

Vea también
DrawingContext
Información general sobre imágenes
Información general sobre objetos Drawing
Usar objetos DrawingVisual
Procedimiento Crear un objeto BitmapSource
23/10/2019 • 2 minutes to read • Edit Online

Este ejemplo muestra cómo usar el Create método BitmapSource para crear un nuevo BitmapSource objeto.

Ejemplo
// Define parameters used to create the BitmapSource.
PixelFormat pf = PixelFormats.Bgr32;
int width = 200;
int height = 200;
int rawStride = (width * pf.BitsPerPixel + 7) / 8;
byte[] rawImage = new byte[rawStride * height];

// Initialize the image with data.


Random value = new Random();
value.NextBytes(rawImage);

// Create a BitmapSource.
BitmapSource bitmap = BitmapSource.Create(width, height,
96, 96, pf, null,
rawImage, rawStride);

// Create an image element;


Image myImage = new Image();
myImage.Width = 200;
// Set image source.
myImage.Source = bitmap;

' Define parameters used to create the BitmapSource.


Dim pf As PixelFormat = PixelFormats.Bgr32
Dim width As Integer = 200
Dim height As Integer = 200
Dim rawStride As Integer = CType((width * pf.BitsPerPixel + 7) / 8, Integer)
Dim rawImage(rawStride * height) As Byte

' Initialize the image with data.


Dim value As New Random()
value.NextBytes(rawImage)

' Create a BitmapSource.


Dim bitmap As BitmapSource = BitmapSource.Create(width, height, 96, 96, pf, Nothing, rawImage, rawStride)

' Create an image element;


Dim myImage As New Image()
myImage.Width = 200
' Set image source.
myImage.Source = bitmap

Vea también
Información general sobre imágenes
Procedimiento Encadenar objetos BitmapSource
23/10/2019 • 5 minutes to read • Edit Online

En este ejemplo se muestra cómo aplicar diversos efectos a un origen de imagen encadenando varios
BitmapSource objetos derivados entre sí.
En el ejemplo siguiente se utiliza el encadenamiento para voltear y cambiar el formato de píxel del origen de una
imagen.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Page.Resources>

<!-- This resource defines a BitmapImage with a source and a


DecodePixelWidth of 200. This property is set to the same value
as the desired width of the image to save on memory use. This
BitmapImage is used as the base for the other BitmapSource resources. -->
<BitmapImage x:Key="masterImage" DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Forest.jpg"/>

<!-- This TransformedBitmap uses the BitmapImage defined above and flips
it 90 degrees. -->
<TransformedBitmap x:Key="rotatedImage" Source="{StaticResource masterImage}">
<TransformedBitmap.Transform>
<RotateTransform Angle="90" />
</TransformedBitmap.Transform>
</TransformedBitmap>

<!-- This FormatConvertedBitmap uses the TransformedBitmap defined above and


changes the format to Gray32Float (grayscale). -->
<FormatConvertedBitmap x:Key="convertFormatImage"
Source="{StaticResource rotatedImage}"
DestinationFormat="Gray32Float" />

</Page.Resources>

<StackPanel>

<!-- Apply the "convertFormatImage" resource defined above to this image.


The resource is a combination of all three BitmapSource objects which
renders this image with DecodePixelWidth set to 200, fliped 90 degrees
and converted to grayscale. -->
<Image Width="200" Source="{StaticResource convertFormatImage}" />
</StackPanel>
</Page>

//This is a list of commonly used namespaces for a pane.


using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace SDKSample
{
public partial class ChainedBitmapSourcesExample : Page
public partial class ChainedBitmapSourcesExample : Page
{
public ChainedBitmapSourcesExample()
{
///// Create a BitmapImage and set it's DecodePixelWidth to 200. Use /////
///// this BitmapImage as a source for other BitmapSource objects. /////

BitmapImage myBitmapImage = new BitmapImage();

// BitmapSource objects like BitmapImage can only have their properties


// changed within a BeginInit/EndInit block.
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri("sampleImages/WaterLilies.jpg",UriKind.Relative);

// To save significant application memory, set the DecodePixelWidth or


// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();

/////////////////// Create a BitmapSource that Rotates the image //////////////////////


// Use the BitmapImage created above as the source for a new BitmapSource object
// that will be scaled to a different size. Create a new BitmapSource by
// scaling the original one.
// Note: New BitmapSource does not cache. It is always pulled when required.

// Create the new BitmapSource that will be used to scale the size of the source.
TransformedBitmap myRotatedBitmapSource = new TransformedBitmap();

// BitmapSource objects like TransformedBitmap can only have their properties


// changed within a BeginInit/EndInit block.
myRotatedBitmapSource.BeginInit();

// Use the BitmapSource object defined above as the source for this BitmapSource.
// This creates a "chain" of BitmapSource objects which essentially inherit from each other.
myRotatedBitmapSource.Source = myBitmapImage;
// Multiply the size of the X and Y axis of the source by 3.
myRotatedBitmapSource.Transform = new RotateTransform(90);
myRotatedBitmapSource.EndInit();

// Create a new BitmapSource using a different format than the original one.
FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap();

// BitmapSource objects like FormatConvertedBitmap can only have their properties


// changed within a BeginInit/EndInit block.
newFormatedBitmapSource.BeginInit();
newFormatedBitmapSource.Source = myRotatedBitmapSource;
newFormatedBitmapSource.DestinationFormat = PixelFormats.Gray32Float;
newFormatedBitmapSource.EndInit();

// Create Image Element


Image myImage = new Image();
myImage.Width = 200;
//set image source
myImage.Source = newFormatedBitmapSource;

// Add Image to the UI


StackPanel myStackPanel = new StackPanel();
myStackPanel.Children.Add(myImage);
this.Content = myStackPanel;
}

public void PageLoaded(object sender, RoutedEventArgs args)


{
}
}
}
}

'This is a list of commonly used namespaces for a pane.


Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Imaging

Namespace SDKSample

Class ChainedBitmapSourcesExample
Inherits Page

Public Sub New()


'/// Create a BitmapImage and set it's DecodePixelWidth to 200. Use /////
'/// this BitmapImage as a source for other BitmapSource objects. /////
Dim myBitmapImage As New BitmapImage()

' BitmapSource objects like BitmapImage can only have their properties
' changed within a BeginInit/EndInit block.
myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("sampleImages/WaterLilies.jpg", UriKind.Relative)

' To save significant application memory, set the DecodePixelWidth or


' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()

'///////////////// Create a BitmapSource that Rotates the image //////////////////////


' Use the BitmapImage created above as the source for a new BitmapSource object
' that will be scaled to a different size. Create a new BitmapSource by
' scaling the original one.
' Note: New BitmapSource does not cache. It is always pulled when required.
' Create the new BitmapSource that will be used to scale the size of the source.
Dim myRotatedBitmapSource As New TransformedBitmap()

' BitmapSource objects like TransformedBitmap can only have their properties
' changed within a BeginInit/EndInit block.
myRotatedBitmapSource.BeginInit()

' Use the BitmapSource object defined above as the source for this BitmapSource.
' This creates a "chain" of BitmapSource objects which essentially inherit from each other.
myRotatedBitmapSource.Source = myBitmapImage
' Multiply the size of the X and Y axis of the source by 3.
myRotatedBitmapSource.Transform = New RotateTransform(90)
myRotatedBitmapSource.EndInit()

' Create a new BitmapSource using a different format than the original one.
Dim newFormatedBitmapSource As New FormatConvertedBitmap()

' BitmapSource objects like FormatConvertedBitmap can only have their properties
' changed within a BeginInit/EndInit block.
newFormatedBitmapSource.BeginInit()
newFormatedBitmapSource.Source = myRotatedBitmapSource
newFormatedBitmapSource.DestinationFormat = PixelFormats.Gray32Float
newFormatedBitmapSource.EndInit()

' Create Image Element


Dim myImage As New Image()
myImage.Width = 200
'set image source
myImage.Source = newFormatedBitmapSource
myImage.Source = newFormatedBitmapSource

' Add Image to the UI


Dim myStackPanel As New StackPanel()
myStackPanel.Children.Add(myImage)
Me.Content = myStackPanel

End Sub

Public Sub PageLoaded(ByVal sender As Object, ByVal args As RoutedEventArgs)

End Sub
End Class
End Namespace
Procedimiento Convertir un elemento BitmapSource
a un formato de píxeles diferente
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo convertir un BitmapSource objeto (BitmapImage) en otro PixelFormat mediante
un FormatConvertedBitmap.

Ejemplo
///// Create a BitmapImage and set it's DecodePixelWidth to 200. Use /////
///// this BitmapImage as a source for other BitmapSource objects. /////

BitmapImage myBitmapImage = new BitmapImage();

// BitmapSource objects like BitmapImage can only have their properties


// changed within a BeginInit/EndInit block.
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri("sampleImages/WaterLilies.jpg",UriKind.Relative);

// To save significant application memory, set the DecodePixelWidth or


// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();

////////// Convert the BitmapSource to a new format ////////////


// Use the BitmapImage created above as the source for a new BitmapSource object
// which is set to a gray scale format using the FormatConvertedBitmap BitmapSource.
// Note: New BitmapSource does not cache. It is always pulled when required.

FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap();

// BitmapSource objects like FormatConvertedBitmap can only have their properties


// changed within a BeginInit/EndInit block.
newFormatedBitmapSource.BeginInit();

// Use the BitmapSource object defined above as the source for this new
// BitmapSource (chain the BitmapSource objects together).
newFormatedBitmapSource.Source = myBitmapImage;

// Set the new format to Gray32Float (grayscale).


newFormatedBitmapSource.DestinationFormat = createPixelFormat();
newFormatedBitmapSource.EndInit();
'/// Create a BitmapImage and set it's DecodePixelWidth to 200. Use /////
'/// this BitmapImage as a source for other BitmapSource objects. /////
Dim myBitmapImage As New BitmapImage()

' BitmapSource objects like BitmapImage can only have their properties
' changed within a BeginInit/EndInit block.
myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("sampleImages/WaterLilies.jpg", UriKind.Relative)

' To save significant application memory, set the DecodePixelWidth or


' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()

'//////// Convert the BitmapSource to a new format ////////////


' Use the BitmapImage created above as the source for a new BitmapSource object
' which is set to a gray scale format using the FormatConvertedBitmap BitmapSource.
' Note: New BitmapSource does not cache. It is always pulled when required.
Dim newFormatedBitmapSource As New FormatConvertedBitmap()

' BitmapSource objects like FormatConvertedBitmap can only have their properties
' changed within a BeginInit/EndInit block.
newFormatedBitmapSource.BeginInit()

' Use the BitmapSource object defined above as the source for this new
' BitmapSource (chain the BitmapSource objects together).
newFormatedBitmapSource.Source = myBitmapImage

' Set the new format to Gray32Float (grayscale).


newFormatedBitmapSource.DestinationFormat = createPixelFormat()
newFormatedBitmapSource.EndInit()

Vea también
Información general sobre imágenes
Procedimiento Convertir un elemento BitmapSource
a un formato de píxeles indexado
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo convertir un BitmapSource a un formato de píxeles indizado.

Ejemplo
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Collections.Generic;
namespace SDKSample
{
public partial class FormatConvertedBitmapExample2 : Page
{
public FormatConvertedBitmapExample2()
{

///// Create a BitmapImage and set it's DecodePixelWidth to 200. Use /////
///// this BitmapImage as a source for other BitmapSource objects. /////

BitmapImage myBitmapImage = new BitmapImage();

// BitmapSource objects like BitmapImage can only have their properties


// changed within a BeginInit/EndInit block.
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"sampleImages/WaterLilies.jpg",UriKind.Relative);

// To save significant application memory, set the DecodePixelWidth or


// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();

////////// Convert the BitmapSource to a new format ////////////


// Use the BitmapImage created above as the source for a new BitmapSource object
// which is set to a two color pixel format using the FormatConvertedBitmap BitmapSource.
// Note: New BitmapSource does not cache. It is always pulled when required.

FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap();

// BitmapSource objects like FormatConvertedBitmap can only have their properties


// changed within a BeginInit/EndInit block.
newFormatedBitmapSource.BeginInit();

// Use the BitmapSource object defined above as the source for this new
// BitmapSource (chain the BitmapSource objects together).
newFormatedBitmapSource.Source = myBitmapImage;

// Because the DestinationFormat for the FormatConvertedBitmap will be an


// indexed pixel format (Indexed1),a DestinationPalette also needs to be specified.
// Below, create a custom two color palette to be used for the DestinationPalette.
List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
colors.Add(System.Windows.Media.Colors.Red);
colors.Add(System.Windows.Media.Colors.Blue);
BitmapPalette myPalette = new BitmapPalette(colors);

// Set the DestinationPalette property to the custom palette created above.


newFormatedBitmapSource.DestinationPalette = myPalette;

// Set the DestinationFormat to the palletized pixel format of Indexed1.


newFormatedBitmapSource.DestinationFormat = PixelFormats.Indexed1;
newFormatedBitmapSource.EndInit();

// Create Image Element


Image myImage = new Image();
myImage.Width = 200;
//set image source
myImage.Source = newFormatedBitmapSource;

// Add Image to the UI


StackPanel myStackPanel = new StackPanel();
myStackPanel.Children.Add(myImage);
this.Content = myStackPanel;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Collections.Generic

Namespace SDKSample

Class FormatConvertedBitmapExample2
Inherits Page

Public Sub New()

'/// Create a BitmapImage and set it's DecodePixelWidth to 200. Use /////
'/// this BitmapImage as a source for other BitmapSource objects. /////
Dim myBitmapImage As New BitmapImage()

' BitmapSource objects like BitmapImage can only have their properties
' changed within a BeginInit/EndInit block.
myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("sampleImages/WaterLilies.jpg", UriKind.Relative)

' To save significant application memory, set the DecodePixelWidth or


' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()

'//////// Convert the BitmapSource to a new format ////////////


' Use the BitmapImage created above as the source for a new BitmapSource object
' which is set to a two color pixel format using the FormatConvertedBitmap BitmapSource.
' Note: New BitmapSource does not cache. It is always pulled when required.
Dim newFormatedBitmapSource As New FormatConvertedBitmap()

' BitmapSource objects like FormatConvertedBitmap can only have their properties
' changed within a BeginInit/EndInit block.
newFormatedBitmapSource.BeginInit()
' Use the BitmapSource object defined above as the source for this new
' BitmapSource (chain the BitmapSource objects together).
newFormatedBitmapSource.Source = myBitmapImage

' Because the DestinationFormat for the FormatConvertedBitmap will be an


' indexed pixel format (Indexed1),a DestinationPalette also needs to be specified.
' Below, create a custom two color palette to be used for the DestinationPalette.
Dim colors As New List(Of Color)
colors.Add(System.Windows.Media.Colors.Red)
colors.Add(System.Windows.Media.Colors.Blue)
Dim myPalette As New BitmapPalette(colors)

' Set the DestinationPalette property to the custom palette created above.
newFormatedBitmapSource.DestinationPalette = myPalette

' Set the DestinationFormat to the palletized pixel format of Indexed1.


newFormatedBitmapSource.DestinationFormat = PixelFormats.Indexed1
newFormatedBitmapSource.EndInit()

' Create Image Element


Dim myImage As New Image()
myImage.Width = 200
'set image source
myImage.Source = newFormatedBitmapSource

' Add Image to the UI


Dim myStackPanel As New StackPanel()
myStackPanel.Children.Add(myImage)
Me.Content = myStackPanel

End Sub
End Class
End Namespace 'ImagingSnippetGallery
Procedimiento Codificar y descodificar una imagen
JPEG
23/10/2019 • 2 minutes to read • Edit Online

Los ejemplos siguientes muestran cómo descodificar y codificar imágenes JPEG con específico del
JpegBitmapDecoder y JpegBitmapEncoder objetos.

Por ejemplo, descodificar una imagen JPEG


En este ejemplo se muestra cómo descodificar una imagen JPEG mediante un JpegBitmapDecoder desde un
FileStream.

// Open a Stream and decode a JPEG image


Stream^ imageStreamSource = gcnew FileStream("tulipfarm.jpg", FileMode::Open, FileAccess::Read,
FileShare::Read);
JpegBitmapDecoder^ decoder = gcnew JpegBitmapDecoder(imageStreamSource,
BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);
BitmapSource^ bitmapSource = decoder->Frames[0];

// Draw the Image


Image^ myImage = gcnew Image();
myImage->Source = bitmapSource;
myImage->Stretch = Stretch::None;
myImage->Margin = System::Windows::Thickness(20);

// Open a Stream and decode a JPEG image


Stream imageStreamSource = new FileStream("tulipfarm.jpg", FileMode.Open, FileAccess.Read, FileShare.Read);
JpegBitmapDecoder decoder = new JpegBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];

// Draw the Image


Image myImage = new Image();
myImage.Source = bitmapSource;
myImage.Stretch = Stretch.None;
myImage.Margin = new Thickness(20);

' Open a Stream and decode a JPEG image


Dim imageStreamSource As New FileStream("tulipfarm.jpg", FileMode.Open, FileAccess.Read, FileShare.Read)
Dim decoder As New JpegBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim bitmapSource As BitmapSource = decoder.Frames(0)

' Draw the Image


Dim myImage As New Image()
myImage.Source = bitmapSource
myImage.Stretch = Stretch.None
myImage.Margin = New Thickness(20)

Ejemplo: codificar una imagen JPEG


En este ejemplo se muestra cómo codificar un BitmapSource en formato JPEG de la imagen mediante un
JpegBitmapEncoder.

int width = 128;


int height = width;
int stride = width / 8;
array<System::Byte>^ pixels = gcnew array<System::Byte>(height * stride);

// Define the image palette


BitmapPalette^ myPalette = BitmapPalettes::Halftone256;

// Creates a new empty image with the pre-defined palette.


BitmapSource^ image = BitmapSource::Create(
width, height,
96, 96,
PixelFormats::Indexed1,
myPalette,
pixels,
stride);

System::IO::FileStream^ stream = gcnew System::IO::FileStream("new.jpg", FileMode::Create);


JpegBitmapEncoder^ encoder = gcnew JpegBitmapEncoder();
TextBlock^ myTextBlock = gcnew System::Windows::Controls::TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->FlipHorizontal = true;
encoder->FlipVertical = false;
encoder->QualityLevel = 30;
encoder->Rotation = Rotation::Rotate90;
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);

int width = 128;


int height = width;
int stride = width / 8;
byte[] pixels = new byte[height * stride];

// Define the image palette


BitmapPalette myPalette = BitmapPalettes.Halftone256;

// Creates a new empty image with the pre-defined palette


BitmapSource image = BitmapSource.Create(
width,
height,
96,
96,
PixelFormats.Indexed1,
myPalette,
pixels,
stride);

FileStream stream = new FileStream("new.jpg", FileMode.Create);


JpegBitmapEncoder encoder = new JpegBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.FlipHorizontal = true;
encoder.FlipVertical = false;
encoder.QualityLevel = 30;
encoder.Rotation = Rotation.Rotate90;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
Dim width As Integer = 128
Dim height As Integer = width
Dim stride As Integer = CType(width / 8, Integer)
Dim pixels(height * stride) As Byte

' Define the image palette


Dim myPalette As BitmapPalette = BitmapPalettes.Halftone256

' Creates a new empty image with the pre-defined palette


Dim image As BitmapSource = System.Windows.Media.Imaging.BitmapSource.Create(width, height, 96, 96,
PixelFormats.Indexed1, myPalette, pixels, stride)
Dim stream As New FileStream("new.jpg", FileMode.Create)
Dim encoder As New JpegBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.FlipHorizontal = True
encoder.FlipVertical = False
encoder.QualityLevel = 30
encoder.Rotation = Rotation.Rotate90
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)

Vea también
Información general sobre imágenes
Procedimiento Codificar y descodificar una imagen
BMP
23/10/2019 • 2 minutes to read • Edit Online

En los siguientes ejemplos se muestra cómo descodificar y codificar una imagen de mapa de bits (
BmpBitmapDecoder BMP BmpBitmapEncoder ) mediante los objetos y específicos.

Ejemplo
En este ejemplo se muestra cómo descodificar una imagen BMP BmpBitmapDecoder con un Uride.

// Open a Uri and decode a BMP image


System::Uri^ myUri = gcnew System::Uri("tulipfarm.bmp", UriKind::RelativeOrAbsolute);
BmpBitmapDecoder^ decoder2 = gcnew BmpBitmapDecoder(myUri, BitmapCreateOptions::PreservePixelFormat,
BitmapCacheOption::Default);
BitmapSource^ bitmapSource2 = decoder2->Frames[0];

// Draw the Image


Image^ myImage2 = gcnew Image();
myImage2->Source = bitmapSource2;
myImage2->Stretch = Stretch::None;
myImage2->Margin = System::Windows::Thickness(20);

// Open a Uri and decode a BMP image


Uri myUri = new Uri("tulipfarm.bmp", UriKind.RelativeOrAbsolute);
BmpBitmapDecoder decoder2 = new BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapSource bitmapSource2 = decoder2.Frames[0];

// Draw the Image


Image myImage2 = new Image();
myImage2.Source = bitmapSource2;
myImage2.Stretch = Stretch.None;
myImage2.Margin = new Thickness(20);

' Open a Uri and decode a BMP image


Dim myUri As New Uri("tulipfarm.bmp", UriKind.RelativeOrAbsolute)
Dim decoder2 As New BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim bitmapSource2 As BitmapSource = decoder2.Frames(0)

' Draw the Image


Dim myImage2 As New Image()
myImage2.Source = bitmapSource2
myImage2.Stretch = Stretch.None
myImage2.Margin = New Thickness(20)

Ejemplo
En este ejemplo se muestra cómo codificar BitmapSource un en una imagen BMP BmpBitmapEncodermediante.
int width = 128;
int height = width;
int stride = width / 8;
array<System::Byte>^ pixels = gcnew array<System::Byte>(height * stride);

List<Color>^ colors = gcnew List<Color>();


colors->Add(Colors::Red);
colors->Add(Colors::Blue);
colors->Add(Colors::Green);
BitmapPalette^ myPalette = gcnew BitmapPalette(colors);

// Creates a new empty image with the pre-defined palette

BitmapSource^ image = BitmapSource::Create(


width,
height,
96,
96,
PixelFormats::Indexed1,
myPalette,
pixels,
stride);

FileStream^ stream = gcnew FileStream("new.bmp", FileMode::Create);


BmpBitmapEncoder^ encoder = gcnew BmpBitmapEncoder();
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);

int width = 128;


int height = width;
int stride = width / 8;
byte[] pixels = new byte[height * stride];

// Try creating a new image with a custom palette.


List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
colors.Add(System.Windows.Media.Colors.Red);
colors.Add(System.Windows.Media.Colors.Blue);
colors.Add(System.Windows.Media.Colors.Green);
BitmapPalette myPalette = new BitmapPalette(colors);

// Creates a new empty image with the pre-defined palette


BitmapSource image = BitmapSource.Create(
width,
height,
96,
96,
PixelFormats.Indexed1,
myPalette,
pixels,
stride);

FileStream stream = new FileStream("new.bmp", FileMode.Create);


BmpBitmapEncoder encoder = new BmpBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
Dim width As Integer = 128
Dim height As Integer = width
Dim stride As Integer = CType(width / 8, Integer)
Dim pixels(height * stride) As Byte

' Try creating a new image with a custom palette.


Dim colors As New List(Of System.Windows.Media.Color)()
colors.Add(System.Windows.Media.Colors.Red)
colors.Add(System.Windows.Media.Colors.Blue)
colors.Add(System.Windows.Media.Colors.Green)
Dim myPalette As New BitmapPalette(Colors)

' Creates a new empty image with the pre-defined palette


Dim image As BitmapSource = System.Windows.Media.Imaging.BitmapSource.Create(width, height, 96, 96,
PixelFormats.Indexed1, myPalette, pixels, stride)
Dim stream As New FileStream("new.bmp", FileMode.Create)
Dim encoder As New BmpBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)

Vea también
Información general sobre imágenes
Procedimiento Codificar y descodificar una imagen
PNG
23/10/2019 • 2 minutes to read • Edit Online

En los siguientes ejemplos se muestra cómo descodificar y codificar una imagen PNG (Portable Network
Graphics) PngBitmapDecoder mediante PngBitmapEncoder los objetos y específicos.

Ejemplo
En este ejemplo se muestra cómo descodificar una imagen PNG PngBitmapDecoder con un FileStreamde.

// Open a Stream and decode a PNG image


Stream^ imageStreamSource = gcnew FileStream("smiley.png", FileMode::Open, FileAccess::Read, FileShare::Read);
PngBitmapDecoder^ decoder = gcnew PngBitmapDecoder(imageStreamSource,
BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);
BitmapSource^ bitmapSource = decoder->Frames[0];

// Draw the Image


Image^ myImage = gcnew Image();
myImage->Source = bitmapSource;
myImage->Stretch = Stretch::None;
myImage->Margin = System::Windows::Thickness(20);

// Open a Stream and decode a PNG image


Stream imageStreamSource = new FileStream("smiley.png", FileMode.Open, FileAccess.Read, FileShare.Read);
PngBitmapDecoder decoder = new PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];

// Draw the Image


Image myImage = new Image();
myImage.Source = bitmapSource;
myImage.Stretch = Stretch.None;
myImage.Margin = new Thickness(20);

' Open a Stream and decode a PNG image


Dim imageStreamSource As New FileStream("smiley.png", FileMode.Open, FileAccess.Read, FileShare.Read)
Dim decoder As New PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim bitmapSource As BitmapSource = decoder.Frames(0)

' Draw the Image


Dim myImage As New Image()
myImage.Source = bitmapSource
myImage.Stretch = Stretch.None
myImage.Margin = New Thickness(20)

Ejemplo
En este ejemplo se muestra cómo codificar BitmapSource un en una imagen PNG PngBitmapEncodermediante.
int width = 128;
int height = 128;
int stride = width;
array<System::Byte>^ pixels = gcnew array<System::Byte>(height * stride);

// Define the image palette


BitmapPalette^ myPalette = BitmapPalettes::Halftone256;

// Creates a new empty image with the pre-defined palette

BitmapSource^ image = BitmapSource::Create(width,


height,
96,
96,
PixelFormats::Indexed8,
myPalette,
pixels,
stride);

FileStream^ stream = gcnew FileStream("new.png", FileMode::Create);


PngBitmapEncoder^ encoder = gcnew PngBitmapEncoder();
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->Interlace = PngInterlaceOption::On;
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);

int width = 128;


int height = 128;
int stride = width;
byte[] pixels = new byte[height * stride];

// Define the image palette


BitmapPalette myPalette = BitmapPalettes.Halftone256;

// Creates a new empty image with the pre-defined palette

BitmapSource image = BitmapSource.Create(


width,
height,
96,
96,
PixelFormats.Indexed8,
myPalette,
pixels,
stride);

FileStream stream = new FileStream("new.png", FileMode.Create);


PngBitmapEncoder encoder = new PngBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.Interlace = PngInterlaceOption.On;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
Dim width As Integer = 128
Dim height As Integer = 128
Dim stride As Integer = width
Dim pixels(height * stride) As Byte

' Define the image palette


Dim myPalette As BitmapPalette = BitmapPalettes.Halftone256

' Creates a new empty image with the pre-defined palette


Dim image As BitmapSource = System.Windows.Media.Imaging.BitmapSource.Create( _
width, height, 96, 96, PixelFormats.Indexed8, myPalette, pixels, stride)
Dim stream As New FileStream("new.png", FileMode.Create)
Dim encoder As New PngBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.Interlace = PngInterlaceOption.On
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)

Vea también
Información general sobre imágenes
Cómo: Codificar y descodificar una imagen WDP
29/10/2019 • 2 minutes to read • Edit Online

En los siguientes ejemplos se muestra cómo descodificar y codificar una imagen de Microsoft Windows Media
Photo con los objetos WmpBitmapDecoder y WmpBitmapEncoder específicos.

Ejemplo
En este ejemplo se muestra cómo descodificar una imagen de Windows Media Photo mediante una
WmpBitmapDecoder de un Uri.

// Open a Stream and decode a WDP image


Stream^ imageStreamSource = gcnew FileStream("tulipfarm.wdp", FileMode::Open, FileAccess::Read,
FileShare::Read);
WmpBitmapDecoder^ decoder = gcnew WmpBitmapDecoder(imageStreamSource,
BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);
BitmapSource^ bitmapSource = decoder->Frames[0];

// Draw the Image


Image^ myImage = gcnew Image();
myImage->Source = bitmapSource;
myImage->Stretch = Stretch::None;
myImage->Margin = System::Windows::Thickness(20);

// Open a Stream and decode a WDP image


Stream imageStreamSource = new FileStream("tulipfarm.wdp", FileMode.Open, FileAccess.Read, FileShare.Read);
WmpBitmapDecoder decoder = new WmpBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];

// Draw the Image


Image myImage = new Image();
myImage.Source = bitmapSource;
myImage.Stretch = Stretch.None;
myImage.Margin = new Thickness(20);

' Open a Stream and decode a WDP image


Dim imageStreamSource As New FileStream("tulipfarm.wdp", FileMode.Open, FileAccess.Read, FileShare.Read)
Dim decoder As New WmpBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim bitmapSource As BitmapSource = decoder.Frames(0)

' Draw the Image


Dim myImage As New Image()
myImage.Source = bitmapSource
myImage.Stretch = Stretch.None
myImage.Margin = New Thickness(20)

Ejemplo
En este ejemplo se muestra cómo codificar un BitmapSource en una imagen fotográfica de Windows Media
mediante un WmpBitmapEncoder.
int width = 128;
int height = width;
int stride = width / 8;
array<System::Byte>^ pixels = gcnew array<System::Byte>(height * stride);

// Define the image palette


BitmapPalette^ myPalette = BitmapPalettes::WebPalette;

// Creates a new empty image with the pre-defined palette

BitmapSource^ image = BitmapSource::Create(


width,
height,
96,
96,
PixelFormats::Indexed1,
myPalette,
pixels,
stride);

FileStream^ stream = gcnew FileStream("new.wdp", FileMode::Create);


WmpBitmapEncoder^ encoder = gcnew WmpBitmapEncoder();
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);

int width = 128;


int height = width;
int stride = width / 8;
byte[] pixels = new byte[height * stride];

// Define the image palette


BitmapPalette myPalette = BitmapPalettes.WebPalette;

// Creates a new empty image with the pre-defined palette

BitmapSource image = BitmapSource.Create(


width,
height,
96,
96,
PixelFormats.Indexed1,
myPalette,
pixels,
stride);

FileStream stream = new FileStream("new.wdp", FileMode.Create);


WmpBitmapEncoder encoder = new WmpBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
Dim width As Integer = 128
Dim height As Integer = width
Dim stride As Integer = CType(width / 8, Integer)
Dim pixels(height * stride) As Byte

' Define the image palette


Dim myPalette As BitmapPalette = BitmapPalettes.WebPalette

' Creates a new empty image with the pre-defined palette


Dim image As BitmapSource = System.Windows.Media.Imaging.BitmapSource.Create( _
width, height, 96, 96, PixelFormats.Indexed1, myPalette, pixels, stride)
Dim stream As New FileStream("new.wdp", FileMode.Create)
Dim encoder As New WmpBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)

Vea también
Información general sobre imágenes
Procedimiento Codificar y descodificar una imagen
GIF
23/10/2019 • 2 minutes to read • Edit Online

En los siguientes ejemplos se muestra cómo descodificar y codificar una imagen de formato de intercambio de
gráficos ( GifBitmapDecoder GIF GifBitmapEncoder ) mediante los objetos y específicos.

Ejemplo
En este ejemplo se muestra cómo descodificar una imagen GIF GifBitmapDecoder mediante un FileStreamde.

// Open a Stream and decode a GIF image


Stream^ imageStreamSource = gcnew FileStream("tulipfarm.gif", FileMode::Open, FileAccess::Read,
FileShare::Read);
GifBitmapDecoder^ decoder = gcnew GifBitmapDecoder(imageStreamSource,
BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);
BitmapSource^ bitmapSource = decoder->Frames[0];

// Draw the Image


Image^ myImage = gcnew Image();
myImage->Source = bitmapSource;
myImage->Stretch = Stretch::None;
myImage->Margin = System::Windows::Thickness(20);

// Open a Stream and decode a GIF image


Stream imageStreamSource = new FileStream("tulipfarm.gif", FileMode.Open, FileAccess.Read, FileShare.Read);
GifBitmapDecoder decoder = new GifBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];

// Draw the Image


Image myImage = new Image();
myImage.Source = bitmapSource;
myImage.Stretch = Stretch.None;
myImage.Margin = new Thickness(20);

' Open a Stream and decode a GIF image


Dim imageStreamSource As New FileStream("tulipfarm.gif", FileMode.Open, FileAccess.Read, FileShare.Read)
Dim decoder As New GifBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim bitmapSource As BitmapSource = decoder.Frames(0)

' Draw the Image


Dim myImage As New Image()
myImage.Source = bitmapSource
myImage.Stretch = Stretch.None
myImage.Margin = New Thickness(20)

Ejemplo
En este ejemplo se muestra cómo codificar BitmapSource un en una imagen GIF GifBitmapEncodermediante.
int width = 128;
int height = width;
int stride = width / 8;
array<System::Byte>^ pixels = gcnew array<System::Byte>(height * stride);

// Define the image palette

BitmapPalette^ myPalette = BitmapPalettes::WebPalette;

// Creates a new empty image with the pre-defined palette

BitmapSource^ image = BitmapSource::Create(


width,
height,
96,
96,
PixelFormats::Indexed1,
myPalette,
pixels,
stride);

FileStream^ stream = gcnew FileStream("new.gif", FileMode::Create);


GifBitmapEncoder^ encoder = gcnew GifBitmapEncoder();
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);

int width = 128;


int height = width;
int stride = width / 8;
byte[] pixels = new byte[height * stride];

// Define the image palette


BitmapPalette myPalette = BitmapPalettes.WebPalette;

// Creates a new empty image with the pre-defined palette

BitmapSource image = BitmapSource.Create(


width,
height,
96,
96,
PixelFormats.Indexed1,
myPalette,
pixels,
stride);

FileStream stream = new FileStream("new.gif", FileMode.Create);


GifBitmapEncoder encoder = new GifBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
Dim width As Integer = 128
Dim height As Integer = width
Dim stride As Integer = CType(width / 8, Integer)
Dim pixels(height * stride) As Byte

' Define the image palette


Dim myPalette As BitmapPalette = BitmapPalettes.WebPalette

' Creates a new empty image with the pre-defined palette


Dim image As BitmapSource = System.Windows.Media.Imaging.BitmapSource.Create(width, height, 96, 96,
PixelFormats.Indexed1, myPalette, pixels, stride)
Dim stream As New FileStream("new.gif", FileMode.Create)
Dim encoder As New GifBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)

Vea también
Información general sobre imágenes
Procedimiento Codificar y descodificar una imagen
TIFF
23/10/2019 • 2 minutes to read • Edit Online

En los siguientes ejemplos se muestra cómo descodificar y codificar una imagen de Tagged Image File Format
(TIFF ) mediante los objetos TiffBitmapDecoder y TiffBitmapEncoder específicos.

Ejemplo
En este ejemplo se muestra cómo descodificar una imagen TIFF mediante un TiffBitmapDecoder de un Uri.

// Open a Stream and decode a TIFF image.


Stream^ imageStreamSource = gcnew FileStream("tulipfarm.tif", FileMode::Open, FileAccess::Read,
FileShare::Read);
TiffBitmapDecoder^ decoder = gcnew TiffBitmapDecoder(imageStreamSource,
BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);
BitmapSource^ bitmapSource = decoder->Frames[0];

// Draw the Image.


Image^ myImage = gcnew Image();
myImage->Source = bitmapSource;
myImage->Stretch = Stretch::None;
myImage->Margin = System::Windows::Thickness(20);

// Open a Stream and decode a TIFF image.


Stream imageStreamSource = new FileStream("tulipfarm.tif", FileMode.Open, FileAccess.Read, FileShare.Read);
var decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];

// Draw the Image.


var myImage = new Image();
myImage.Source = bitmapSource;
myImage.Stretch = Stretch.None;
myImage.Margin = new Thickness(20);

' Open a Stream and decode a TIFF image.


Dim imageStreamSource As New FileStream("tulipfarm.tif", FileMode.Open, FileAccess.Read, FileShare.Read)
Dim decoder As New TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim bitmapSource As BitmapSource = decoder.Frames(0)

' Draw the Image.


Dim myImage As New Image()
myImage.Source = bitmapSource
myImage.Stretch = Stretch.None
myImage.Margin = New Thickness(20)

Ejemplo
En este ejemplo se muestra cómo codificar un BitmapSource en una imagen TIFF mediante un TiffBitmapEncoder.
int width = 128;
int height = width;
int stride = width / 8;
array<System::Byte>^ pixels = gcnew array<System::Byte>(height * stride);

// Define the image palette.


BitmapPalette^ myPalette = BitmapPalettes::WebPalette;

// Creates a new empty image with the pre-defined palette.

BitmapSource^ image = BitmapSource::Create(width,


height,
96,
96,
PixelFormats::Indexed1,
myPalette,
pixels,
stride);

FileStream^ stream = gcnew FileStream("new.tif", FileMode::Create);


TiffBitmapEncoder^ encoder = gcnew TiffBitmapEncoder();
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->Compression = TiffCompressOption::Zip;
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);

int width = 128;


int height = width;
int stride = width / 8;
byte[] pixels = new byte[height * stride];

// Define the image palette.


BitmapPalette myPalette = BitmapPalettes.WebPalette;

// Creates a new empty image with the pre-defined palette.

BitmapSource image = BitmapSource.Create(


width,
height,
96,
96,
PixelFormats.Indexed1,
myPalette,
pixels,
stride);

var stream = new FileStream("new.tif", FileMode.Create);


var encoder = new TiffBitmapEncoder();
var myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.Compression = TiffCompressOption.Zip;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
Dim width As Integer = 128
Dim height As Integer = width
Dim stride As Integer = width / 8
Dim pixels(height * stride - 1) As Byte

' Define the image palette.


Dim myPalette As BitmapPalette = BitmapPalettes.WebPalette

' Creates a new empty image with the pre-defined palette.


Dim image As BitmapSource = BitmapSource.Create( _
width, height, 96, 96, PixelFormats.Indexed1, myPalette, pixels, stride)
Dim stream As New FileStream("new.tif", FileMode.Create)
Dim encoder As New TiffBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.Compression = TiffCompressOption.Zip
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)

Vea también
Información general sobre imágenes
Procedimiento Escribir metadatos en un mapa de bits
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo escribir metadatos en un mapa de bits mediante el lenguaje de consulta de
metadatos.

Ejemplo
Stream^ pngStream = gcnew FileStream("smiley.png", FileMode::Open, FileAccess::ReadWrite,
FileShare::ReadWrite);
PngBitmapDecoder^ pngDecoder = gcnew PngBitmapDecoder(pngStream, BitmapCreateOptions::PreservePixelFormat,
BitmapCacheOption::Default);
BitmapFrame^ pngFrame = pngDecoder->Frames[0];
InPlaceBitmapMetadataWriter^ pngInplace = pngFrame->CreateInPlaceBitmapMetadataWriter();
if (pngInplace->TrySave() == true)
{
pngInplace->SetQuery("/Text/Description", "Have a nice day.");
}
pngStream->Close();

Stream pngStream = new System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite,


FileShare.ReadWrite);
PngBitmapDecoder pngDecoder = new PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapFrame pngFrame = pngDecoder.Frames[0];
InPlaceBitmapMetadataWriter pngInplace = pngFrame.CreateInPlaceBitmapMetadataWriter();
if (pngInplace.TrySave() == true)
{ pngInplace.SetQuery("/Text/Description", "Have a nice day."); }
pngStream.Close();

Dim pngStream As New System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite,


FileShare.ReadWrite)
Dim pngDecoder As New PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default)
Dim pngFrame As BitmapFrame = pngDecoder.Frames(0)
Dim pngInplace As InPlaceBitmapMetadataWriter = pngFrame.CreateInPlaceBitmapMetadataWriter()
If pngInplace.TrySave() = True Then
pngInplace.SetQuery("/Text/Description", "Have a nice day.")
End If
pngStream.Close()
Procedimiento Leer metadatos de un mapa de bits
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo leer los metadatos de mapa de bits mediante el lenguaje de consulta de
metadatos.

Ejemplo
// Add the metadata of the bitmap image to the text block.
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "The Description metadata of this image is: " + pngInplace->GetQuery("/Text/Description")-
>ToString();

// Add the metadata of the bitmap image to the text block.


TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "The Description metadata of this image is: " +
pngInplace.GetQuery("/Text/Description").ToString();

' Add the metadata of the bitmap image to the text block.
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "The Description metadata of this image is: " +
pngInplace.GetQuery("/Text/Description").ToString()
Formas
23/10/2019 • 2 minutes to read • Edit Online

Windows Presentation Foundation (WPF ) proporciona compatibilidad para dibujar formas básicas mediante el
Shape clase. Los objetos de forma que se derivan de FrameworkElement y por lo tanto, participar en el sistema de
diseño y se pueden dibujar usando simplemente Lenguaje XAML (Extensible Application Markup Language).

En esta sección
Información general sobre formas y dibujo básico en WPF
Temas "Cómo..."

Vea también
Shape
Imágenes y gráficos 2D
Gráficos y multimedia
Información general sobre formas y dibujo básico
en WPF
03/02/2020 • 15 minutes to read • Edit Online

En este tema se proporciona información general sobre cómo dibujar con objetos Shape. Un Shape es un tipo
de UIElement que permite dibujar una forma en la pantalla. Dado que son elementos de interfaz de usuario, se
pueden usar Shape objetos dentro de Panel elementos y la mayoría de los controles.
Windows Presentation Foundation (WPF ) ofrece varias capas de acceso a gráficos y servicios de
representación. En la capa superior, los objetos Shape son fáciles de usar y proporcionan muchas
características útiles, como el diseño y la participación en el sistema de eventos Windows Presentation
Foundation (WPF ).

Objetos Shape
WPF proporciona varios objetos Shape listos para usar. Todos los objetos de forma se heredan de la clase
Shape. Los objetos de forma disponibles incluyen Ellipse, Line, Path, Polygon, Polyliney Rectangle. Shape
objetos comparten las siguientes propiedades comunes.
Stroke: describe cómo se pinta el contorno de la forma.
StrokeThickness: describe el grosor del contorno de la forma.
Fill: describe cómo se pinta el interior de la forma.
Propiedades de datos para especificar coordenadas y vértices, medidos en píxeles independientes del
dispositivo.
Dado que se derivan de UIElement, los objetos de forma se pueden usar dentro de los paneles y la mayoría de
los controles. El panel de Canvas es una opción especialmente adecuada para crear dibujos complejos porque
admite el posicionamiento absoluto de sus objetos secundarios.
La clase Line permite dibujar una línea entre dos puntos. En el ejemplo siguiente se muestran varias maneras
de especificar coordenadas de línea y propiedades de trazo.
<Canvas Height="300" Width="300">

<!-- Draws a diagonal line from (10,10) to (50,50). -->


<Line
X1="10" Y1="10"
X2="50" Y2="50"
Stroke="Black"
StrokeThickness="4" />

<!-- Draws a diagonal line from (10,10) to (50,50)


and moves it 100 pixels to the right. -->
<Line
X1="10" Y1="10"
X2="50" Y2="50"
StrokeThickness="4"
Canvas.Left="100">
<Line.Stroke>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="Red" Offset="0" />
<GradientStop Color="Blue" Offset="0.25" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Line.Stroke>
</Line>

<!-- Draws a horizontal line from (10,60) to (150,60). -->


<Line
X1="10" Y1="60"
X2="150" Y2="60"
Stroke="Black"
StrokeThickness="4"/>

</Canvas>

// Add a Line Element


myLine = gcnew Line();
myLine->Stroke = Brushes::LightSteelBlue;
myLine->X1 = 1;
myLine->X2 = 50;
myLine->Y1 = 1;
myLine->Y2 = 50;
myLine->HorizontalAlignment = HorizontalAlignment::Left;
myLine->VerticalAlignment = VerticalAlignment::Center;
myLine->StrokeThickness = 2;
myGrid->Children->Add(myLine);

// Add a Line Element


myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1;
myLine.X2 = 50;
myLine.Y1 = 1;
myLine.Y2 = 50;
myLine.HorizontalAlignment = HorizontalAlignment.Left;
myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
myGrid.Children.Add(myLine);
' Add a Line Element
Dim myLine As New Line()
myLine.Stroke = Brushes.LightSteelBlue
myLine.X1 = 1
myLine.X2 = 50
myLine.Y1 = 1
myLine.Y2 = 50
myLine.HorizontalAlignment = HorizontalAlignment.Left
myLine.VerticalAlignment = VerticalAlignment.Center
myLine.StrokeThickness = 2
myGrid.Children.Add(myLine)

En la imagen siguiente se muestra el Linerepresentado.

Aunque la clase Line proporciona una propiedad Fill, establecerla no tiene ningún efecto porque un Line no
tiene área.
Otra forma común es la Ellipse. Cree una Ellipse definiendo las propiedades Width y Height de la forma. Para
dibujar un círculo, especifique una Ellipse cuyos valores de Width y Height sean iguales.

<Ellipse
Fill="Yellow"
Height="100"
Width="200"
StrokeThickness="2"
Stroke="Black"/>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace SDKSample
{
public partial class SetBackgroundColorOfShapeExample : Page
{
public SetBackgroundColorOfShapeExample()
{
// Create a StackPanel to contain the shape.
StackPanel myStackPanel = new StackPanel();

// Create a red Ellipse.


Ellipse myEllipse = new Ellipse();

// Create a SolidColorBrush with a red color to fill the


// Ellipse with.
SolidColorBrush mySolidColorBrush = new SolidColorBrush();

// Describes the brush's color using RGB values.


// Each value has a range of 0-255.
mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0);
myEllipse.Fill = mySolidColorBrush;
myEllipse.StrokeThickness = 2;
myEllipse.Stroke = Brushes.Black;

// Set the width and height of the Ellipse.


myEllipse.Width = 200;
myEllipse.Height = 100;

// Add the Ellipse to the StackPanel.


myStackPanel.Children.Add(myEllipse);

this.Content = myStackPanel;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes

Namespace SDKSample
Partial Public Class SetBackgroundColorOfShapeExample
Inherits Page
Public Sub New()
' Create a StackPanel to contain the shape.
Dim myStackPanel As New StackPanel()

' Create a red Ellipse.


Dim myEllipse As New Ellipse()

' Create a SolidColorBrush with a red color to fill the


' Ellipse with.
Dim mySolidColorBrush As New SolidColorBrush()

' Describes the brush's color using RGB values.


' Each value has a range of 0-255.
mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0)
myEllipse.Fill = mySolidColorBrush
myEllipse.StrokeThickness = 2
myEllipse.Stroke = Brushes.Black

' Set the width and height of the Ellipse.


myEllipse.Width = 200
myEllipse.Height = 100

' Add the Ellipse to the StackPanel.


myStackPanel.Children.Add(myEllipse)

Me.Content = myStackPanel
End Sub

End Class
End Namespace

En la imagen siguiente se muestra un ejemplo de una Ellipserepresentada.

Utilizar trazados y geometrías


La clase Path permite dibujar curvas y formas complejas. Estas curvas y formas se describen mediante objetos
Geometry. Para usar un Path, cree un Geometry y úselo para establecer la propiedad Data del objeto Path.
Hay una variedad de objetos de Geometry entre los que elegir. Las clases LineGeometry, RectangleGeometryy
EllipseGeometry describen formas relativamente simples. Para crear formas más complejas o crear curvas, use
una PathGeometry.
PathGeometry y PathSegments
PathGeometry objetos se componen de uno o varios objetos PathFigure; cada PathFigure representa una
"figura" o forma diferente. Cada PathFigure se compone de uno o varios objetos PathSegment, cada uno de
los cuales representa una parte conectada de la figura o forma. Entre los tipos de segmentos se incluyen los
siguientes: LineSegment, BezierSegmenty ArcSegment.
En el ejemplo siguiente, se usa un Path para dibujar una curva Bézier cuadrática.

<Path Stroke="Black" StrokeThickness="1">


<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment Point1="200,200" Point2="300,100" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>

La siguiente imagen muestra la forma representada.

Para obtener más información sobre PathGeometry y las demás clases de Geometry, consulte la información
general sobre geometría.
Sintaxis abreviada de XAML
En Lenguaje XAML (Extensible Application Markup Language), también puede usar una sintaxis abreviada
especial para describir un Path. En el ejemplo siguiente, se utiliza la sintaxis abreviada para dibujar una forma
compleja.

<Path Stroke="DarkGoldenRod" StrokeThickness="3"


Data="M 100,200 C 100,25 400,350 400,175 H 280" />

En la imagen siguiente se muestra una Pathrepresentada.

La cadena de atributo de Data comienza con el comando "moveTo", indicado por M, que establece un punto de
inicio para la ruta de acceso en el sistema de coordenadas del Canvas. Path parámetros de datos distinguen
mayúsculas de minúsculas. La letra M mayúscula indica una ubicación absoluta para el nuevo punto actual.
Una m minúscula indica coordenadas relativas. El primer segmento es una curva de Bézier cúbica que
comienza en (100,200) y termina en (400,175), trazado con los dos puntos de control (100,25) y (400,350).
Este segmento se indica mediante el comando C en la cadena de atributo Data. De nuevo, la C mayúscula
indica una ruta de acceso absoluta; la c minúscula indicaría una ruta de acceso relativa.
El segundo segmento comienza con un comando H "lineto" horizontal absoluto, que especifica una línea
trazada desde el punto de conexión del subtrazado anterior (400,175) hasta un nuevo punto de conexión
(280,175). Dado que es un comando "lineTo" horizontal, el valor especificado es una coordenada x.
Para obtener la sintaxis de ruta de acceso completa, vea la referencia de Data y crear una forma mediante
PathGeometry.

Pintar formas
Brush objetos se utilizan para pintar el Stroke y el Fillde una forma. En el ejemplo siguiente, se especifican el
trazo y el relleno de un Ellipse. Tenga en cuenta que una entrada válida para las propiedades del pincel puede
ser una palabra clave o el valor de color en formato hexadecimal. Para obtener más información sobre las
palabras clave de color disponibles, consulte propiedades de la clase Colors en el espacio de nombres
System.Windows.Media.

<Canvas Background="LightGray">
<Ellipse
Canvas.Top="50"
Canvas.Left="50"
Fill="#FFFFFF00"
Height="75"
Width="75"
StrokeThickness="5"
Stroke="#FF0000FF"/>
</Canvas>

En la imagen siguiente se muestra el Ellipserepresentado.

Como alternativa, puede usar la sintaxis de elementos de propiedad para crear explícitamente un objeto
SolidColorBrush para pintar la forma con un color sólido.
<!-- This polygon shape uses pre-defined color values for its Stroke and
Fill properties.
The SolidColorBrush's Opacity property affects the fill color in
this case by making it slightly transparent (opacity of 0.4) so
that it blends with any underlying color. -->

<Polygon
Points="300,200 400,125 400,275 300,200"
Stroke="Purple"
StrokeThickness="2">
<Polygon.Fill>
<SolidColorBrush Color="Blue" Opacity="0.4"/>
</Polygon.Fill>
</Polygon>

En la ilustración siguiente se muestra la forma representada.

También puede pintar el trazo o relleno de una forma con degradados, imágenes, patrones y mucho más. Para
obtener más información, consulte la información General sobre el dibujo con colores sólidos y degradados.

Formas extensibles
Todas las clases Line, Path, Polygon, Polyliney Rectangle tienen una propiedad Stretch. Esta propiedad
determina cómo se ajusta el contenido de un objeto Shape (la forma que se va a dibujar) para rellenar el
espacio de diseño del objeto Shape. El espacio de diseño de un objeto Shape es la cantidad de espacio que el
sistema de diseño asigna al Shape, debido a un valor de Width explícito y Height, o debido a su configuración
HorizontalAlignment y VerticalAlignment. Para obtener información adicional sobre el diseño en Windows
Presentation Foundation, consulte información general de diseño .
La propiedad Stretch puede tener uno de los siguientes valores:
None: el contenido del objeto de Shape no se ajusta.
Fill: el contenido del objeto de Shape se ajusta para rellenar el espacio de diseño. No se mantiene la
relación de aspecto.
Uniform: el contenido del objeto de Shape se ajusta tanto como sea posible para rellenar el espacio de
diseño a la vez que conserva su relación de aspecto original.
UniformToFill: el contenido del objeto de la Shape se ajusta para rellenar completamente su espacio de
diseño conservando la relación de aspecto original.
Tenga en cuenta que, cuando se ajusta el contenido de un objeto Shape, el contorno del objeto Shape se pinta
después de la ampliación.
En el ejemplo siguiente, se usa un Polygon para dibujar un triángulo muy pequeño de (0,0) a (0,1) a (1,1). Los
Width y Height del objeto de Polygon se establecen en 100 y su propiedad Stretch está establecida en Fill.
Como resultado, el contenido del objeto Polygon (el triángulo) se ajusta para rellenar el espacio mayor.

<Polygon
Points="0,0 0,1 1,1"
Fill="Blue"
Width="100"
Height="100"
Stretch="Fill"
Stroke="Black"
StrokeThickness="2" />

PointCollection myPointCollection = new PointCollection();


myPointCollection.Add(new Point(0,0));
myPointCollection.Add(new Point(0,1));
myPointCollection.Add(new Point(1,1));

Polygon myPolygon = new Polygon();


myPolygon.Points = myPointCollection;
myPolygon.Fill = Brushes.Blue;
myPolygon.Width = 100;
myPolygon.Height = 100;
myPolygon.Stretch = Stretch.Fill;
myPolygon.Stroke = Brushes.Black;
myPolygon.StrokeThickness = 2;

Transformar formas
La clase Transform proporciona los medios para transformar las formas en un plano bidimensional. Los
distintos tipos de transformaciones incluyen la rotación (RotateTransform), la escala (ScaleTransform), el sesgo
(SkewTransform) y la traslación (TranslateTransform).
Una transformación común para aplicar a una forma es la rotación. Para girar una forma, cree un
RotateTransform y especifique su Angle. Un Angle de 45 gira el elemento 45 grados en el sentido de las agujas
del reloj; un ángulo de 90 gira el elemento 90 grados en el sentido de las agujas del reloj; etc. Establezca las
propiedades CenterX y CenterY si desea controlar el punto sobre el que se gira el elemento. Estos valores de
propiedad se expresan en el espacio de coordenadas del elemento que se va a transformar. CenterX y CenterY
tienen valores predeterminados de cero. Por último, aplique el RotateTransform al elemento. Si no desea que
la transformación afecte al diseño, establezca la propiedad RenderTransform de la forma.
En el ejemplo siguiente, se usa un RotateTransform para girar una forma 45 grados sobre la esquina superior
izquierda de la forma (0,0).

<!-- Rotates the Polyline 45 degrees about the point (0,0). -->
<Polyline Points="25,25 0,50 25,75 50,50 25,25 25,0"
Stroke="Blue" StrokeThickness="10"
Canvas.Left="75" Canvas.Top="50">
<Polyline.RenderTransform>
<RotateTransform CenterX="0" CenterY="0" Angle="45" />
</Polyline.RenderTransform>
</Polyline>

En el ejemplo siguiente, otra forma se gira 45 grados, pero esta vez se gira alrededor del punto (25,50).
<!-- Rotates the Polyline 45 degrees about its center. -->
<Polyline
Points="25,25 0,50 25,75 50,50 25,25 25,0"
Stroke="Blue" StrokeThickness="10"
Canvas.Left="75" Canvas.Top="50"
RenderTransformOrigin="0.5,0.5">
<Polyline.RenderTransform>
<RotateTransform Angle="45" />
</Polyline.RenderTransform>
</Polyline>

En la ilustración siguiente se muestran los resultados de aplicar las dos transformaciones.

En los ejemplos anteriores, se aplicó una única transformación a cada objeto de forma. Para aplicar varias
transformaciones a una forma (o cualquier otro elemento de la interfaz de usuario), use una TransformGroup.

Consulte también
Imágenes y gráficos 2D
Información general sobre el dibujo con colores sólidos y degradados
Información general sobre geometría
Tutorial: Mi primera aplicación de escritorio WPF
Información general sobre animaciones
Temas "Cómo..." de formas
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección muestran cómo usar Shape objetos que se va a dibujar formas básicas en la pantalla.

En esta sección
Dibujar una forma cerrada utilizando el elemento Polygon
Dibujar una elipse o un círculo
Dibujar una línea
Dibujar una Polilínea mediante el uso del elemento Polyline
Dibujar un rectángulo
Modificar el extremo en el final de una línea o segmento

Vea también
Shape
Gráficos y multimedia
Cómo: Dibujar una forma cerrada utilizando el
elemento Polygon
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo dibujar una forma cerrada utilizando el elemento Polygon. Para dibujar una
forma cerrada, cree un elemento Polygon y utilice su propiedad Points para especificar los vértices de una forma.
Se dibuja automáticamente una línea que conecta los puntos primero y último. Por último, especifique un Fill, un
Strokeo ambos.

Ejemplo
En Lenguaje XAML (Extensible Application Markup Language), la sintaxis válida para los puntos es una lista
delimitada por espacios de pares de coordenadas x e y separadas por comas.

<Canvas Height="300" Width="300">

<!-- Draws a triangle with a blue interior. -->


<Polygon Points="10,110 60,10 110,110"
Fill="Blue" />

<!-- Draws a triangle with a blue interior and a black outline.


The Canvas.Top setting moves the Polygon down 150 pixels. -->
<Polygon Points="10,110 60,10 110,110"
Fill="Blue"
Stroke="Black" StrokeThickness="4"
Canvas.Top="150" />

<!-- Draws another triangle with a blue interior.


The Canvas.Left setting moves the Polygon 150 pixels to the right. -->
<Polygon Points="10,110 110,110 110,10"
Fill="Blue"
Canvas.Left="150" />

<!-- Draws a triangle with a black outline.


The Canvas.Left and Canvas.Top settings move
the Polygon down 150 pixels and 150 pixels to the right.-->
<Polygon Points="10,110 110,110 110,10"
Stroke="Black" StrokeThickness="4"
Canvas.Left="150" Canvas.Top="150" />

</Canvas>

Aunque en el ejemplo se usa una Canvas para contener los polígonos, puede utilizar elementos Polygon (y todos
los demás elementos de forma) con cualquier Panel o Control que admita contenido que no sea de texto.
Este ejemplo forma parte de un ejemplo más grande; para obtener el ejemplo completo, vea ejemplo de elementos
de forma.
Cómo: Dibujar una elipse o un círculo
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo dibujar elipses y círculos mediante el elemento Ellipse. Para dibujar una elipse,
cree un elemento Ellipse y especifique su Width y Height. Utilice su propiedad Fill para especificar el Brush que se
utiliza para pintar el interior de la elipse. Utilice su propiedad Stroke para especificar el Brush que se usa para
pintar el contorno de la elipse. La propiedad StrokeThickness especifica el grosor del contorno de la elipse.
Para dibujar un círculo, convierta el Width y Height del elemento Ellipse igual entre sí.
En el ejemplo siguiente se dibujan cuatro elementos Ellipse dentro de un Canvas.

Ejemplo
<Canvas Height="200" Width="200">

<!-- Draws an oval with a blue interior. -->


<Ellipse
Width="100"
Height="50"
Fill="Blue"
Canvas.Left="10"
Canvas.Top="25" />

<!-- Draws an oval with a blue interior and a black outline. -->
<Ellipse
Width="100"
Height="50"
Fill="Blue"
Stroke="Black"
StrokeThickness="4"
Canvas.Left="10"
Canvas.Top="100"/>

<!-- Draws a circle with a blue interior. -->


<Ellipse
Width="50"
Height="50"
Fill="Blue"
Canvas.Left="135"
Canvas.Top="25"/>

<!-- Draws a circle with a blue interior and a black outline. -->
<Ellipse
Width="50"
Height="50"
Stroke="Black"
StrokeThickness="4"
Canvas.Left="135"
Canvas.Top="100" />

</Canvas>

Aunque en este ejemplo se usa una Canvas para contener los puntos suspensivos, se pueden usar elementos
Ellipse (y todos los demás elementos Shape) con cualquier Panel o Control que admita contenido que no sea de
texto.
Este ejemplo forma parte de un ejemplo más grande; para obtener el ejemplo completo, vea ejemplo de elementos
de forma.

Consulte también
Ellipse
Shape
Ejemplo de elementos de forma
Cómo: Dibujar una línea
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo dibujar líneas mediante el elemento Line.


Para dibujar una línea, cree un elemento Line. Use sus propiedades X1 y Y1 para establecer su punto inicial; y usan
sus propiedades X2 y Y2 para establecer su punto final. Por último, establezca su Stroke y StrokeThickness porque
una línea sin trazo es invisible.
Establecer el elemento Fill para una línea no tiene ningún efecto, ya que una línea no tiene ningún interior.
En el ejemplo siguiente se dibujan tres líneas dentro de un elemento Canvas.

Ejemplo
<Canvas Height="300" Width="300">

<!-- Draws a diagonal line from (10,10) to (50,50). -->


<Line
X1="10" Y1="10"
X2="50" Y2="50"
Stroke="Black"
StrokeThickness="4" />

<!-- Draws a diagonal line from (10,10) to (50,50)


and moves it 100 pixels to the right. -->
<Line
X1="10" Y1="10"
X2="50" Y2="50"
StrokeThickness="4"
Canvas.Left="100">
<Line.Stroke>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="Red" Offset="0" />
<GradientStop Color="Blue" Offset="0.25" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Line.Stroke>
</Line>

<!-- Draws a horizontal line from (10,60) to (150,60). -->


<Line
X1="10" Y1="60"
X2="150" Y2="60"
Stroke="Black"
StrokeThickness="4"/>

</Canvas>

Este ejemplo forma parte de un ejemplo más grande; para obtener el ejemplo completo, vea ejemplo de elementos
de forma.

Consulte también
Line
Ejemplo de elementos de forma
Cómo: Dibujar una polilínea mediante el uso del
elemento Polyline
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo dibujar una polilínea, que es una serie de líneas conectadas, mediante el
elemento Polyline.
Para dibujar una polilínea, cree un elemento Polyline y utilice su propiedad Points para especificar los vértices de la
forma. Por último, use las propiedades Stroke y StrokeThickness para describir el contorno de la polilínea porque
una línea sin trazo es invisible.

NOTE
Dado que el elemento Polyline no es una forma cerrada, la propiedad Fill no tiene ningún efecto, aunque cierre
deliberadamente el contorno de la forma. Para crear una forma cerrada con un Fill, use un elemento Polygon.

En el ejemplo siguiente se dibujan dos elementos Polyline dentro de un Canvas.

Ejemplo
En Lenguaje XAML (Extensible Application Markup Language), la sintaxis válida para los puntos es una lista
delimitada por espacios de pares de coordenadas x e y separadas por comas.

<Canvas Height="400" Width="400">

<Polyline
Points="10,110 60,10 110,110"
Stroke="Black"
StrokeThickness="4" />

<Polyline
Points="10,110 110,110 110,10"
Stroke="Black"
StrokeThickness="4"
Canvas.Left="150" />

</Canvas>

Aunque en este ejemplo se usa una Canvas para contener las polilíneas, puede utilizar elementos Polyline (y todos
los demás elementos Shape) con cualquier Panel o Control que admita contenido que no sea de texto.
Este ejemplo forma parte de un ejemplo más grande; para obtener el ejemplo completo, vea ejemplo de elementos
de forma.

Consulte también
Polyline
Polygon
Shape
Ejemplo de elementos de forma
Información general sobre formas y dibujo básico en WPF
Cómo: Dibujar un rectángulo
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo dibujar un rectángulo mediante el elemento Rectangle.


Para dibujar un rectángulo, cree un elemento Rectangle y especifique su Width y Height. Para pintar el interior del
rectángulo, establezca su Fill. Para asignar un contorno al rectángulo, use sus propiedades Stroke y
StrokeThickness.
Para dar al rectángulo esquinas redondeadas, especifique las propiedades RadiusX y RadiusY opcionales. Las
propiedades RadiusX y RadiusY establecen los radios de los ejes x e y de la elipse que se usa para redondear los
vértices del rectángulo.
En el ejemplo siguiente, se dibujan dos elementos Rectangle en una Canvas. El primer rectángulo tiene un Blue
interior. El segundo rectángulo tiene un Blue interior, un esquema Black y esquinas redondeadas.

Ejemplo
<Canvas Width="120" Height="200" >

<!-- Draws a 100 by 50 rectangle with a solid blue fill. -->


<Rectangle
Width="100"
Height="50"
Fill="Blue"
Canvas.Left="10"
Canvas.Top="25" />

<!-- Draws a 100 by 50 rectangle with a solid blue fill,


a black outline, and rounded corners. -->
<Rectangle
Width="100"
Height="50"
Fill="Blue"
Stroke="Black" StrokeThickness="4"
RadiusX="20" RadiusY="20"
Canvas.Left="10"
Canvas.Top="100"/>

</Canvas>

Aunque en este ejemplo se usa un Canvas para contener los rectángulos, puede utilizar elementos de rectángulo (y
todos los demás elementos de forma) con cualquier Panel o Control que admita contenido que no sea de texto. De
hecho, los rectángulos son especialmente útiles para proporcionar el fondo para partes de los paneles de Grid.
Para obtener un ejemplo, vea la información generalde la tabla.
Este ejemplo forma parte de un ejemplo más grande; para obtener el ejemplo completo, vea ejemplo de elementos
de forma.

Consulte también
Rectangle
Ejemplo de elementos de forma
Información general sobre formas y dibujo básico en WPF
Información general sobre las tablas
Cómo: Modificar el extremo en el final de una línea o
segmento
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo modificar la forma al principio o al final de un elemento de Shape abierto. Para
cambiar el extremo al principio de un Shapeabierto, utilice su propiedad StrokeStartLineCap. Para cambiar el
extremo al final de un Shapeabierto, utilice su propiedad StrokeEndLineCap. Para ver los límites de línea
disponibles, consulte la enumeración PenLineCap.

NOTE
Esta propiedad solo afecta a una forma abierta, como un Line, un Polylineo un elemento Path abierto.

En el ejemplo siguiente se dibujan cuatro elementos Polyline y se utiliza un conjunto diferente de formas en los
extremos de cada uno de ellos.

Ejemplo
<TextBlock Grid.Column="3" Grid.Row="0" Grid.ColumnSpan="2">
<Bold>Line Caps</Bold>
</TextBlock>
<TextBlock Grid.Column="3" Grid.Row="1">Flat</TextBlock>
<Polyline
Points="50,50 75,30 100,100 130,40"
Stroke="Red"
StrokeThickness="20"
StrokeStartLineCap="Flat"
StrokeEndLineCap="Flat"
Grid.Row="1" Grid.Column="4"/>

<TextBlock Grid.Column="3" Grid.Row="2">Square</TextBlock>


<Polyline
Points="50,50 75,30 100,100 130,40"
Stroke="Red"
StrokeThickness="20"
StrokeStartLineCap="Square"
StrokeEndLineCap="Square"
Grid.Row="2" Grid.Column="4"/>

<TextBlock Grid.Column="3" Grid.Row="3">Round</TextBlock>


<Polyline
Points="50,50 75,30 100,100 130,40"
Stroke="Red"
StrokeThickness="20"
StrokeStartLineCap="Round"
StrokeEndLineCap="Round"
Grid.Row="3" Grid.Column="4"/>

<TextBlock Grid.Column="3" Grid.Row="4">Triangle</TextBlock>


<Polyline
Points="50,50 75,30 100,100 130,40"
Stroke="Red"
StrokeThickness="20"
StrokeStartLineCap="Triangle"
StrokeEndLineCap="Triangle"
Grid.Row="4" Grid.Column="4"/>

Este ejemplo forma parte de un ejemplo más grande; para obtener el ejemplo completo, vea ejemplo de elementos
de forma.

Consulte también
Polyline
PenLineCap
Transformaciones
23/10/2019 • 2 minutes to read • Edit Online

Las transformaciones se usan para girar, escalar, traducir o sesgar FrameworkElement objetos.

En esta sección
Información general sobre transformaciones
Temas "Cómo..."

Vea también
Transform
Gráficos y multimedia
Información general sobre la representación de gráficos en WPF
Diseño
Información general sobre transformaciones
04/11/2019 • 13 minutes to read • Edit Online

En este tema se describe cómo utilizar las clases de Transform 2D para girar, escalar, desplazar (trasladar) y
sesgar objetos de FrameworkElement.

¿Qué es una transformación?


Un Transform define cómo asignar, o transformar, puntos de un espacio de coordenadas a otro espacio de
coordenadas. Esta asignación se describe mediante una transformación Matrix, que es una colección de tres
filas con tres columnas de valores Double.

NOTE
Windows Presentation Foundation (WPF) usa matrices de filas principales. Los vectores se expresan como vectores de fila,
no como vectores de columna.

En la tabla siguiente se muestra la estructura de una matriz de WPF.


Matriz de transformación 2D

M11 M12 0.0

Valor predeterminado: 1.0 Valor predeterminado: 0.0

M21 M22 0.0

Valor predeterminado: 0.0 Valor predeterminado: 1.0

OffsetX OffsetY 1.0

Valor predeterminado: 0.0 Valor predeterminado: 0.0

Manipulando los valores de la matriz, puede girar, escalar, sesgar y mover (trasladar) un objeto.Por ejemplo, si
cambia el valor de la primera columna de la tercera fila (el valor OffsetX) a 100, puede utilizarlo para desplace
un objeto 100 unidades a lo largo del eje x. Si cambia a 3 el valor de la segunda columna de la segunda fila,
puede usarlo para triplicar el alto actual de un objeto. Si cambia ambos valores, mueve el objeto 100 unidades a
lo largo del eje X y ajusta su alto a un factor de 3. Dado que Windows Presentation Foundation (WPF ) solo
admite transformaciones afines, los valores de la columna derecha siempre son 0, 0, 1.
Aunque Windows Presentation Foundation (WPF ) permite manipular directamente los valores de la matriz,
también proporciona varias clases Transform que permiten transformar un objeto sin saber cómo se configura
la estructura de la matriz subyacente. Por ejemplo, la clase ScaleTransform permite escalar un objeto
estableciendo sus propiedades ScaleX y ScaleY, en lugar de manipular una matriz de transformación. Del
mismo modo, la clase RotateTransform permite girar un objeto simplemente estableciendo su propiedad Angle.

Clases Transform
Windows Presentation Foundation (WPF ) proporciona las siguientes clases de Transform 2D para operaciones
de transformación comunes:
CLASE DESCRIPCIÓN EJEMPLO ILUSTRACIÓN

RotateTransform Gira un elemento por el Girar un objeto


Angleespecificado.

ScaleTransform Escala un elemento según Ajustar la escala de un


las cantidades de ScaleX y elemento
ScaleY especificadas.

SkewTransform Sesga un elemento según Sesgar un elemento


las cantidades de AngleX y
AngleY especificadas.

TranslateTransform Mueve (traduce) un Trasladar un elemento


elemento según las
cantidades de X y Y
especificadas.

Para crear transformaciones más complejas, Windows Presentation Foundation (WPF ) proporciona las dos
clases siguientes:

CLASE DESCRIPCIÓN EJEMPLO

TransformGroup Agrupa varios objetos de Aplicar varias transformaciones a un


TransformGroup en un solo Transform objeto
que se pueden aplicar a las
propiedades de transformación.

MatrixTransform Crea transformaciones personalizadas Utilizar un objeto MatrixTransform


que no proporcionan otras clases para crear transformaciones
Transform. Cuando se usa un personalizadas
MatrixTransform, se manipula
directamente una matriz.

Windows Presentation Foundation (WPF ) también proporciona transformaciones 3D. Para obtener más
información, vea la clase Transform3D.

Propiedades de transformación comunes


Una manera de transformar un objeto es declarar el tipo de Transform adecuado y aplicarlo a la propiedad de
transformación del objeto. Los diferentes tipos de objetos tienen distintos tipos de propiedades de
transformación. En la tabla siguiente se enumeran varios tipos de Windows Presentation Foundation (WPF )
usados comúnmente y sus propiedades de transformación.

TYPE PROPIEDADES DE TRANSFORMACIÓN

Brush Transform, RelativeTransform

ContainerVisual Transform

DrawingGroup Transform

FrameworkElement RenderTransform, LayoutTransform

Geometry Transform

TextEffect Transform

UIElement RenderTransform

Transformaciones y sistemas de coordenadas


Al transformar un objeto, no solo transforma el objeto, se transformar el espacio de coordenadas en el que se
encuentra. De forma predeterminada, una transformación tiene su centro en el origen del sistema de
coordenadas del objeto de destino: (0,0). La única excepción es TranslateTransform; un TranslateTransform no
tiene propiedades de centro para establecer porque el efecto de traslación es el mismo independientemente de
dónde se Centre.
En el ejemplo siguiente se usa un RotateTransform para girar un elemento Rectangle, un tipo de
FrameworkElement, de 45 grados sobre su centro predeterminado, (0,0). En la ilustración siguiente se muestra
el efecto de la rotación.

Elemento Rectangle girado 45 grados alrededor del punto (0,0)

<Canvas Width="200" Height="200">


<Rectangle
Canvas.Left="100" Canvas.Top="100"
Width="50" Height="50"
Fill="RoyalBlue" Opacity="1.0">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
De forma predeterminada, el elemento gira sobre su esquina superior izquierda, (0, 0). Las clases
RotateTransform, ScaleTransformy SkewTransform proporcionan propiedades CenterX y CenterY que permiten
especificar el punto en el que se aplica la transformación.
En el ejemplo siguiente también se usa un RotateTransform para girar un elemento Rectangle en 45 grados; sin
embargo, esta vez se establecen las propiedades CenterX y CenterY para que el RotateTransform tenga un
centro de (25, 25). En la ilustración siguiente se muestra el efecto de la rotación.

Elemento Rectangle girado 45 grados alrededor del punto (25, 25)

<Canvas Width="200" Height="200">


<Rectangle
Canvas.Left="100" Canvas.Top="100"
Width="50" Height="50"
Fill="RoyalBlue" Opacity="1.0">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" CenterX="25" CenterY="25" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>

Transformación de un elemento FrameworkElement


Para aplicar transformaciones a un FrameworkElement, cree un Transform y aplíquelo a una de las dos
propiedades que proporciona la clase FrameworkElement:
LayoutTransform: una transformación que se aplica antes de la fase de diseño. Después de aplicar la
transformación, el sistema de diseño procesa el tamaño y la posición transformados del elemento.
RenderTransform: una transformación que modifica la apariencia del elemento, pero se aplica una vez
completado el paso de diseño. Mediante el uso de la propiedad RenderTransform en lugar de la
propiedad LayoutTransform, puede obtener ventajas de rendimiento.
¿Qué propiedad debe usar? Debido a las ventajas de rendimiento que proporciona, utilice la propiedad
RenderTransform siempre que sea posible, especialmente cuando se utilizan objetos de Transform animados.
Use la propiedad LayoutTransform cuando escale, gire o sesgo y necesite el elemento primario del elemento
para ajustarse al tamaño transformado del elemento. Tenga en cuenta que, cuando se usan con la propiedad
LayoutTransform, los objetos TranslateTransform parecen no tener ningún efecto en los elementos. Esto se debe
a que el sistema de diseño devuelve el elemento trasladado a su posición original como parte de su
procesamiento.
Para obtener información adicional acerca del diseño en Windows Presentation Foundation (WPF ), consulte la
información general sobre diseño.

Ejemplo: Girar un elemento FrameworkElement 45 grados


En el ejemplo siguiente se usa un RotateTransform para girar un botón en el sentido de las agujas del reloj por
45 grados. El botón está contenido en un StackPanel que tiene otros dos botones.
De forma predeterminada, un RotateTransform gira sobre el punto (0,0). Puesto que el ejemplo no especifica un
centro, el botón gira sobre el punto (0, 0), que está en la esquina superior izquierda. El RotateTransform se
aplica a la propiedad RenderTransform. En la ilustración siguiente se muestra el resultado de la transformación.

Rotación de 45 grados en el sentido de las agujas del reloj desde la esquina superior izquierda

<Border Margin="30"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="1" >
<StackPanel Orientation="Vertical">
<Button Content="A Button" Opacity="1" />
<Button Content="Rotated Button">
<Button.RenderTransform>
<RotateTransform Angle="45" />
</Button.RenderTransform>
</Button>
<Button Content="A Button" Opacity="1" />
</StackPanel>
</Border>

En el ejemplo siguiente también se usa un RotateTransform para girar un botón 45 grados en el sentido de las
agujas del reloj, pero también se establece el RenderTransformOrigin del botón en (0,5, 0,5). El valor de la
propiedad RenderTransformOrigin es relativo al tamaño del botón. Como resultado, la rotación se aplica al
centro del botón en lugar de a la esquina superior izquierda. En la ilustración siguiente se muestra el resultado
de la transformación.

Rotación de 45 grados en el sentido de las agujas del reloj alrededor del centro

<Border Margin="30"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical">
<Button Content="A Button" Opacity="1" />
<Button Content="Rotated Button"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<RotateTransform Angle="45" />
</Button.RenderTransform>
</Button>
<Button Content="A Button" Opacity="1" />
</StackPanel>
</Border>

En el ejemplo siguiente se usa la propiedad LayoutTransform en lugar de la propiedad RenderTransform para


girar el botón. Esto hace que la transformación afecte al diseño del botón, lo que desencadena un recorrido
completo del sistema de diseño. Como resultado, el botón se gira y se vuelve a cambiar de posición porque su
tamaño ha cambiado. En la ilustración siguiente se muestra el resultado de la transformación.
Propiedad LayoutTransform utilizada para girar el botón

<Border Margin="30"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical">

<Button Content="A Button" Opacity="1" />


<Button Content="Rotated Button">
<Button.LayoutTransform>
<RotateTransform Angle="45" />
</Button.LayoutTransform>
</Button>
<Button Content="A Button" Opacity="1" />
</StackPanel>
</Border>

Animación de transformaciones
Dado que heredan de la clase Animatable, las clases de Transform se pueden animar. Para animar un Transform,
aplique una animación de un tipo compatible a la propiedad que desee animar.
En el ejemplo siguiente se usa un Storyboard y un DoubleAnimation con un RotateTransform para hacer que
un Button gire en su lugar cuando se hace clic en él.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Button Animated RotateTransform Example"
Background="White" Margin="50">
<StackPanel>

<Button Content="A Button"


RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="AnimatedRotateTransform"
Storyboard.TargetProperty="Angle"
To="360" Duration="0:0:1" FillBehavior="Stop" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

</StackPanel>
</Page>
Para ver el ejemplo completo, consulte Ejemplo de transformaciones 2D. Para más información sobre
animaciones, vea Información general sobre animaciones.

Características de los objetos Freezable


Dado que hereda de la clase Freezable, la clase Transform proporciona varias características especiales: los
objetos Transform se pueden declarar como recursos, compartirse entre varios objetos, convertirse en de solo
lectura para mejorar el rendimiento, clonarse y hacerse seguro para subprocesos. Para obtener más
información sobre las distintas características proporcionadas por Freezable objetos, vea la información general
sobre objetos Freezable.

Vea también
Transform
Matrix
Temas "Cómo..."
Ejemplo de transformaciones 2D
Temas "Cómo..." de transformaciones
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección describen cómo aplicar distintas transformaciones a los objetos.

En esta sección
Aplicar una transformación a un elemento cuando se provoca un evento
Aplicar varias transformaciones a un objeto
Hacer que un elemento gire en su posición
Girar un objeto
Ajustar la escala de un elemento
Sesgar un elemento
Especificar el origen de una transformación utilizando valores relativos
Trasladar un elemento
Utilizar un objeto MatrixTransform para crear transformaciones personalizadas

Vea también
Transform
Gráficos y multimedia
Información general sobre la representación de gráficos en WPF
Diseño
Procedimiento Aplicar una transformación a un
elemento cuando se produce un evento
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo aplicar un ScaleTransform cuando se produce un evento. El concepto que se
muestra aquí es el mismo que se utiliza para aplicar otros tipos de transformaciones. Para obtener más
información acerca de los tipos de transformaciones disponibles, consulte el Transform clase o información general
sobre transformaciones.
Puede aplicar una transformación a un elemento de cualquiera de estas dos maneras:
Si lo hace no desea que la transformación afecte al diseño, utilice el RenderTransform propiedad del
elemento.
Si desea que la transformación afecte al diseño, utilice el LayoutTransform propiedad del elemento.
El ejemplo siguiente aplica un ScaleTransform a la RenderTransform propiedad de un botón. Cuando se mueve el
mouse sobre el botón, el ScaleX y ScaleY propiedades de la ScaleTransform se establecen en 2 , lo que hace que el
botón se agrande. Cuando el mouse se aleja del botón, ScaleX y ScaleY se establecen en 1 , lo que hace que el
botón para volver a su tamaño original.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WCSample.TransformExample"
WindowTitle="Transform on Mouse Enter Example">
<Canvas Width="400" Height="400">

<Button Name="Button1" MouseEnter="Enter" MouseLeave="Leave">


<Button.RenderTransform>
<ScaleTransform x:Name="myScaleTransform" ScaleX="1" ScaleY="1" />
</Button.RenderTransform>
Button
</Button>

</Canvas>
</Page>

public partial class TransformExample : Page {


private void Enter(object sender, MouseEventArgs args) {
myScaleTransform.ScaleX = 2;
myScaleTransform.ScaleY = 2;
}

private void Leave(object sender, MouseEventArgs args) {


myScaleTransform.ScaleX = 1;
myScaleTransform.ScaleY = 1;
}
}
Partial Public Class TransformExample
Inherits Page
Private Sub Enter(ByVal sender As Object, ByVal args As System.Windows.Input.MouseEventArgs)
myScaleTransform.ScaleX = 2
myScaleTransform.ScaleY = 2
End Sub

Private Sub Leave(ByVal sender As Object, ByVal e As System.Windows.Input.MouseEventArgs)


myScaleTransform.ScaleX = 1
myScaleTransform.ScaleY = 1
End Sub
End Class

Vea también
Transform
ScaleTransform
Información general sobre transformaciones
Temas "Cómo..."
Información general sobre eventos enrutados
Cómo: Aplicar varias transformaciones a un objeto
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un TransformGroup para agrupar dos o más objetos de Transform en un
solo Transformcompuesto.

Ejemplo
En el ejemplo siguiente se usa un TransformGroup para aplicar un ScaleTransform y un RotateTransform a un
Button.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel Margin="50">

<Button
RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="Center">Click
<Button.RenderTransform>

<!-- TransformGroup enables you to apply multiple transforms. In


this example, the button is scaled and rotated. -->
<TransformGroup>

<!-- Triple the size (scale) of the button in the Y direction. -->
<ScaleTransform ScaleY="3" />

<!-- Rotate the button by 45 degrees. -->


<RotateTransform Angle="45" />

</TransformGroup>
</Button.RenderTransform>
</Button>

</StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace SDKSample
{
public partial class MultipleTransformsExample : Page
{
public MultipleTransformsExample()
{
// Create a Button that will have two transforms applied to it.
Button myButton = new Button();
myButton.Content = "Click";

// Set the center point of the transforms.


myButton.RenderTransformOrigin = new Point(0.5,0.5);

// Create a transform to scale the size of the button.


ScaleTransform myScaleTransform = new ScaleTransform();

// Set the transform to triple the scale in the Y direction.


myScaleTransform.ScaleY = 3;

// Create a transform to rotate the button


RotateTransform myRotateTransform = new RotateTransform();

// Set the rotation of the transform to 45 degrees.


myRotateTransform.Angle = 45;

// Create a TransformGroup to contain the transforms


// and add the transforms to it.
TransformGroup myTransformGroup = new TransformGroup();
myTransformGroup.Children.Add(myScaleTransform);
myTransformGroup.Children.Add(myRotateTransform);

// Associate the transforms to the button.


myButton.RenderTransform = myTransformGroup;

// Create a StackPanel which will contain the Button.


StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(50);
myStackPanel.Children.Add(myButton);
this.Content = myStackPanel;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media

Namespace SDKSample
Partial Public Class MultipleTransformsExample
Inherits Page
Public Sub New()
' Create a Button that will have two transforms applied to it.
Dim myButton As New Button()
myButton.Content = "Click"

' Set the center point of the transforms.


myButton.RenderTransformOrigin = New Point(0.5,0.5)

' Create a transform to scale the size of the button.


Dim myScaleTransform As New ScaleTransform()

' Set the transform to triple the scale in the Y direction.


myScaleTransform.ScaleY = 3

' Create a transform to rotate the button


Dim myRotateTransform As New RotateTransform()

' Set the rotation of the transform to 45 degrees.


myRotateTransform.Angle = 45

' Create a TransformGroup to contain the transforms


' and add the transforms to it.
Dim myTransformGroup As New TransformGroup()
myTransformGroup.Children.Add(myScaleTransform)
myTransformGroup.Children.Add(myRotateTransform)

' Associate the transforms to the button.


myButton.RenderTransform = myTransformGroup

' Create a StackPanel which will contain the Button.


Dim myStackPanel As New StackPanel()
myStackPanel.Margin = New Thickness(50)
myStackPanel.Children.Add(myButton)
Me.Content = myStackPanel

End Sub
End Class
End Namespace

Consulte también
RenderTransform
TransformGroup
Información general sobre transformaciones
Ejemplo de transformaciones 2D
Cómo: Hacer que un elemento gire en su posición
20/02/2020 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo hacer que un elemento gire mediante un RotateTransform y un
DoubleAnimation.
En el ejemplo siguiente se aplica el RotateTransform a la propiedad RenderTransform del elemento. En el ejemplo
se usa un DoubleAnimation para animar el Angle de la RotateTransform. Para hacer que el elemento gire en su
lugar, en el ejemplo se establece la propiedad RenderTransformOrigin del elemento en el punto (0,5, 0,5).

Ejemplo
<!-- RotateAboutCenterExample.xaml
This example shows how to make an element spin
about its center. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.Animation.RotateAboutCenterExample"
WindowTitle="Rotate About Center Example">
<StackPanel Margin="50">

<Button
RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="Left">
Hello,World
<Button.RenderTransform>
<RotateTransform x:Name="MyAnimatedTransform" Angle="0" />
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyAnimatedTransform"
Storyboard.TargetProperty="(RotateTransform.Angle)"
From="0.0" To="360" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>

Para obtener el ejemplo completo, que incluye más ejemplos de transformación, vea ejemplo de transformaciones
2D.

Consulte también
Información general sobre animaciones
Información general sobre transformaciones
Procedimiento Girar un objeto
23/10/2019 • 3 minutes to read • Edit Online

Este ejemplo muestra cómo girar un objeto. El ejemplo crea primero un RotateTransform y, a continuación,
especifica su Angle en grados.
En el ejemplo siguiente se gira un Polyline objeto 45 grados sobre su esquina superior izquierda.

Ejemplo
<Canvas Height="200" Width="200">

<!-- Rotates the Polyline 45 degrees about the point (0,0). -->
<Polyline Points="25,25 0,50 25,75 50,50 25,25 25,0"
Stroke="Blue" StrokeThickness="10"
Canvas.Left="75" Canvas.Top="50">
<Polyline.RenderTransform>
<RotateTransform CenterX="0" CenterY="0" Angle="45" />
</Polyline.RenderTransform>
</Polyline>
</Canvas>

// Create a Polyline.
Polyline polyline1 = new Polyline();
polyline1.Points.Add(new Point(25, 25));
polyline1.Points.Add(new Point(0, 50));
polyline1.Points.Add(new Point(25, 75));
polyline1.Points.Add(new Point(50, 50));
polyline1.Points.Add(new Point(25, 25));
polyline1.Points.Add(new Point(25, 0));
polyline1.Stroke = Brushes.Blue;
polyline1.StrokeThickness = 10;

// Create a RotateTransform to rotate


// the Polyline 45 degrees about its
// top-left corner.
RotateTransform rotateTransform1 =
new RotateTransform(45);
polyline1.RenderTransform = rotateTransform1;

// Create a Canvas to contain the Polyline.


Canvas canvas1 = new Canvas();
canvas1.Width = 200;
canvas1.Height = 200;
Canvas.SetLeft(polyline1, 75);
Canvas.SetTop(polyline1, 50);
canvas1.Children.Add(polyline1);
' Create a Polyline.
Dim polyline1 As New Polyline()
polyline1.Points.Add(New Point(25, 25))
polyline1.Points.Add(New Point(0, 50))
polyline1.Points.Add(New Point(25, 75))
polyline1.Points.Add(New Point(50, 50))
polyline1.Points.Add(New Point(25, 25))
polyline1.Points.Add(New Point(25, 0))
polyline1.Stroke = Brushes.Blue
polyline1.StrokeThickness = 10

' Create a RotateTransform to rotate


' the Polyline 45 degrees about its
' top-left corner.
Dim rotateTransform1 As New RotateTransform(45)
polyline1.RenderTransform = rotateTransform1

' Create a Canvas to contain the Polyline.


Dim canvas1 As New Canvas()
canvas1.Width = 200
canvas1.Height = 200
Canvas.SetLeft(polyline1, 75)
Canvas.SetTop(polyline1, 50)
canvas1.Children.Add(polyline1)

El CenterX y CenterY propiedades de la RotateTransform especificar el punto sobre el que se gira el objeto. Este
punto central se expresa en el espacio de coordenadas del elemento que se transforma. De forma predeterminada,
la rotación se aplica a (0,0), que es la esquina superior izquierda del objeto que transformar.
El siguiente ejemplo se gira un Polyline objeto hacia la derecha 45 grados sobre el punto (25,50).

<Canvas Height="200" Width="200">

<!-- Rotates the Polyline 45 degrees about the point (25,50). -->
<Polyline Points="25,25 0,50 25,75 50,50 25,25 25,0"
Stroke="Blue" StrokeThickness="10"
Canvas.Left="75" Canvas.Top="50">
<Polyline.RenderTransform>
<RotateTransform CenterX="25" CenterY="50" Angle="45" />
</Polyline.RenderTransform>
</Polyline>
</Canvas>
// Create a Polyline.
Polyline polyline2 = new Polyline();
polyline2.Points = polyline1.Points;
polyline2.Stroke = Brushes.Blue;
polyline2.StrokeThickness = 10;

// Create a RotateTransform to rotate


// the Polyline 45 degrees about the
// point (25,50).
RotateTransform rotateTransform2 =
new RotateTransform(45);
rotateTransform2.CenterX = 25;
rotateTransform2.CenterY = 50;
polyline2.RenderTransform = rotateTransform2;

// Create a Canvas to contain the Polyline.


Canvas canvas2 = new Canvas();
canvas2.Width = 200;
canvas2.Height = 200;
Canvas.SetLeft(polyline2, 75);
Canvas.SetTop(polyline2, 50);
canvas2.Children.Add(polyline2);

' Create a Polyline.


Dim polyline2 As New Polyline()
polyline2.Points = polyline1.Points
polyline2.Stroke = Brushes.Blue
polyline2.StrokeThickness = 10

' Create a RotateTransform to rotate


' the Polyline 45 degrees about the
' point (25,50).
Dim rotateTransform2 As New RotateTransform(45)
rotateTransform2.CenterX = 25
rotateTransform2.CenterY = 50
polyline2.RenderTransform = rotateTransform2

' Create a Canvas to contain the Polyline.


Dim canvas2 As New Canvas()
canvas2.Width = 200
canvas2.Height = 200
Canvas.SetLeft(polyline2, 75)
Canvas.SetTop(polyline2, 50)
canvas2.Children.Add(polyline2)

La siguiente ilustración muestra el resultado de aplicar un Transform a los dos objetos.

Dos objetos que se giran 45 grados desde distintos centros de giro


El Polyline en los ejemplos anteriores es un UIElement. Al aplicar un Transform a la RenderTransform propiedad
de un UIElement, puede usar el RenderTransformOrigin propiedad para especificar un origen para cada Transform
que se aplican al elemento. Dado que el RenderTransformOrigin propiedad usa coordenadas relativas, puede
aplicar una transformación al centro del elemento incluso si no conoce su tamaño. Para obtener más información y
para obtener un ejemplo, vea especificar el origen de una transformación utilizando valores relativos.
Para ver el ejemplo completo, consulte Ejemplo de transformaciones 2D.

Vea también
Transform
Información general sobre transformaciones
Temas "Cómo..."
Procedimiento Ajustar la escala de un elemento
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un ScaleTransform para escalar un elemento.


Use la ScaleX y ScaleY propiedades para cambiar el tamaño del elemento por el factor que especifique. Por
ejemplo, un ScaleX valor de 1,5 ajusta el elemento al 150 por ciento de su ancho original. Un ScaleY valor de 0,5
reduce el alto de un elemento en un 50%.
Use la CenterX y CenterY propiedades para especificar el punto que es el centro de la operación de escalado. De
forma predeterminada, un ScaleTransform se centra en el punto (0,0), que corresponde a la esquina superior
izquierda del rectángulo. Esto tiene el efecto de mover el elemento y también de que parezca más grande, ya que
al aplicar un Transform, cambie el espacio de coordenadas en el que reside el objeto.
En el ejemplo siguiente se usa un ScaleTransform duplicar el tamaño de un 50 por 50 Rectangle. El
ScaleTransform tiene un valor de 0 (valor predeterminado) para ambos CenterX y CenterY.

Ejemplo
<!-- Scales a rectangle by 200% from a center of (0,0).-->
<Rectangle Height="50" Width="50" Fill="#CCCCCCFF"
Stroke="Blue" StrokeThickness="2"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<ScaleTransform CenterX="0" CenterY="0" ScaleX="2" ScaleY="2" />
</Rectangle.RenderTransform>
</Rectangle>

Normalmente, se establece CenterX y CenterY al centro del objeto que se escala: (Width/2, Height /2).
El ejemplo siguiente muestra otro Rectangle que tiene el doble de tamaño; sin embargo, esto ScaleTransform tiene
un valor de 25 para ambos CenterX y CenterY, que se corresponde con el centro del rectángulo.

<!-- Scales a rectangle by 200% from a center of (25,25).-->


<Rectangle Height="50" Width="50" Fill="#CCCCCCFF"
Canvas.Left="100" Canvas.Top="100" Stroke="Blue" StrokeThickness="2">
<Rectangle.RenderTransform>
<ScaleTransform CenterX="25" CenterY="25" ScaleX="2" ScaleY="2" />
</Rectangle.RenderTransform>
</Rectangle>

La siguiente ilustración muestra la diferencia entre los dos ScaleTransform operaciones. La línea de puntos
muestra el tamaño y la posición del rectángulo antes de escalar.
Dos operaciones de ScaleTransform con valores idénticos de ScaleX y ScaleY pero con centros diferentes
Para ver el ejemplo completo, consulte Ejemplo de transformaciones 2D.

Vea también
Transform
ScaleTransform
Información general sobre transformaciones
Temas "Cómo..."
Procedimiento Sesgar un elemento
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un SkewTransform para sesgar un elemento. Un sesgo, también conocido
como distorsión, es una transformación que expande el espacio de coordenadas de una manera no uniforme. Un
uso típico de un SkewTransform para simular una profundidad 3D en objetos 2D.
Use la CenterX y CenterY propiedades para especificar el centro de punto de la SkewTransform.
Use la AngleX y AngleY propiedades para especificar el ángulo de sesgado de los ejes x y y y para sesgar el
sistema de coordenadas actual a lo largo de estos ejes.
Para predecir el efecto de una transformación de sesgo, considere la posibilidad de que AngleX sesga los valores
del eje x en relación con el sistema de coordenadas original. Por lo tanto, para un AngleX de 30, el eje y gira 30
grados a través del origen y sesga los valores de x-30 grados desde ese origen. Del mismo modo, un AngleY de 30
sesga los valores y de la forma 30 grados desde el origen. Tenga en cuenta que esto no tiene el mismo efecto que
trasladar (mover) el sistema de coordenadas 30 grados en x o y.
El ejemplo siguiente aplica un sesgo horizontal de 45 grados a un Rectangle desde un punto central de (0,0).

Ejemplo
<Rectangle
Height="50" Width="50" Fill="#CCCCCCFF"
Stroke="Blue" StrokeThickness="2"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>

<!-- Applies a horizontal skew of 45 degrees


from a center point of (0,0). -->
<SkewTransform CenterX="0" CenterY="0" AngleX="45" AngleY="0" />
</Rectangle.RenderTransform>
</Rectangle>

El ejemplo siguiente aplica un sesgo horizontal de 45 grados a un Rectangle desde un punto central de (25,25).

<Rectangle Height="50" Width="50" Fill="#CCCCCCFF"


Canvas.Left="100" Canvas.Top="100"
Stroke="Blue" StrokeThickness="2">
<Rectangle.RenderTransform>

<!-- Applies a horizontal skew of 45 degrees


from a center point of (25,25). -->
<SkewTransform CenterX="25" CenterY="25" AngleX="45" AngleY="0" />
</Rectangle.RenderTransform>
</Rectangle>

El ejemplo siguiente aplica un sesgo vertical de 45 grados a un Rectangle desde un punto central de (25,25).
<Rectangle Height="50" Width="50" Fill="#CCCCCCFF"
Stroke="Blue" StrokeThickness="2"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>

<!-- Applies a vertical skew of 45 degrees


from a center point of (25,25). -->
<SkewTransform CenterX="25" CenterY="25" AngleX="0" AngleY="45" />
</Rectangle.RenderTransform>
</Rectangle>

La ilustración siguiente muestra los diferentes sesgos que se usan en este ejemplo.

Los tres ejemplos de SkewTransform ilustrados


Para ver el ejemplo completo, consulte Ejemplo de transformaciones 2D.

Vea también
Transform
SkewTransform
Información general sobre transformaciones
Temas "Cómo..."
Procedimiento Especificar el origen de una
transformación mediante valores relativos
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo utilizar valores relativos para especificar el origen de un RenderTransform que
se aplica a un FrameworkElement.
Al girar, escalar o sesgar un FrameworkElement utilizando el RenderTransform propiedad, el valor
predeterminado aplica la transformación a la esquina superior izquierda del elemento. Si desea girar, escalar o
sesgar desde el centro del elemento, puede realizar la compensación estableciendo el centro de la transformación
en el centro del elemento. Sin embargo, esa solución requiere que conozca el tamaño del elemento. Una manera
más fácil de aplicar una transformación al centro de un elemento es establecer su RenderTransformOrigin
propiedad en (0,5, 0,5), en lugar de establecer un valor central en la propia transformación.

Ejemplo
En el ejemplo siguiente se usa un RotateTransform para girar un Button 45 grados a la derecha. Puesto que el
ejemplo no especifica un centro, el botón gira sobre el punto (0, 0), que está en la esquina superior izquierda. El
RotateTransform se aplica a la RenderTransform propiedad.
La siguiente ilustración muestra el resultado de la transformación del ejemplo siguiente.

Giro hacia la derecha de 45 grados utilizando la propiedad RenderTransform

<Border Margin="30"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="1" >
<StackPanel Orientation="Vertical">
<Button Content="A Button" Opacity="1" />
<Button Content="Rotated Button">
<Button.RenderTransform>
<RotateTransform Angle="45" />
</Button.RenderTransform>
</Button>
<Button Content="A Button" Opacity="1" />
</StackPanel>
</Border>

El ejemplo siguiente se usa también un RotateTransform para girar un Button 45 grados a la derecha; sin
embargo, este ejemplo se establece la RenderTransformOrigin del botón en (0,5, 0,5). Como resultado, la rotación
se aplica al centro del botón en lugar de a la esquina superior izquierda.
La siguiente ilustración muestra el resultado de la transformación del ejemplo siguiente.
Una rotación de 45 grados utilizando la propiedad RenderTransform con un valor de RenderTransformOrigin de
(0,5, 0,5)

<Border Margin="30"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical">
<Button Content="A Button" Opacity="1" />
<Button Content="Rotated Button"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<RotateTransform Angle="45" />
</Button.RenderTransform>
</Button>
<Button Content="A Button" Opacity="1" />
</StackPanel>
</Border>

Para obtener más información acerca de la transformación FrameworkElement objetos, vea el información
general sobre transformaciones.

Vea también
Transform
Información general sobre transformaciones
Temas "Cómo..."
Procedimiento Trasladar un elemento
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo trasladar (mover) un elemento mediante el uso de un TranslateTransform.
La TranslateTransform clase es especialmente útil para mover elementos dentro de paneles que no admiten el
posicionamiento absoluto. Por ejemplo, aplicando un TranslateTransform a la RenderTransform propiedad de un
elemento, puede mover un elemento dentro de un StackPanel o DockPanel.
Use la X propiedad de la TranslateTransform para especificar la cantidad, en píxeles, que moverá el elemento a lo
largo del eje x. Use el Y propiedad para especificar la cantidad, en píxeles, que moverá el elemento a lo largo del
eje y. Por último, aplique el TranslateTransform a la RenderTransform propiedad del elemento.
En el ejemplo siguiente se usa un TranslateTransform para mover un elemento 50 píxeles a la derecho y 50 píxeles
hacia abajo.

Ejemplo
<Rectangle Height="50" Width="50"
Fill="#CCCCCCFF" Stroke="Blue" StrokeThickness="2"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<TranslateTransform X="50" Y="50" />
</Rectangle.RenderTransform>
</Rectangle>

Para ver el ejemplo completo, consulte Ejemplo de transformaciones 2D.

Vea también
Información general sobre transformaciones
Procedimiento Usar un objeto MatrixTransform para
crear transformaciones personalizadas
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo utilizar MatrixTransform un para trasladar (mover) la posición, el ajuste y el
Buttonsesgo de un.

NOTE
Utilice la MatrixTransform clase para crear transformaciones personalizadas no proporcionadas por las RotateTransformclases,
SkewTransform, ScaleTransformo TranslateTransform .

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel Margin="20">
<Canvas HorizontalAlignment="Left" Width="340" Height="240" >

<Button MinWidth="100">Click
<Button.RenderTransform>
<MatrixTransform x:Name="myMatrixTransform">
<MatrixTransform.Matrix >

<!-- OffsetX and OffsetY specify the position of the button,


M11 stretches it, and M12 skews it. -->
<Matrix OffsetX="10" OffsetY="100" M11="3" M12="2"/>
</MatrixTransform.Matrix>
</MatrixTransform>
</Button.RenderTransform>
</Button>
</Canvas>
</StackPanel>
</Page>

Vea también
MatrixTransform
Transform
Información general sobre transformaciones
Temas "Cómo..."
Información general sobre formas y dibujo básico en WPF
Configuración del Registro en la representación de
gráficos
20/02/2020 • 9 minutes to read • Edit Online

En este tema se ofrece información general sobre la configuración del Registro en la representación de gráficos
WPF que afecta a las aplicaciones de WPF.

Cuándo usar la configuración del Registro en la representación de


gráficos
Esta configuración del Registro se proporciona a efectos de solución de problemas, depuración y soporte técnico
del producto. Como los cambios al Registro afectan a todas las aplicaciones WPF, la aplicación no debe nunca
modificar estas claves del Registro automáticamente ni durante la instalación.

¿Qué son XPDM y WDDM?


Parte de la configuración del Registro en la representación de gráficos incluye distintos valores predeterminados,
que varían en función de que la tarjeta de vídeo use un controlador XPDM o WDDM. XPDM es el modelo de
controladores de pantalla de Microsoft Windows XP y WDDM es el modelo de controladores de pantalla de
Windows. WDDM está disponible en equipos que ejecutan Windows Vista y Windows 7. XPDM está disponible en
equipos que ejecutan Windows Vista, Microsoft Windows XP y Microsoft Windows Server 2003. Para obtener
más información acerca de WDDM, vea Guía de diseño de Windows Display Driver Model (WDDM ).

Configuración de registro
WPF proporciona cuatro parámetros de configuración del Registro para controlar la representación de WPF:

CONFIGURACIÓN DESCRIPCIÓN

Opción de deshabilitación de aceleración de hardware Especifica si se debe habilitar la aceleración de hardware.

Valor máximo de muestreo múltiple Especifica el grado de muestreo múltiple para el suavizado de
contorno de contenido 3D.

Configuración obligatoria de fecha del controlador de Especifica si el sistema deshabilita la aceleración de hardware
vídeo para los controladores publicados antes de noviembre de
2004.

Opción de uso del rasterizador de referencia Especifica si WPF debe utilizar el rasterizador de referencia.

Es posible acceder a estos parámetros mediante una utilidad de configuración externa que pueda hacer referencia
a la configuración del Registro de WPF. Esta configuración también se puede crear o modificar si se obtiene acceso
a los valores directamente mediante el editor del registro de Windows.

Opción de deshabilitación de aceleración de hardware


CLAVE DEL REGISTRO TIPO DE VALOR

DWORD
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\DisableHWAcceleration

La opción de deshabilitación de aceleración de hardware le permite desactivar la aceleración de hardware a


efectos de depuración y prueba. Cuando vea artefactos de representación en una aplicación, intente desactivar la
aceleración de hardware. Si el artefacto desaparece, podría ser el problema con el controlador de vídeo.
La opción de deshabilitación de aceleración de hardware es un valor DWORD que se establece en 0 o 1. Un
valor de 1 deshabilita la aceleración de hardware. Un valor de 0 habilita la aceleración de hardware, siempre que el
sistema cumpla los requisitos de aceleración de hardware. Para más información, consulte Niveles de
representación de gráficos.

Valor máximo de muestreo múltiple


CLAVE DEL REGISTRO TIPO DE VALOR

DWORD
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\MaxMultisampleType

El valor máximo de muestreo múltiple permite ajustar la cantidad máxima de suavizado de contorno del
contenido 3D. Use este nivel para deshabilitar el suavizado de contorno 3D en Windows Vista.
El valor máximo de muestreo múltiple es un valor DWORD comprendido entre 0 y 16. Un valor de 0 especifica
que debe deshabilitarse el suavizado de contorno de muestreo múltiple del contenido 3D y un valor de 16
intentará usar un suavizado de contorno de muestreo múltiple hasta 16 veces mayor, si la tarjeta de vídeo lo
admite. Tenga en cuenta que el establecimiento de este valor de clave del registro en los equipos que usan
controladores XPDM hará que las aplicaciones usen una gran cantidad de memoria de vídeo adicional, reduzcan el
rendimiento de la representación 3D y tenga el potencial de introducir errores de representación y estabilidad
surge.
Cuando no se establece esta clave del Registro, el valor predeterminado de WPF es 0 para los controladores
XPDM y 4 para los controladores WDDM.

Configuración obligatoria de fecha del controlador de vídeo


CLAVE DEL REGISTRO TIPO DE VALOR

String
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\RequiredVideoDriverDate

En noviembre de 2004, Microsoft publicó una nueva versión de las directrices de pruebas de controladores; los
controladores escritos después de esta fecha ofrecen una mayor estabilidad. De forma predeterminada, WPF usará
la canalización de aceleración de hardware para estos controladores y recurrirá a la representación de software
para los controladores XPDM publicados antes de esta fecha.
La configuración obligatoria de fecha del controlador de vídeo le permite especificar una fecha mínima
alternativa para los controladores XPDM. Solo se debe especificar una fecha anterior a noviembre de 2004 si está
seguro de que el controlador de vídeo es lo suficientemente estable como para admitir WPF.
La configuración obligatoria de fecha del controlador de vídeo adopta una cadena con el formato siguiente:

YYYY / mm / DD
Donde AAAA son los cuatro dígitos del año, MM son los dos dígitos del mes y DD son los dos dígitos del día.
Cuando este valor no se establece, WPF usa noviembre de 2004 como fecha obligatoria del controlador de vídeo.

Opción de uso del rasterizador de referencia


CLAVE DEL REGISTRO TIPO DE VALOR

DWORD
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\UseReferenceRasterizer

La opción usar rasterizador de referencia permite forzar el WPF en un modo de representación de hardware
simulado para la depuración: WPF entra en modo de hardware, pero usa el rasterizador de software de referencia
de Microsoft Direct3D, d3dref9. dll, en lugar de un dispositivo de hardware real.
El rasterizador de referencia es muy lento, pero omite el controlador de vídeo para evitar cualquier problema de
representación causado por problemas de controladores. Por este motivo, se puede usar el rasterizador de
referencia para determinar si los problemas de representación se deben al controlador de vídeo. El archivo
d3dref9.dll debe estar en una ubicación en la que la aplicación pueda acceder a él, como cualquier ubicación en la
ruta del sistema o el directorio local de la aplicación.
La opción de uso del rasterizador de referencia adopta un valor DWORD. Un valor de 0 indica que no se usa
el rasterizador de referencia. Cualquier otro valor distinto de cero fuerza a WPF a usar el rasterizador de referencia.

Consulte también
Niveles de representación de gráficos
Información general sobre la representación de gráficos en WPF
Temas "Cómo..." de gráficos
23/10/2019 • 2 minutes to read • Edit Online

Los temas siguientes muestran cómo usar las capacidades gráficas de la Windows Presentation Foundation
(WPF ).

En esta sección
Animar un rectángulo
Animar la posición de un objeto mediante PointAnimation
Transformar puntos y vectores
Ampliar el marco de vidrio en una aplicación de WPF
Cómo: Mejorar el rendimiento al almacenar en caché un elemento de la representación
Cómo: Usar un elemento almacenado en caché como pincel

Vea también
Shape
Transform
BitmapImage
Geometry
Drawing
Brush
BitmapEffect
Gráficos y multimedia
Información general sobre la representación de gráficos en WPF
Procedimiento Animar un rectángulo
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo animar los cambios de tamaño y posición de un rectángulo.

Ejemplo
En el ejemplo siguiente se usa una instancia de la RectAnimation clase se va a animar el Rect propiedad de un
RectangleGeometry, que anima los cambios de tamaño y posición del rectángulo.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;

namespace SDKSamples
{
public class RectAnimationExample : Page
{
public RectAnimationExample()
{

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

RectangleGeometry myRectangleGeometry = new RectangleGeometry();


myRectangleGeometry.Rect = new Rect(0, 200, 100, 100);

// Assign the geometry a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"MyAnimatedRectangleGeometry", myRectangleGeometry);

Path myPath = new Path();


myPath.Fill = Brushes.LemonChiffon;
myPath.StrokeThickness = 1;
myPath.Stroke = Brushes.Black;
myPath.Data = myRectangleGeometry;

RectAnimation myRectAnimation = new RectAnimation();


myRectAnimation.Duration = TimeSpan.FromSeconds(2);
myRectAnimation.FillBehavior = FillBehavior.HoldEnd;

// Set the animation to repeat forever.


myRectAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the From and To properties of the animation.


myRectAnimation.From = new Rect(0, 200, 100, 100);
myRectAnimation.To = new Rect(600, 50, 200, 50);

// Set the animation to target the Rect property


// of the object named "MyAnimatedRectangleGeometry."
Storyboard.SetTargetName(myRectAnimation, "MyAnimatedRectangleGeometry");
Storyboard.SetTargetProperty(
myRectAnimation, new PropertyPath(RectangleGeometry.RectProperty));

// Create a storyboard to apply the animation.


Storyboard ellipseStoryboard = new Storyboard();
ellipseStoryboard.Children.Add(myRectAnimation);

// Start the storyboard when the Path loads.


myPath.Loaded += delegate(object sender, RoutedEventArgs e)
{
ellipseStoryboard.Begin(this);
};

Canvas containerCanvas = new Canvas();


containerCanvas.Children.Add(myPath);

Content = containerCanvas;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation
Imports System.Windows.Media

Namespace SDKSamples
Public Class RectAnimationExample
Inherits Page
Public Sub New()

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myRectangleGeometry As New RectangleGeometry()


myRectangleGeometry.Rect = New Rect(0, 200, 100, 100)

' Assign the geometry a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("MyAnimatedRectangleGeometry", myRectangleGeometry)

Dim myPath As New Path()


With myPath
.Fill = Brushes.LemonChiffon
.StrokeThickness = 1
.Stroke = Brushes.Black
.Data = myRectangleGeometry
End With

Dim myRectAnimation As New RectAnimation()


With myRectAnimation
.Duration = TimeSpan.FromSeconds(2)
.FillBehavior = FillBehavior.HoldEnd

' Set the animation to repeat forever.


.RepeatBehavior = RepeatBehavior.Forever

' Set the From and To properties of the animation.


.From = New Rect(0, 200, 100, 100)
.To = New Rect(600, 50, 200, 50)
End With

' Set the animation to target the Rect property


' of the object named "MyAnimatedRectangleGeometry."
Storyboard.SetTargetName(myRectAnimation, "MyAnimatedRectangleGeometry")
Storyboard.SetTargetProperty(myRectAnimation, New PropertyPath(RectangleGeometry.RectProperty))

' Create a storyboard to apply the animation.


Dim ellipseStoryboard As New Storyboard()
ellipseStoryboard.Children.Add(myRectAnimation)

' Start the storyboard when the Path loads.


AddHandler myPath.Loaded, Sub(sender As Object, e As RoutedEventArgs) ellipseStoryboard.Begin(Me)

Dim containerCanvas As New Canvas()


containerCanvas.Children.Add(myPath)

Content = containerCanvas
End Sub
End Class
End Namespace

Vea también
RectAnimation
Rect
RectangleGeometry
Información general sobre animaciones
Gráficos y multimedia
Temas de procedimientos de gráficos
Temas de procedimientos de temporización y animación
Procedimiento Animar la posición de un objeto
mediante PointAnimation
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el PointAnimation clase para animar un objeto a lo largo de un Path.

Ejemplo
En el ejemplo siguiente se mueve una elipse a lo largo de un Path desde un punto en la pantalla a otra. En el
ejemplo se anima la posición de un EllipseGeometry utilizando PointAnimation para animar el Center propiedad.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;

namespace SDKSamples
{
// This example shows how to use PointAnimation to animate the
// position of an ellipse by animating the Center property of an
// EllipseGeometry. PointAnimation is used because the Center property
// takes a Point value.
public class PointAnimationExample : Page
{
public PointAnimationExample()
{

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

EllipseGeometry myEllipseGeometry = new EllipseGeometry();


myEllipseGeometry.Center = new Point(200, 100);
myEllipseGeometry.RadiusX = 15;
myEllipseGeometry.RadiusY = 15;

// Assign the EllipseGeometry a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"MyAnimatedEllipseGeometry", myEllipseGeometry);

Path myPath = new Path();


myPath.Fill = Brushes.Blue;
myPath.Margin = new Thickness(15);
myPath.Data = myEllipseGeometry;

PointAnimation myPointAnimation = new PointAnimation();


myPointAnimation.Duration = TimeSpan.FromSeconds(2);

// Set the animation to repeat forever.


myPointAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the From and To properties of the animation.


myPointAnimation.From = new Point(200, 100);
myPointAnimation.To = new Point(450, 250);

// Set the animation to target the Center property


// of the object named "MyAnimatedEllipseGeometry."
// of the object named "MyAnimatedEllipseGeometry."
Storyboard.SetTargetName(myPointAnimation, "MyAnimatedEllipseGeometry");
Storyboard.SetTargetProperty(
myPointAnimation, new PropertyPath(EllipseGeometry.CenterProperty));

// Create a storyboard to apply the animation.


Storyboard ellipseStoryboard = new Storyboard();
ellipseStoryboard.Children.Add(myPointAnimation);

// Start the storyboard when the Path loads.


myPath.Loaded += delegate(object sender, RoutedEventArgs e)
{
ellipseStoryboard.Begin(this);
};

Canvas containerCanvas = new Canvas();


containerCanvas.Children.Add(myPath);

Content = containerCanvas;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation
Imports System.Windows.Media

Namespace SDKSamples
' This example shows how to use PointAnimation to animate the
' position of an ellipse by animating the Center property of an
' EllipseGeometry. PointAnimation is used because the Center property
' takes a Point value.
Public Class PointAnimationExample
Inherits Page
Public Sub New()

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myEllipseGeometry As New EllipseGeometry()


With myEllipseGeometry
.Center = New Point(200, 100)
.RadiusX = 15
.RadiusY = 15
End With

' Assign the EllipseGeometry a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("MyAnimatedEllipseGeometry", myEllipseGeometry)

Dim myPath As New Path()


With myPath
.Fill = Brushes.Blue
.Margin = New Thickness(15)
.Data = myEllipseGeometry
End With

Dim myPointAnimation As New PointAnimation()


With myPointAnimation
.Duration = TimeSpan.FromSeconds(2)

' Set the animation to repeat forever.


.RepeatBehavior = RepeatBehavior.Forever
' Set the From and To properties of the animation.
.From = New Point(200, 100)
.To = New Point(450, 250)
End With

' Set the animation to target the Center property


' of the object named "MyAnimatedEllipseGeometry."
Storyboard.SetTargetName(myPointAnimation, "MyAnimatedEllipseGeometry")
Storyboard.SetTargetProperty(myPointAnimation, New PropertyPath(EllipseGeometry.CenterProperty))

' Create a storyboard to apply the animation.


Dim ellipseStoryboard As New Storyboard()
ellipseStoryboard.Children.Add(myPointAnimation)

' Start the storyboard when the Path loads.


AddHandler myPath.Loaded, Sub(sender As Object, e As RoutedEventArgs) ellipseStoryboard.Begin(Me)

Dim containerCanvas As New Canvas()


containerCanvas.Children.Add(myPath)

Content = containerCanvas
End Sub

End Class
End Namespace

Vea también
PointAnimation
Path
EllipseGeometry
Center
Información general sobre animaciones
Gráficos y multimedia
Temas de procedimientos de gráficos
Temas de procedimientos de temporización y animación
Procedimiento Transformar puntos y vectores
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un Matrix transformar Point y Vector objetos.

Ejemplo
private void transformExamples()
{

Matrix myMatrix = new Matrix(5, 10, 15, 20, 25, 30);

//
// Transform a point.
//
Point myPoint = new Point(15,25);

// pointResult is (475, 680).


Point pointResult = myMatrix.Transform(myPoint);

//
// Transform an array of points.
//
Point[] myPointArray = new Point[]
{new Point(15,25), new Point(30,35)};

// myPointArray[0] becomes (475, 680).


// myPointArray[1] becomes (700, 1030).
myMatrix.Transform(myPointArray);

//
// Transform a vector.
//
Vector myVector = new Vector(15,25);

// vectorResult becomes (450, 650).


Vector vectorResult = myMatrix.Transform(myVector);

//
// Transform an array of vectors.
//
Vector[] myVectorArray = new Vector[]
{new Vector(15, 25), new Vector(30,35)};

// myVectorArray[0] becomes (450, 650).


// myVectorArray[1] becomes (675, 1000).
myMatrix.Transform(myVectorArray);
}
Ampliar el marco de vidrio en una aplicación de WPF
03/02/2020 • 4 minutes to read • Edit Online

En este tema se muestra cómo extender el marco Glass de Windows Vista en el área cliente de una aplicación
Windows Presentation Foundation (WPF ).

NOTE
Este ejemplo solo funcionará en un equipo con Windows Vista que ejecute el Administrador de ventanas de escritorio (DWM)
con Glass habilitado. Windows Vista Home Basic Edition no admite el efecto de cristal transparente. Las áreas que
normalmente se representarían con el efecto de cristal transparente en otras ediciones de Windows Vista se representan
opacas.

Ejemplo
En la imagen siguiente se muestra el marco Glass extendido en la barra de direcciones de Internet Explorer 7:

Para extender el marco Glass en una aplicación WPF, se necesita acceso a la API no administrada. En el ejemplo de
código siguiente se realiza una invocación de plataforma (PInvoke) para las dos API necesarias para extender el
marco en el área cliente. Cada una de estas API se declaran en una clase denominada NonClientRegionAPI.

[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
public int cxLeftWidth; // width of left border that retains its size
public int cxRightWidth; // width of right border that retains its size
public int cyTopHeight; // height of top border that retains its size
public int cyBottomHeight; // height of bottom border that retains its size
};

[DllImport("DwmApi.dll")]
public static extern int DwmExtendFrameIntoClientArea(
IntPtr hwnd,
ref MARGINS pMarInset);

<StructLayout(LayoutKind.Sequential)>
Public Structure MARGINS
Public cxLeftWidth As Integer ' width of left border that retains its size
Public cxRightWidth As Integer ' width of right border that retains its size
Public cyTopHeight As Integer ' height of top border that retains its size
Public cyBottomHeight As Integer ' height of bottom border that retains its size
End Structure

<DllImport("DwmApi.dll")>
Public Shared Function DwmExtendFrameIntoClientArea(ByVal hwnd As IntPtr, ByRef pMarInset As MARGINS) As
Integer
End Function
DwmExtendFrameIntoClientArea es la función de DWM que amplia el marco en el área cliente. Toma dos
parámetros; un identificador de ventana y una estructura MARGINS. MARGINS se usa para indicarle al DWM
cuánto más debe ampliarse el marco en el área cliente.

Ejemplo
Para usar la función DwmExtendFrameIntoClientArea, debe obtenerse un identificador de ventana. En WPF, el
identificador de ventana se puede obtener de la propiedad Handle de una HwndSource. En el ejemplo siguiente, el
marco se extiende en el área cliente del evento Loaded de la ventana.

void OnLoaded(object sender, RoutedEventArgs e)


{
try
{
// Obtain the window handle for WPF application
IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);

// Get System Dpi


System.Drawing.Graphics desktop = System.Drawing.Graphics.FromHwnd(mainWindowPtr);
float DesktopDpiX = desktop.DpiX;
float DesktopDpiY = desktop.DpiY;

// Set Margins
NonClientRegionAPI.MARGINS margins = new NonClientRegionAPI.MARGINS();

// Extend glass frame into client area


// Note that the default desktop Dpi is 96dpi. The margins are
// adjusted for the system Dpi.
margins.cxLeftWidth = Convert.ToInt32(5 * (DesktopDpiX / 96));
margins.cxRightWidth = Convert.ToInt32(5 * (DesktopDpiX / 96));
margins.cyTopHeight = Convert.ToInt32(((int)topBar.ActualHeight + 5) * (DesktopDpiX / 96));
margins.cyBottomHeight = Convert.ToInt32(5 * (DesktopDpiX / 96));

int hr = NonClientRegionAPI.DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins);


//
if (hr < 0)
{
//DwmExtendFrameIntoClientArea Failed
}
}
// If not Vista, paint background white.
catch (DllNotFoundException)
{
Application.Current.MainWindow.Background = Brushes.White;
}
}

Ejemplo
En el ejemplo siguiente se muestra una ventana simple en la que el marco se amplía en el área cliente. El marco se
extiende detrás del borde superior que contiene los dos objetos TextBox.
<Window x:Class="SDKSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Extended Glass in WPF" Height="300" Width="400"
Loaded="OnLoaded" Background="Transparent"
>
<Grid ShowGridLines="True">
<DockPanel Name="mainDock">
<!-- The border is used to compute the rendered height with margins.
topBar contents will be displayed on the extended glass frame.-->
<Border Name="topBar" DockPanel.Dock="Top" >
<Grid Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="100" Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" MinWidth="100" Margin="0,0,10,5">Path</TextBox>
<TextBox Grid.Column="1" MinWidth="75" Margin="0,0,0,5">Search</TextBox>
</Grid>
</Border>
<Grid DockPanel.Dock="Top" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" AcceptsReturn="True"/>
</Grid>
</DockPanel>
</Grid>
</Window>

En la imagen siguiente se muestra el marco Glass extendido en una aplicación WPF:

Consulte también
Información general de Administrador de ventanas de escritorio
Información general sobre desenfoque Administrador de ventanas de escritorio
DwmExtendFrameIntoClientArea (DwmExtendFrameIntoClientArea [función])
Procedimiento para mejorar el rendimiento de la
representación mediante el almacenamiento en caché
de un elemento
23/10/2019 • 96 minutes to read • Edit Online

Use la BitmapCache clase para mejorar el rendimiento de la representación de un complejo UIElement. Para
almacenar en caché un elemento, crear una nueva instancia de la BitmapCache clase y se asigna a la propiedad del
elemento CacheMode propiedad. Puede volver a usar un BitmapCache eficazmente en un BitmapCacheBrush.

Ejemplo
El ejemplo de código siguiente muestra cómo crear un elemento complejo y lo almacena en caché como un mapa
de bits, lo que mejora el rendimiento cuando se anima el elemento. El elemento es un lienzo que contiene formas
geométricas con muchos vértices. Un BitmapCache no tiene valor predeterminado se asigna valores a la
CacheMode del lienzo, y una animación muestra la escala sin problemas del mapa de bits almacenado en caché.

<Window x:Class="CachedCompositionDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="bitmapCacheCanvas"
Storyboard.TargetProperty="(Canvas.RenderTransform).(ScaleTransform.ScaleX)"
From="0.5" To="4.0" Duration="0:0:4"
AutoReverse="True" RepeatBehavior="Forever" />
<DoubleAnimation
Storyboard.TargetName="bitmapCacheCanvas"
Storyboard.TargetProperty="(Canvas.RenderTransform).(ScaleTransform.ScaleY)"
From="0.5" To="4.0" Duration="0:0:4"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Canvas>
<Canvas x:Name="demoCanvas" Canvas.Top="10">
<Canvas Name='Popcan_xpr'>
<Canvas x:Name="bitmapCacheCanvas">
<Canvas.RenderTransform>
<ScaleTransform CenterX="200" CenterY="600"/>
</Canvas.RenderTransform>

<!-- //////////////////////////////////////////////////////////////// -->


<!-- // The following XAML creates a BitmapCache with default // -->
<!-- // properties and assigns it as the CacheMode for the canvas. // -->
<!-- //////////////////////////////////////////////////////////////// -->
<Canvas.CacheMode>
<BitmapCache EnableClearType="False"
RenderAtScale="1"
SnapsToDevicePixels="False" />
</Canvas.CacheMode>

<Canvas Name='Layer_2' Width='1280' Height='1024'>


<Canvas Name='Layer_2' Width='1280' Height='1024'>
<Path Canvas.Left='191.32' Canvas.Top='738.375' Data='F1 M 0,158.843L 81.744,196.619L
108.992,206.682L 126.332,216.126L 138.717,221.39L 210.553,262.107L 265.049,256.379L 274.957,249.412L
304.682,246.78L 314.591,239.194L 351.747,235.169L 388.903,223.403L 413.674,222.783L 423.583,213.649L
458.262,213.185L 463.216,205.908L 492.941,202.347L 502.85,194.452L 537.529,192.903L 547.437,184.079L
582.116,183.305L 592.025,173.861L 626.704,173.396L 636.612,163.952L 671.292,163.488L 681.2,154.044L
715.879,153.58L 725.788,144.136L 760.467,143.207L 775.33,130.512L 810.009,128.189L 819.917,119.984L
854.596,117.352L 864.505,111.005L 909.093,103.419L 917.608,79.5765L 890.05,47.3743L 849.642,30.9636L
822.394,26.0094L 795.146,16.7203L 710.925,0.464417L 611.842,0L 572.208,6.9668L 562.3,13.624L 530.098,18.5781L
502.85,28.9509L 473.124,30.4991L 463.216,39.6334L 433.491,40.4075L 418.628,54.0315L 383.949,56.6635L
374.041,63.011L 324.499,71.3712L 314.591,78.0283L 227.892,98.4644L 200.644,107.753L 161.011,118.281L
136.24,119.674L 126.332,128.809L 101.561,129.428L 91.6524,138.872L 52.0189,139.956L 37.1564,152.186L
2.47708,156.057L 0,158.843'>
<Shape.Fill>
<!-- alloy -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='282.68,199.959'
EndPoint='764.68,13.9586'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#175C686E' Offset='0'/>
<GradientStop Color='#17B8BEC7' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='191.32' Canvas.Top='736.827' Data='F1 M 0,160.392L 81.744,198.167L


108.992,208.23L 126.332,217.674L 138.717,222.938L 210.553,263.655L 265.049,257.927L 274.957,250.96L
304.682,248.328L 314.591,240.742L 351.747,236.717L 408.72,221.235L 445.876,216.126L 473.124,206.373L
492.941,203.741L 502.85,196.155L 537.529,194.297L 547.437,185.782L 582.116,184.853L 592.025,175.409L
626.704,174.945L 636.612,165.501L 671.292,165.036L 681.2,155.592L 715.879,155.128L 725.788,145.684L
760.467,145.219L 775.33,131.131L 810.009,130.357L 819.917,120.913L 854.596,120.449L 864.505,111.005L
899.184,110.695L 911.57,98.6192L 917.298,81.1248L 890.669,48.9225L 862.028,37.7756L 775.33,13.1595L
743.127,8.6698L 720.834,2.94153L 611.842,0L 596.979,5.72827L 572.208,7.43127L 562.3,16.2559L 532.575,17.03L
522.666,26.4739L 483.033,27.5576L 468.17,39.7883L 433.491,42.7299L 418.628,54.0316L 381.472,59.7598L
287.343,85.3048L 193.213,109.147L 165.965,119.674L 136.24,121.223L 126.332,130.357L 101.561,130.976L
91.6524,140.42L 52.0189,141.504L 37.1564,153.734L 2.47708,156.676L 0,160.392'>
<Shape.Fill>
<!-- alloy -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='282.68,201.507'
EndPoint='764.68,15.5068'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#155C686E' Offset='0'/>
<GradientStop Color='#15B8BEC7' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='191.32' Canvas.Top='736.362' Data='F1 M 0,160.856L 81.744,198.632L


108.992,208.695L 210.553,263.501L 265.049,258.701L 274.957,251.115L 309.636,249.257L 319.545,240.742L
354.224,239.813L 364.132,230.37L 391.38,230.215L 423.583,220.926L 448.354,219.532L 458.262,211.017L
483.033,209.624L 497.895,196.929L 537.529,194.761L 547.437,186.246L 587.071,185.317L 596.979,175.874L
619.273,175.719L 651.475,166.43L 676.246,165.036L 686.154,156.521L 720.834,155.592L 730.742,146.148L
748.082,145.994L 785.238,132.37L 814.963,130.047L 824.871,122.152L 859.551,120.603L 869.459,111.779L
904.138,111.159L 911.57,106.36L 916.524,81.5892L 896.243,54.3412L 879.367,43.8136L 866.982,39.3239L
817.44,23.2228L 760.467,10.6825L 750.559,3.71564L 601.933,0L 587.071,7.12164L 567.254,7.58612L 557.346,17.03L
535.052,17.1848L 502.85,30.1896L 473.124,32.8215L 463.216,41.3365L 428.537,42.1106L 423.583,49.387L
376.518,60.9984L 334.407,68.4297L 324.499,75.0869L 277.434,85.3048L 237.801,94.2843L 210.553,105.586L
190.736,106.979L 180.828,115.804L 143.671,119.21L 126.332,129.118L 96.6066,132.06L 86.6982,140.265L
42.1105,147.077L 32.2022,154.973L 2.47708,156.057L 0,160.856'>
<Shape.Fill>
<!-- alloy -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='282.68,201.971'
EndPoint='764.68,15.9713'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStopCollection>
<GradientStop Color='#135C686E' Offset='0'/>
<GradientStop Color='#13B8BEC7' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='184.167' Canvas.Top='312.697' Data='F1 M 406.667,586.572C


406.667,640.88 315.631,680.649 203.333,684.905C 91.0355,684.905 0,640.88 0,586.572C 0,585.152
0.0622559,583.739 0.185486,582.333L 6.10352e-005,582.333L 6.10352e-005,0L 402.028,1L 406.667,582.333L
406.481,582.333C 406.604,583.739 406.667,585.152 406.667,586.572'>
<Shape.Fill>
<!-- blue -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='-4.28632,337.69'
EndPoint='412.423,337.69'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FF0038A6' Offset='0'/>
<GradientStop Color='#FF2A82E7' Offset='0.484375'/>
<GradientStop Color='#FF0038A6' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='198.933' Canvas.Top='803.014' Data='F1 M 0.181965,101.931C


20.5224,122.785 70.8955,144.918 121.269,150.957C 121.375,115.7 121.746,47.1885 121.746,47.1885C
74.6269,40.1877 27.0522,24.095 1.98131e-006,0L 0.181965,101.931'>
<Shape.Fill>
<!-- fade -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='276.067,98.0692'
EndPoint='-371.433,98.0692'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FFFFFFFF' Offset='0'/>
<GradientStop Color='#FF646464' Offset='0.734375'/>
<GradientStop Color='#FF828282' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='183.833' Canvas.Top='223.173' Data='F1 M 203.333,0C 315.631,0


406.667,44.0253 406.667,98.3334C 406.667,152.641 315.631,196.667 203.333,196.667C 91.0354,196.667 0,152.641
0,98.3334C 0,44.0254 91.0355,0 203.333,0'>
<Shape.Fill>
<!-- blue -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='259.5,20.9026'
EndPoint='259.5,347.569'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FF0038A6' Offset='0'/>
<GradientStop Color='#FF2A82E7' Offset='0.484375'/>
<GradientStop Color='#FF0038A6' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='374.55' Canvas.Top='273.133' Data='F1 M 190.25,0C 146.5,28.75


54.2001,64.2 54.2001,64.2C 54.2001,77.95 164.2,82.95 156.7,270.45C 148.48,475.962 21.7001,519.2
0.450134,707.95C 0,711.948 189.95,706.85 217.45,625.6C 217.45,506.85 216.65,128.318 216.65,51.2C
216.65,49.9501 216.25,16.8 190.25,0'>
<Shape.Fill>
<!-- fade -->
<!-- fade -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='-188.883,653.2'
EndPoint='709.45,653.2'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FFFFFFFF' Offset='0'/>
<GradientStop Color='#FF646464' Offset='0.734375'/>
<GradientStop Color='#FF828282' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='539.747' Canvas.Top='345.745' Data='F1 M 36.0103,448.724C


41.0389,444.498 46.7076,440.893 51.921,439.078L 51.921,484.402C 51.5677,483.883 51.1672,483.41 50.7137,482.99C
47.7121,480.211 40.3624,483.212 35.2047,487.424C 29.1878,493.094 24.1761,501.302 21.4851,508.657C
17.3874,519.859 17.337,530.296 16.9959,540.33C 33.8355,532.096 44.544,519.008 51.921,506.273L 51.921,541.413C
38.5948,562.405 19.5574,577.31 0.163687,587.966C 1.25488,560.521 2.60647e-005,533.875 5.81624,504.462C
7.97904,493.525 11.5487,481.597 17.9334,470.42C 22.5329,462.369 29.2518,454.897 36.0103,448.724M
46.9429,385.656C 48.6156,384.273 50.278,382.844 51.921,381.372L 51.921,419.109C 36.5704,432.945
18.6974,444.081 1.9323,452.254C 2.79406,430.72 2.93709,409.41 4.79355,387.559C 5.55573,378.588 6.80175,369.377
9.40255,360.064C 11.2171,353.567 14.3247,346.116 19.5642,341.026C 22.636,338.041 27.08,335.389
30.2042,335.905C 33.3162,336.419 35.6892,338.668 37.0759,341.404C 38.0356,343.297 38.7239,345.408
39.3263,347.559L 39.4634,348.14L 39.9145,350.03L 40.4239,352.695L 40.8067,355.244C 40.8223,355.347
40.7795,355.501 40.854,355.555C 40.8987,355.587 40.9787,355.46 41.041,355.413C 42.7723,345.745 46.908,336.039
51.921,326.326L 51.921,368.209C 49.0751,374.177 47.042,380.162 46.9429,385.656M 25.1686,377.418C 21.658,379.87
19.3768,384.873 18.5148,388.782C 17.2025,394.732 17.3739,400.376 17.1756,406.052C 22.3202,403.134
27.43,399.985 32.4412,396.564C 32.5887,391.233 33.1802,385.553 31.7822,381.001C 30.9864,378.41 28.1387,375.831
25.1686,377.418M 6.98284,326.05L 8.54462,287.025C 22.932,280.011 38.6357,271.056 51.921,259.53L
51.921,297.212C 38.1458,309.284 21.9311,318.763 6.98284,326.05M 44.5368,193.815C 42.8057,197.704
41.049,201.592 39.1495,205.449C 38.1553,207.468 36.2493,209.576 36.1942,211.512C 41.3503,207.55
46.7677,203.555 51.921,199.248L 51.921,234.849C 38.9579,246.015 23.5872,254.621 9.5679,261.455L
11.0429,224.598C 18.6477,209.899 26.0171,195.131 33.0107,180.295C 37.3168,171.159 40.8897,161.844
45.8446,152.872C 45.8709,151.727 43.7505,154.558 42.6783,155.344C 40.2293,157.138 37.7422,158.843
35.2328,160.463C 27.991,165.136 20.5601,169.205 13.1144,172.835L 14.5605,136.7C 23.4428,132.37 32.3209,127.394
40.8585,121.501C 44.6193,118.905 48.3305,116.122 51.921,113.132L 51.921,176.737C 49.538,182.441
47.0655,188.135 44.5368,193.815M 51.3152,44.873C 49.5983,48.4014 45.7425,51.953 45.6583,55.3285C
47.7713,53.788 49.8655,52.1902 51.921,50.5204L 51.921,88.4083C 51.4235,88.8184 50.9241,89.2243 50.4232,89.626C
39.4131,98.4545 27.4505,105.441 15.5799,111.227L 17.1416,72.2014C 26.1861,67.7924 35.2174,62.6481
43.892,56.5936C 43.9231,55.4009 42.0608,55.8029 41.1702,55.3687C 39.2176,54.4168 37.3076,53.3999
35.4101,52.3657C 29.5476,49.1705 23.8851,45.6812 18.3491,42.0291L 8.84882,4.99731C 16.8038,12.4969
33.558,14.9082 42.1643,21.6551C 44.5389,16.6802 48.0366,5.01251 50.2553,0L 51.921,43.6231C 51.7198,44.04
51.5178,44.4566 51.3152,44.873'>
<Shape.Fill>
<!-- blue -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='61.9193,301.588'
EndPoint='-178.081,301.588'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FF0038A6' Offset='0'/>
<GradientStop Color='#FF2A82E7' Offset='0.484375'/>
<GradientStop Color='#FF0038A6' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='212.489' Canvas.Top='172.534' Data='F1 M 178.277,0C 276.736,0


356.554,37.5338 356.554,83.834C 356.554,130.134 276.736,167.668 178.277,167.668C 79.8172,167.668 5.1753e-
006,130.134 5.1753e-006,83.834C 5.1753e-006,37.5338 79.8172,0 178.277,0'>
<Shape.Fill>
<!-- fade -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='141.111,10.1998'
EndPoint='375.511,162.2'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FFFFFFFF' Offset='0'/>
<GradientStop Color='#FF646464' Offset='0.734375'/>
<GradientStop Color='#FF646464' Offset='0.734375'/>
<GradientStop Color='#FF828282' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='303.391' Canvas.Top='352.426' Fill='#14FFFFFF' Data='F1 M


65.4263,12.2839C 64.1538,12.2839 62.8809,12.2491 61.6088,12.2839C 59.214,12.3493 57.0076,14.085
55.3473,15.812C 52.0241,19.2688 50.8018,24.3486 47.6602,27.9711C 44.3193,31.8234 40.1792,34.9216
36.7621,38.7065C 30.8181,45.29 25.7855,52.7066 21.2686,60.3402C 21.2013,60.0004 21.1274,59.6598
21.0131,59.3328C 20.9454,59.1389 20.8669,58.9477 20.7683,58.7676C 20.6047,58.4687 20.0661,58.075
19.8432,58.3327C 19.4515,58.7853 19.4746,59.4886 19.4599,60.087C 19.4501,60.4868 19.4519,60.8878
19.4853,61.2863C 19.5733,62.3372 19.6964,63.3849 19.8238,64.4318C 20.4342,69.4479 21.3066,74.4547
21.4228,79.5065C 20.501,96.3665 17.9513,113.156 17.9242,130.041C 18.0921,145.86 19.0748,161.662
19.3607,177.479C 19.7505,199.042 19.7605,220.61 20.0542,242.174C 20.7408,292.574 21.5402,342.972
21.9943,393.374C 21.9816,409.789 20.0644,426.166 18.1425,442.468C 17.4128,448.588 18.3183,454.807
18.9048,460.942C 19.6439,468.674 20.4418,476.427 20.4091,484.194C 21.4507,496.313 24.1274,508.252
25.1765,520.37C 26.9892,541.307 27.2285,562.36 27.4475,583.374C 27.3929,587.422 27.0435,591.462
26.7368,595.498C 26.5515,597.938 26.7275,600.663 25.3936,602.713C 24.4395,604.18 22.6813,604.939
21.1993,605.87C 19.3626,607.022 17.4665,608.077 15.6004,609.182C 9.84341,612.59 3.27774,617.104
1.62491,623.587C 1.23764,624.288 0.914734,625.061 0.839386,625.858C 0,622.518 1.3714,618.745 3.13147,615.785C
5.71729,611.437 9.68918,608.025 12.3076,603.696C 13.929,601.016 13.762,597.576 14.0052,594.452C
14.2924,590.764 14.6337,587.074 14.6853,583.374C 14.4818,562.383 14.0421,541.384 12.9281,520.421C
12.2683,508.004 10.5257,495.634 10.4623,483.2C 10.6733,476.113 10.0403,469.014 9.3396,461.959C 8.66492,455.165
7.74802,448.29 8.4357,441.497C 10.2101,425.508 12.0303,409.461 12.0801,393.374C 11.6913,321.408
11.2804,249.442 10.4999,177.479C 10.3284,161.665 9.73871,145.856 9.63803,130.041C 9.69009,113.475
11.6339,96.9529 11.7372,80.387C 11.5738,76.6815 10.987,72.9952 10.2598,69.358C 10.1412,68.7649 10.0145,68.1734
9.89856,67.5798C 9.69495,66.5375 9.48825,65.4957 9.30112,64.4503C 9.2215,64.0055 9.15695,63.558 9.09842,63.11C
9.04733,62.7189 9.00879,62.3261 8.97238,61.9333C 8.90652,61.2231 8.888,60.4958 9.01538,59.7941C
9.08109,59.4321 9.27911,58.8451 9.64462,58.8872C 14.7638,43.1336 25.0822,29.1252 36.3355,16.9702C
40.4689,12.5056 44.3391,7.57953 49.4427,4.26746C 53.6575,1.53229 58.8749,0 63.8994,0L 65.4263,12.2839'/>

<Path Canvas.Left='300.812' Canvas.Top='340.142' Fill='#27FFFFFF' Data='F1 M


66.4785,12.2838C 61.4541,12.2838 56.2366,13.8161 52.0219,16.5513C 46.9182,19.8633 43.0481,24.7894
38.9147,29.254C 27.6613,41.4091 17.3429,55.4174 12.2238,71.171C 11.8583,71.1289 11.6602,71.7159
11.5945,72.0779C 11.4672,72.7797 11.4857,73.507 11.5515,74.2172C 11.7276,76.1163 12.1121,77.9917
12.4777,79.8636C 13.3046,84.0964 14.1263,88.3622 14.3163,92.6708C 14.213,109.237 12.2693,125.759
12.2172,142.325C 12.3179,158.14 12.9076,173.949 13.0791,189.763C 13.8596,261.726 14.2704,333.692
14.6592,405.658C 14.6095,421.745 12.7892,437.792 11.0149,453.781C 10.3272,460.573 11.2441,467.449
11.9188,474.242C 12.6194,481.298 13.2525,488.396 13.0414,495.484C 13.1049,507.918 14.8475,520.288
15.5073,532.705C 16.6212,553.668 17.0609,574.667 17.2645,595.658C 17.2129,599.357 16.8716,603.048
16.5844,606.736C 16.3412,609.859 16.5082,613.299 14.8867,615.98C 12.2683,620.309 8.29645,623.721
5.71063,628.069C 3.95056,631.029 2.57916,634.802 3.41855,638.142C 3.39194,638.71 3.51257,639.296
3.73703,639.819C 1.97946,637.236 1.06824,634 0.920105,630.88C 0.705292,626.354 1.76813,621.844
2.63284,617.396C 4.0209,610.257 4.39554,602.93 4.50229,595.658C 4.31595,574.688 3.68497,553.723
3.25891,532.756C 2.99976,520.003 2.32709,507.222 3.0946,494.489C 3.99078,480.612 0.0502625,466.659
1.30798,452.81C 2.94025,437.136 4.65631,421.417 4.74503,405.658C 4.58627,317.88 4.11758,230.103 3.931,142.325C
4.00595,126.066 5.42844,109.791 4.63071,93.5513C 4.26315,88.9108 2.9057,84.3932 1.69617,79.8981C
0.809357,76.6024 0,73.0779 0.599854,69.7181C 4.5654,48.0903 16.8726,26.9274 33.5068,12.5474C 42.0441,5.16699
53.6663,0 64.9515,0L 66.4785,12.2838'/>

<Path Canvas.Left='289.064' Canvas.Top='327.683' Fill='#44FFFFFF' Data='F1 M


76.6996,12.4589C 65.4143,12.4589 53.7922,17.6259 45.2549,25.0062C 28.6207,39.3863 16.3135,60.5492
12.3479,82.1769C 11.7481,85.5367 12.5574,89.0612 13.4442,92.3569C 14.6538,96.8521 16.0112,101.37
16.3788,106.01C 17.1765,122.25 15.754,138.524 15.6791,154.784C 15.8657,242.562 16.3344,330.339
16.4931,418.117C 16.4044,433.876 14.6883,449.595 13.0561,465.269C 11.7983,479.118 15.7389,493.071
14.8427,506.948C 14.0752,519.681 14.7478,532.462 15.007,545.215C 15.433,566.182 16.064,587.146
16.2504,608.117C 16.1436,615.389 15.769,622.716 14.3809,629.855C 13.5162,634.302 12.4534,638.813
12.6682,643.339C 12.8163,646.459 13.7275,649.695 15.4851,652.278L 15.4942,652.296L 15.6935,652.617L
15.9361,652.9L 16.4759,653.44L 15.9361,652.9C 8.5665,647.2 4.00824,637.509 2.69397,628.285C 1.74496,621.624
3.38004,614.844 3.4884,608.117C 3.21713,574.06 1.03,539.791 4.89609,505.953C 6.47821,492.149 2.1861,478.144
3.3494,464.298C 4.84473,448.94 6.4494,433.548 6.57904,418.117C 6.73779,330.339 7.20648,242.562
7.39307,154.784C 7.48846,138.818 8.4856,122.756 6.69336,106.891C 5.37247,98.0424 0,89.6409 0.724213,80.7239C
2.05685,66.7812 6.61194,52.968 13.1642,40.5888C 17.7834,31.8618 23.5879,23.4742 30.966,16.912C 42.7213,6.45673
59.3606,0 75.0919,0.166443C 75.3733,2.21667 75.6677,4.26514 75.9361,6.31708C 76.2036,8.36267 76.445,10.4116
76.6996,12.4589'/>

<Path Canvas.Left='277.36' Canvas.Top='315.281' Fill='#27FFFFFF' Data='F1 M


<Path Canvas.Left='277.36' Canvas.Top='315.281' Fill='#27FFFFFF' Data='F1 M
86.7958,12.5683C 71.0645,12.4019 54.4252,18.8586 42.6699,29.3139C 35.2917,35.8761 29.4873,44.2636
24.8681,52.9907C 18.3158,65.3698 13.7607,79.183 12.4281,93.1258C 11.7039,102.043 17.0764,110.444
18.3972,119.293C 20.1895,135.158 19.1924,151.22 19.097,167.186C 18.9104,254.964 18.4417,342.741
18.2829,430.519C 18.1533,445.95 16.5486,461.342 15.0533,476.7C 13.89,490.546 18.1821,504.551 16.6,518.355C
12.7339,552.193 14.921,586.462 15.1923,620.519C 15.0839,627.246 13.4489,634.026 14.3979,640.687C
15.7121,649.911 20.2704,659.602 27.64,665.302L 28.1798,665.842L 29.2596,666.922L 27.64,665.302C
21.5255,662.687 16.0143,658.508 11.3883,653.731C 7.70401,649.926 4.34698,645.546 2.42731,640.61C 0,634.368
2.29523,627.215 2.43008,620.519C 2.28488,599.586 1.30374,578.633 2.21432,557.719C 2.80304,544.198
4.52081,530.725 6.65314,517.36C 7.94345,510.674 6.83508,503.706 6.07349,496.939C 5.28238,489.909
4.78769,482.781 5.34641,475.73C 6.71002,460.688 8.19562,445.622 8.36871,430.519C 8.75754,358.553
9.1684,286.586 9.94885,214.624C 10.1204,198.809 10.7101,183.001 10.8108,167.186C 10.9251,151.5 11.6015,135.591
8.71164,120.173C 7.02731,115.479 4.54651,111.09 2.94635,106.366C 1.35837,101.678 0.560211,96.6163
0.804169,91.6729C 1.3949,75.1973 5.58997,58.4947 12.8936,43.7145C 16.9407,35.5245 21.9427,27.5813
28.3929,21.1122C 42.5106,6.953 64.6226,0 84.6164,0.20636C 85.4363,4.30945 86.1557,8.43335 86.7958,12.5683'/>

<Path Canvas.Left='265.035' Canvas.Top='302.643' Fill='#14FFFFFF' Data='F1 M


96.9417,12.8441C 76.9479,12.6378 54.8359,19.5908 40.7181,33.7499C 34.2679,40.2191 29.2659,48.1623
25.2188,56.3523C 17.9152,71.1324 13.7202,87.835 13.1294,104.311C 12.8855,109.254 13.6836,114.316
15.2716,119.004C 16.8718,123.728 19.3526,128.116 21.0369,132.811C 23.9268,148.229 23.2503,164.137
23.136,179.823C 23.0353,195.638 22.4456,211.447 22.2741,227.261C 21.4937,299.224 21.0828,371.191
20.694,443.157C 20.5209,458.26 19.0353,473.325 17.6717,488.367C 17.1129,495.419 17.6076,502.547
18.3987,509.576C 19.1603,516.344 20.2687,523.311 18.9784,529.998C 16.8461,543.363 15.1283,556.836
14.5396,570.357C 13.629,591.271 14.6101,612.224 14.7553,633.157C 14.6205,639.852 12.3253,647.006
14.7526,653.247C 16.6722,658.184 20.0293,662.564 23.7136,666.369C 28.3396,671.146 33.8508,675.325
39.9652,677.94L 41.5848,679.56L 42.6646,680.639L 39.9652,677.94C 30.2839,676.034 21.1083,671.007
13.4439,664.793C 10.7365,662.597 8.1752,660.183 5.94623,657.503C 4.29935,655.524 2.4556,653.506
1.71481,651.039C 0,645.33 1.36063,639.085 1.99313,633.157C 1.87259,612.241 0.734833,591.267 2.2912,570.408C
3.3317,556.464 6.31424,542.72 9.03159,529.003C 10.9694,523.181 9.52383,516.69 8.80978,510.596C 7.90936,502.91
7.38089,495.113 7.96481,487.397C 9.20184,472.672 10.5606,457.932 10.7798,443.157C 11.2338,392.755
12.0333,342.356 12.7198,291.956C 13.0136,270.392 13.0236,248.824 13.4133,227.261C 13.6992,211.444
14.6819,195.642 14.8499,179.823C 14.9811,164.402 15.4461,148.559 11.3513,133.691C 10.2486,133.675
9.81232,132.086 9.24573,131.139C 8.05481,129.151 6.96692,127.095 6.009,124.984C 2.89865,118.13 1.25388,110.38
1.50546,102.858C 1.36353,83.674 5.08316,63.8449 13.3646,46.5403C 17.4925,37.9148 22.6033,29.482
29.3935,22.749C 34.1408,18.0416 39.8787,14.3256 45.7804,11.1844C 60.3436,3.43292 77.5915,0 94.0843,0.400879C
94.5432,2.28015 95.0281,4.15326 95.4611,6.03864C 95.9807,8.30133 96.4481,10.5756 96.9417,12.8441'/>

<Path Canvas.Left='210.417' Canvas.Top='173.448' Data='F1 M 177.5,0C 275.531,0


355,34.6979 355,77.4999C 355,120.302 275.531,155 177.5,155C 79.4695,155 0,120.302 0,77.4999C 0,34.6979
79.4694,0 177.5,0'>
<Shape.Fill>
<!-- fade -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='379.983,137.286'
EndPoint='8.78339,60.4858'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FFFFFFFF' Offset='0'/>
<GradientStop Color='#FF646464' Offset='0.734375'/>
<GradientStop Color='#FF828282' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='223.655' Canvas.Top='192.845' Data='F1 M 165.093,0C 256.272,0


330.187,28.957 330.187,64.6772C 330.187,100.398 256.272,129.354 165.093,129.354C 73.9149,129.354 -6.5083e-
006,100.398 -6.5083e-006,64.6772C -6.5083e-006,28.957 73.9148,0 165.093,0'>
<Shape.Fill>
<!-- fade -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='163.01,139.309'
EndPoint='163.01,-140.771'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FFFFFFFF' Offset='0'/>
<GradientStop Color='#FF646464' Offset='0.734375'/>
<GradientStop Color='#FF828282' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='274' Canvas.Top='242' Fill='#FF000000' Data='F1 M 7.66674,42.0001C


11.2339,60.4561 37.9016,66.4291 56.2059,70.7072C 82.4072,76.8309 135.615,78.9291 129,44C 120.667,0 4.55874e-
006,2.33337 7.66674,42.0001'/>

<Path Canvas.Left='255.067' Canvas.Top='232.944' Fill='#345C5C5C' Data='F1 M


9.4162,70.7071C 7.76895,69.0609 5.82782,67.6457 4.53439,65.709C 1.67276,61.4244 0,55.8206 0.747803,50.7228C
2.77301,40.1859 7.94012,29.0883 16.5421,22.6746C 27.4116,15.0288 40.9852,10.9396 54.2074,9.60706C
63.254,8.73438 72.5876,7.15979 80.6532,2.97064C 82.398,2.06439 84.2077,1.2207 85.7491,0L 86.2227,0.436462C
77.7476,7.70923 65.4153,9.54169 54.2976,10.5991C 41.2442,11.8957 27.8148,15.8743 17.0984,23.4396C
8.69409,29.7304 3.58588,40.5558 1.62186,50.8685C 0.615143,57.8 4.68347,65.4359 9.82288,70.259L
9.4162,70.7071'/>

<Path Canvas.Left='255.68' Canvas.Top='233.38' Fill='#675C5C5C' Data='F1 M


9.20969,69.8226C 4.09637,65.0159 0,57.377 1.00867,50.432C 2.97269,40.1194 8.0809,29.2939 16.4852,23.0031C
27.2016,15.4379 40.631,11.4592 53.6844,10.1626C 64.8021,9.10522 77.1344,7.27277 85.6096,0L 86.083,0.434265C
77.7522,8.138 65.072,10.0961 53.7746,11.1545C 40.8901,12.4161 27.6046,16.2832 17.0416,23.7681C 8.83499,29.9363
3.78571,40.4894 1.88269,50.5777C 0.920227,57.2797 4.83594,64.5591 9.61636,69.3745L 9.20969,69.8226'/>

<Path Canvas.Left='256.6' Canvas.Top='233.814' Fill='#B35C5C5C' Data='F1 M


8.69678,68.9402C 3.92325,64.1323 0,56.8499 0.963104,50.1434C 2.86612,40.0552 7.91541,29.502 16.122,23.3338C
26.685,15.8489 39.9705,11.9818 52.855,10.7203C 64.1524,9.6618 76.8326,7.70374 85.1634,0L 85.4002,0.216309L
85.6365,0.432007L 85.6262,0.442322C 77.4444,8.55664 64.4196,10.6531 52.9452,11.7122C 40.2296,12.9387
27.0886,16.6949 16.6783,24.0987C 8.66989,30.1447 3.67944,40.4253 1.83713,50.2891C 0.920319,56.7577
4.67725,63.687 9.10394,68.4919L 8.90012,68.7162L 8.69678,68.9402'/>

<Path Canvas.Left='257.52' Canvas.Top='234.246' Fill='#675C5C5C' Data='F1 M


8.18362,68.0599C 3.75693,63.2549 0,56.3257 0.916809,49.8571C 2.75912,39.9933 7.74957,29.7127 15.7579,23.6667C
26.1682,16.2629 39.3093,12.5067 52.0249,11.2802C 63.4993,10.2211 76.524,8.12463 84.7059,0.0103149L 84.7162,0L
85.1891,0.43158L 85.1581,0.462585C 83.3785,2.34833 81.4954,4.22565 79.2504,5.52295C 71.1802,10.1864
61.3975,11.4283 52.1151,12.2722C 39.5684,13.4637 26.571,17.1078 16.3143,24.4316C 8.50427,30.3557
3.57245,40.3635 1.79083,50.0027C 0.920807,56.2345 4.51434,62.8198 8.59283,67.6111L 8.18362,68.0599'/>

<Path Canvas.Left='258.441' Canvas.Top='234.678' Fill='#345C5C5C' Data='F1 M


7.67203,67.1796C 3.59354,62.3882 0,55.8029 0.870026,49.5712C 2.65164,39.9319 7.58347,29.9241 15.3935,24.0001C
25.6502,16.6763 38.6476,13.0322 51.1942,11.8406C 60.4767,10.9967 70.2594,9.75482 78.3296,5.09137C
80.5746,3.79407 82.4577,1.91675 84.2373,0.0310059L 84.2683,0L 84.7412,0.431519L 84.6895,0.483215C
83.1657,2.20294 81.6686,4.0105 79.7861,5.328C 71.7372,10.9612 61.0696,11.9559 51.2845,12.8326C 38.9066,13.9887
26.0529,17.5211 15.9498,24.765C 8.33865,30.5676 3.46509,40.3021 1.74408,49.7169C 0.921814,55.7128
4.35425,61.9637 8.08331,66.7304L 7.67203,67.1796'/>

<Path Canvas.Left='402.742' Canvas.Top='254.672' Fill='#345C5C5C' Data='F1 M


40.483,0.427795C 37.7426,1.99316 35.4572,4.24683 32.9736,6.19415C 29.7007,8.76038 26.0635,11.8786
25.1887,15.9446C 23.9246,23.7479 26.5791,31.6937 27.2018,39.5743C 27.5235,43.6462 27.083,47.892
25.7018,51.736C 24.6708,54.2384 23.4313,56.7329 21.6555,58.7754C 19.5966,61.1436 16.9563,62.9433
14.4685,64.856C 11.9845,66.7996 9.56293,69.0528 6.58258,70.085C 4.57892,70.7789 2.34875,70.4882
0.229736,70.412L 0,69.4677C 2.2912,69.3365 4.69861,69.3543 6.80994,68.4549C 9.34406,67.3754 11.3893,65.3834
13.5575,63.6846C 15.9678,61.8284 18.5349,60.0926 20.5305,57.7964C 22.1973,55.8787 23.3512,53.5322
24.3242,51.1849C 28.3499,40.0659 22.0579,27.3722 24.0162,15.7101C 24.9869,11.3704 28.8337,7.97296
32.4296,5.35669C 34.9719,3.50696 37.4631,1.55988 40.1929,0L 40.483,0.427795'/>

<Path Canvas.Left='402.514' Canvas.Top='254.245' Fill='#675C5C5C' Data='F1 M


40.4213,0.427734C 37.6916,1.98761 35.2003,3.93469 32.658,5.78442C 29.0621,8.4007 25.2153,11.7981
24.2447,16.1378C 22.2863,27.7999 28.5784,40.4937 24.5526,51.6127C 23.5797,53.9599 22.4257,56.3064
20.759,58.2242C 18.7634,60.5203 16.1962,62.2562 13.7859,64.1124C 11.6177,65.8112 9.57251,67.8031
7.03839,68.8826C 4.92706,69.782 2.51965,69.7643 0.228455,69.8954L 0,68.9563C 2.17621,68.6239 4.43665,68.4391
6.4552,67.5605C 8.8725,66.5085 10.8007,64.5683 12.8749,62.9411C 15.2078,61.1414 17.7015,59.4693
19.6339,57.2452C 21.1918,55.4523 22.2604,53.2537 23.1749,51.0616C 27.1958,40.0535 21.0718,27.4508
23.0723,15.9033C 23.8008,12.7408 25.9355,9.87164 28.389,7.74738C 31.929,4.68219 36.0797,2.38708 40.1312,0L
40.4213,0.427734'/>

<Path Canvas.Left='402.286' Canvas.Top='253.816' Fill='#B35C5C5C' Data='F1 M


40.3586,0.428162C 36.3182,2.80804 32.1615,5.10608 28.6165,8.17554C 26.163,10.2998 24.0283,13.169
23.2997,16.3315C 21.2993,27.879 27.4233,40.4816 23.4024,51.4897C 22.4879,53.6819 21.4193,55.8804
19.8614,57.6734C 17.929,59.8975 15.4352,61.5696 13.1024,63.3693C 11.0282,64.9965 9.09998,66.9366
6.68268,67.9887C 4.66412,68.8672 2.40369,69.0521 0.227478,69.3845L 0.113647,68.9167L 0,68.4498L
0.0194702,68.4459C 2.24445,67.8875 4.57422,67.504 6.59711,66.4222C 8.65765,65.3203 10.3538,63.6413
12.1914,62.198C 14.4468,60.455 16.8674,58.8467 18.7364,56.6945C 20.1852,55.0262 21.1688,52.9759
22.0247,50.9387C 26.045,40.0428 20.0918,27.5312 22.1274,16.097C 22.815,13.1797 24.5266,10.4034
26.7319,8.37366C 30.5941,4.81891 35.4528,2.49988 40.0684,0L 40.2136,0.214233L 40.3586,0.428162'/>

<Path Canvas.Left='402.059' Canvas.Top='253.386' Fill='#675C5C5C' Data='F1 M


40.2956,0.429993C 35.68,2.92987 30.8214,5.2489 26.9591,8.80365C 24.7538,10.8334 23.0422,13.6097
22.3546,16.527C 20.319,27.9612 26.2723,40.4728 22.252,51.3687C 21.3961,53.4059 20.4125,55.4562
18.9636,57.1245C 17.0946,59.2767 14.6741,60.8849 12.4186,62.628C 10.581,64.0713 8.88489,65.7502
6.82434,66.8522C 4.80145,67.934 2.47168,68.3175 0.246704,68.8759L 0.227234,68.8798L 0,67.9457L
0.0583496,67.9341C 2.11133,67.2087 4.2442,66.6268 6.14685,65.5681C 8.11469,64.4731 9.73743,62.8487
11.5076,61.4567C 13.6859,59.7706 16.0328,58.2258 17.8386,56.1456C 19.1785,54.602 20.0775,52.7 20.8743,50.8176C
24.9,40.0358 19.1173,27.6146 21.1822,16.2925C 22.0583,12.645 24.5038,9.28986 27.4122,6.92072C 31.1257,3.89575
35.7121,2.12506 40.0044,0L 40.2956,0.429993'/>

<Path Canvas.Left='401.832' Canvas.Top='252.954' Fill='#345C5C5C' Data='F1 M


40.2317,0.432007C 35.9394,2.55707 31.353,4.32776 27.6395,7.35272C 24.7311,9.72186 22.2856,13.077
21.4095,16.7245C 19.3446,28.0466 25.1273,40.4678 21.1016,51.2496C 20.3047,53.132 19.4058,55.034
18.0659,56.5776C 16.2601,58.6578 13.9131,60.2026 11.7349,61.8887C 9.96472,63.2807 8.34198,64.9052
6.37415,66.0001C 4.4715,67.0588 2.33862,67.6407 0.285645,68.3661L 0.227295,68.3777L 0,67.4437L
0.09729,67.4243C 1.98065,66.5573 3.91138,65.7702 5.69672,64.7161C 7.56305,63.6141 9.12103,62.0582
10.8239,60.7174C 12.925,59.0883 15.1987,57.607 16.9409,55.5986C 18.1718,54.1797 18.9866,52.4262
19.7239,50.6985C 23.762,40.0333 18.148,27.7012 20.2371,16.49C 21.186,12.5998 23.7858,8.99768 26.9238,6.51038C
30.7255,3.49707 35.5151,1.98914 39.9396,0L 40.2317,0.432007'/>

<Path Canvas.Left='210.667' Canvas.Top='268' Fill='#C0273B6E' Data='F1 M 0,0C


1.78418,5.95642 4.82239,11.6618 8.77771,16.4595C 13.3548,22.2748 19.3472,26.9496 25.4955,31.0687C
35.7069,38.1401 47.3544,43.1534 59.1278,47.1112C 76.5842,53.5378 94.9361,57.6492 113.342,60.3441C
133.106,63.7744 153.19,65.6785 173.245,66.0901C 193.429,66.8603 213.769,65.9813 233.77,63.1609C
242.971,62.1271 252.139,60.6179 261.159,58.5264C 270.485,56.3208 279.759,53.8448 288.877,50.8943C
301.182,47.1774 313.376,42.4536 324.335,35.737C 332.329,31.076 339.92,25.2996 345.855,18.2004C 349.858,13.6091
353.274,8.44763 356,3L 356,3C 354.169,9.2088 351.586,15.2778 348.143,20.759C 342.728,29.0021 335.677,36.2894
327.853,42.2941C 316.432,50.9689 303.503,57.6978 290.296,63.2896C 281.959,66.6082 273.438,69.468
264.867,72.1246C 254.949,75.1498 244.806,77.4824 234.592,79.2724C 213.369,82.582 191.762,83.6537
170.284,83.3809C 148.827,82.5825 127.339,80.2187 106.303,75.9114C 87.462,71.5878 68.7829,65.7867
51.2914,57.5563C 39.94,51.9009 29.0087,44.9984 19.6233,36.4688C 13.9898,30.9747 9.20233,24.4868
5.54321,17.5203C 2.78418,12.0515 0.916901,6.0564 0,0'/>

<Path Canvas.Left='229.506' Canvas.Top='187.602' Fill='#14FFFFFF' Data='F1 M


12.3405,100.804C 12.2028,99.9782 12.0794,99.1497 11.9275,98.3263C 11.6325,96.7277 10.0484,95.6653
8.97247,94.4467C 7.13397,92.3646 5.30698,90.2467 3.80005,87.9133C 1.12283,83.7678 0,78.4729 0.237732,73.5438C
1.17871,59.3197 9.87411,45.736 19.8228,35.5266C 32.0301,23.7631 49.1607,18.1021 65.1416,12.4444C
82.8957,6.15894 101.533,1.42511 120.336,0.363342C 126.771,0 133.186,1.38654 139.607,1.93073C 146.014,2.47363
152.388,3.38513 158.74,4.38403C 161.866,4.87567 165.058,4.97748 168.146,5.66748C 175.81,7.3797 182.015,13.0674
189.193,16.2543L 190.101,17.4304C 182.683,15.3032 175.697,11.4503 168.057,10.3573C 158.763,9.02753
149.349,8.61005 139.964,8.32709C 133.683,8.1377 127.382,7.49744 121.115,7.96295C 105.405,9.12982
89.7888,12.2482 74.6554,16.6235C 66.4798,18.9872 58.4211,21.771 50.4749,24.8181C 40.9996,28.4515
31.4367,33.0066 24.0915,40.0087C 15.0522,49.1422 6.89114,61.2039 5.94043,74.019C 5.69522,78.6554
7.19516,83.4874 9.6019,87.4578C 11.9089,91.2637 15.2704,94.7853 16.002,99.1752L 12.3405,100.804'/>

<Path Canvas.Left='235.201' Canvas.Top='195.099' Fill='#27FFFFFF' Data='F1 M


10.3068,91.6778C 9.57516,87.2879 6.21365,83.7662 3.90668,79.9604C 1.49994,75.99 0,71.158 0.245209,66.5215C
1.19592,53.7065 9.35703,41.6448 18.3962,32.5112C 25.7415,25.5092 35.3044,20.954 44.7797,17.3206C
52.7259,14.2736 60.7846,11.4898 68.9602,9.1261C 84.0936,4.75079 99.7096,1.63239 115.419,0.465515C 121.687,0
127.987,0.640259 134.269,0.829651C 143.654,1.11261 153.068,1.53009 162.362,2.85986C 170.001,3.95282
176.988,7.80579 184.406,9.93298L 185.331,10.8536C 177.655,9.68298 170.023,8.02112 162.273,7.54968C
134.334,5.85022 105.86,7.90143 78.5518,14.046C 67.8628,16.451 57.2758,19.4722 47.0229,23.3342C 38.3116,26.6155
29.4501,30.6204 22.6649,36.9933C 14.5374,45.0567 6.92709,55.59 5.94791,66.9968C 5.75012,70.2246
6.60532,73.5515 7.96188,76.4871C 10.0359,80.9752 13.1557,85.172 13.9684,90.0488L 10.3068,91.6778'/>

<Path Canvas.Left='240.951' Canvas.Top='200.949' Fill='#44FFFFFF' Data='F1 M


8.21829,84.1986C 7.40558,79.3218 4.28574,75.125 2.21176,70.6369C 0.855194,67.7013 0,64.3744 0.197784,61.1465C
1.17697,49.7397 8.78729,39.2065 16.9148,31.1431C 23.7,24.7701 32.5615,20.7653 41.2728,17.4839C 51.5257,13.6219
62.1127,10.6008 72.8016,8.19574C 100.11,2.05121 128.584,0 156.523,1.69946C 164.273,2.1709 171.905,3.83276
179.581,5.00342L 180.049,5.38416L 180.519,5.74359L 180.019,5.6944C 172.159,5.41504 164.297,6.20532
156.434,6.38916C 133.526,6.92487 110.631,9.3053 87.9969,12.8813C 73.6531,15.1475 59.2618,17.9296
45.5661,22.7574C 36.8989,25.8126 27.95,29.4067 21.1834,35.6252C 13.9698,42.6257 6.94266,51.6239
5.90036,61.6218C 5.32037,68.8407 10.6239,75.3776 11.8734,82.5111C 10.6739,83.1127 9.4444,83.6531
8.21829,84.1986'/>
8.21829,84.1986'/>

<Path Canvas.Left='246.271' Canvas.Top='206.364' Fill='#27FFFFFF' Data='F1 M


6.55307,77.0961C 5.30356,69.9625 0,63.4257 0.579987,56.2067C 1.62228,46.2089 8.64941,37.2107 15.863,30.2101C
22.6296,23.9917 31.5785,20.3976 40.2458,17.3423C 53.9414,12.5146 68.3328,9.73248 82.6765,7.46631C
105.311,3.89026 128.205,1.50983 151.114,0.974121C 158.977,0.790283 166.838,0 174.698,0.279358L
175.198,0.328552L 176.137,1.04742L 174.637,0.899902C 166.632,1.52203 159.007,4.78876 151.025,5.66394C
147.073,6.09729 143.088,6.2066 139.144,6.70996C 129.243,7.97369 119.427,9.83209 109.592,11.5392C
103.868,12.5328 98.06,12.9665 92.3038,13.7551C 77.6813,15.7583 62.9789,17.7339 48.7108,21.5093C 43.4283,22.907
38.2522,24.7574 33.2463,26.9485C 28.5955,28.9841 23.9294,31.3232 20.1317,34.6923C 13.8346,40.6408 7.46097,48.1
6.28268,56.6819C 5.87811,59.0777 6.74097,61.5414 7.35971,63.8909C 8.3349,67.594 9.48495,71.2618
10.176,75.0283C 8.99329,75.7595 7.78494,76.4511 6.55307,77.0961'/>

<Path Canvas.Left='252.149' Canvas.Top='207.264' Fill='#14FFFFFF' Data='F1 M


4.29788,74.1284C 3.60684,70.3619 2.45679,66.6941 1.4816,62.991C 0.862854,60.6415 0,58.1778 0.404572,55.782C
1.58286,47.2001 7.95651,39.7409 14.2535,33.7924C 18.0513,30.4233 22.7174,28.0842 27.3682,26.0486C
32.3741,23.8575 37.5501,22.0071 42.8327,20.6094C 57.1008,16.834 71.8032,14.8584 86.4257,12.8552C
92.1819,12.0666 97.9898,11.6329 103.714,10.6393C 113.548,8.93219 123.365,7.07379 133.266,5.81006C
137.21,5.3067 141.195,5.19739 145.147,4.76404C 153.128,3.88885 160.754,0.622131 168.759,0L 170.259,0.147522L
171.198,0.866516L 168.698,0.620605C 161.432,1.99591 154.949,6.07831 147.987,8.57153C 145.19,9.57324
142.147,9.67749 139.211,10.1299C 136.261,10.5843 133.337,11.1998 130.421,11.8364C 125.57,12.8956
120.659,13.7015 115.851,14.9438C 111.09,16.1741 106.445,17.9526 101.584,18.6987C 85.6983,21.137
69.6291,22.3375 53.7934,25.0809C 46.2281,26.3916 38.6974,28.2964 31.5818,31.1808C 26.9907,33.0418
22.3353,35.1119 18.5222,38.2745C 13.1435,43.1863 7.63449,49.1351 6.10727,56.2573C 6.05072,55.8453
5.79651,57.0471 5.78659,57.4628C 5.75903,58.6177 5.86258,59.7764 6.02448,60.9202C 6.53555,64.5313
7.34427,68.0946 7.91342,71.6969L 6.43179,72.7293L 4.29788,74.1284'/>

<Path Canvas.Left='538.433' Canvas.Top='332.88' Fill='#22353838' Data='F1 M


21.4432,34.0718C 22.0251,34.1408 22.6031,34.2687 23.1591,34.4532C 23.8205,34.5854 24.5145,34.2079
25.0945,33.8638C 25.3192,33.7304 25.5771,33.6391 25.837,33.6121C 26.2126,33.573 26.9282,33.7969 26.828,34.161C
26.549,35.1749 24.7775,34.7581 23.7261,34.7364C 21.6256,34.6929 19.529,34.5336 17.4317,34.4103C 18.242,36.3724
19.0522,38.4219 20.4546,40.0156C 22.4837,42.3217 26.6615,43.311 29.4491,42.0206C 32.125,40.7817 33.8986,37.399
34.0307,34.4532C 34.1635,31.1389 33.1535,27.7501 31.659,24.7888C 30.417,22.3279 28.5311,20.1289
27.8141,17.4672C 27.9153,17.0933 27.7288,16.6967 27.664,16.3146C 28.5946,14.3097 28.6655,11.8974
28.3127,9.71533C 27.4704,7.81097 26.2593,6.03839 24.8115,4.54175C 21.6753,1.40906 15.9319,0 11.8266,1.67206C
7.66568,3.36676 4.3132,8.43506 4.41068,12.9268C 4.45352,14.9016 5.03281,16.8469 5.66489,18.7183C
5.99258,19.6884 7.02872,20.7206 6.59238,21.647C 6.48782,21.8689 6.47061,21.1707 6.43527,20.928C 6.31729,22.657
6.21951,24.3878 6.16318,26.1199L 6.07474,29.4532L 5.98569,32.7866C 5.66141,51.1691 4.89035,69.5532
3.52866,87.8881C 2.65231,113.89 1.08994,139.864 0.141022,165.863C 3.05176e-005,209.67 1.08298,253.473
1.76761,297.274C 2.50937,308.014 3.24979,318.754 3.98544,329.494C 4.38174,338.21 4.77487,346.925
5.16098,355.641C 7.71695,382.481 10.2887,409.318 12.7813,436.163C 14.0919,441.239 15.3963,446.316
16.6962,451.395C 19.7157,458.475 22.7192,465.563 25.7113,472.656C 28.1448,466.256 30.5756,459.856
33.0063,453.455C 33.4361,448.075 33.8642,442.694 34.2893,437.313C 35.0033,434.026 35.7171,430.738
36.4304,427.451C 37.885,408.065 39.312,388.678 40.6392,369.283C 41.278,340.131 41.9057,310.978
42.4484,281.824C 41.7338,241.404 41.2502,200.968 39.4547,160.582C 38.3814,149.805 37.2306,139.037
36.1065,128.266C 35.4395,119.598 34.783,110.93 34.1613,102.259C 33.458,96.651 32.7818,91.0398 32.139,85.4249C
31.5704,76.6905 31.0622,67.9518 30.641,59.2091C 29.9325,54.7943 29.3084,50.366 28.697,45.9366C 28.5258,41.5539
28.368,37.1705 28.2324,32.7866L 28.1624,29.4532L 28.093,26.1199L 28.084,25.533L 28.0844,25.4731C
27.8134,23.0898 27.7384,20.6765 27.2752,18.323C 26.9494,16.4257 26.1225,14.6295 25.2429,12.9172C
24.9023,12.254 24.8703,11.1418 24.1452,10.9686C 23.903,10.9108 24.1836,11.4653 24.2099,11.7129C
24.2633,12.2152 24.271,12.7247 24.2307,13.2283C 24.1144,14.6841 23.571,16.1587 22.7068,17.336C 21.2884,19.2681
18.722,20.6009 16.3257,20.6502C 14.3673,20.6905 12.1105,20.0011 10.8591,18.4941C 10.7615,18.3166
10.5547,17.9453 10.7512,17.8961C 11.4143,17.7299 11.5298,19.0303 11.8018,19.6575C 12.428,21.1014
12.982,22.5845 13.7489,23.9589C 15.3853,26.6719 17.6976,28.9234 19.8621,31.2372C 20.4891,32.1143
21.1311,33.0279 21.4432,34.0718'/>

<Path Canvas.Left='514.533' Canvas.Top='301.04' Fill='#1E353838' Data='F1 M


30.4951,52.3476C 34.2448,51.7693 37.9751,50.8948 41.5388,49.593C 38.6633,46.4369 36.4412,42.6527
34.744,38.7348L 35.6184,36.9927L 35.9899,36.2909C 33.9624,30.7733 32.2904,25.1223 30.8189,19.4311L
30.4466,17.2545C 29.6079,14.6197 28.1192,11.9946 28.3192,9.23676C 28.2727,8.88007 28.7914,9.80585
28.8922,10.1511C 29.1452,11.0182 29.2776,11.9231 29.3333,12.8246C 29.4996,15.5193 28.865,18.3425
27.6288,20.7426C 25.958,23.9865 23.0155,26.8138 19.6604,28.2482C 16.2256,29.7166 12.0584,29.9907
8.47507,28.9357C 7.13028,28.5799 5.83005,27.9724 4.694,27.1696C 4.2886,26.8831 3.90372,26.5679
3.52475,26.2474C 3.33932,26.0905 3.13925,25.7217 2.92429,25.8347C 2.48093,26.0677 3.02072,26.8391
3.17056,27.317C 3.37717,27.976 3.58835,28.6338 3.81534,29.286C 4.56619,31.4432 5.58713,33.5165 6.78391,35.462C
9.91843,41.4283 13.0464,47.3987 16.0854,53.4142C 18.7297,58.7632 21.3066,64.1491 24.1384,69.4013C
24.0548,69.2957 23.9917,69.0663 23.8629,69.1058C 23.4782,69.2236 24.1084,69.8729 24.258,70.2464C
26.9104,75.5622 29.6632,81.1735 34.1414,85.0771C 37.4694,87.978 41.7433,90.0399 46.0959,90.7787C
50.8088,91.5787 55.9785,90.9087 60.3122,88.891C 64.6302,86.8806 68.4738,83.4037 70.9196,79.3165C
73.2271,75.4603 74.3696,70.787 74.4054,66.2933C 74.354,60.472 72.663,54.5051 69.7639,49.4567C 68.9309,48.0063
73.2271,75.4603 74.3696,70.787 74.4054,66.2933C 74.354,60.472 72.663,54.5051 69.7639,49.4567C 68.9309,48.0063
68.0221,46.5981 67.0627,45.2281C 66.8385,44.9079 66.6103,44.5905 66.3812,44.2737C 66.0674,43.8398
65.7502,43.4082 65.4339,42.9761C 65.3501,42.8617 65.2658,42.7476 65.1808,42.6341C 65.1582,42.6039
65.1481,42.538 65.111,42.545C 64.938,42.5775 65.2226,42.8791 65.2899,43.0417C 65.4314,43.3689 65.5688,43.6989
65.6788,44.0379C 65.7282,44.1903 65.8899,44.639 65.8094,44.5005C 64.7774,42.7248 64.6494,40.554
63.8916,38.6451C 62.3413,34.7405 59.9728,31.0624 57.0035,28.0903C 53.9137,25.0747 49.9488,22.6815
45.7495,21.678C 41.7254,20.7164 37.312,20.813 33.3407,21.9735C 25.4306,24.2849 18.3331,32.3696
16.9668,40.4963C 16.3319,44.2731 16.6344,48.3068 17.7984,51.9554C 18.3182,53.5849 18.4561,55.5234
19.6624,56.7361C 19.8846,56.9594 19.5294,56.1202 19.4671,55.8115C 19.3569,55.2649 19.2712,54.7131
19.2023,54.1598C 19.1994,54.1133 19.196,54.0668 19.1935,54.0202C 19.1913,53.9777 19.1894,53.9351
19.188,53.8925C 19.1732,53.4596 19.1473,53.4783 19.2061,53.4903C 19.8319,53.6175 19.2597,54.7669
19.2579,55.4055C 19.2568,55.7873 19.2495,56.1691 19.2499,56.5508C 19.2504,57.0206 19.2571,57.4902
19.2607,57.96L 19.3724,61.2933L 19.477,64.6266C 19.6562,69.8059 19.8449,74.985 19.9746,80.1658C
20.6835,99.5374 19.3011,118.943 18.0615,138.288C 16.6632,168 15.0567,197.717 14.7163,227.461C 15.1405,263.031
15.8682,298.598 16.5848,334.164C 18.4066,370.915 20.1222,407.672 21.925,444.424C 24.409,471.957
26.9032,499.491 28.9863,527.057C 29.6651,531.912 30.3372,536.769 31.0032,541.627C 32.4626,552.848
33.8961,564.073 35.2916,575.303C 37.9953,586.519 40.7721,597.722 43.1458,609.012L 44.8123,608.874L
54.0852,608.094C 56.0627,601.398 57.2394,594.488 58.5698,587.635L 59.0612,587.213L 60.3407,586.113C
61.3484,578.465 62.3062,570.811 63.2226,563.152L 64.2284,561.187L 64.9732,559.726C 66.9309,539.163
68.7049,518.582 70.6106,498.014C 70.9775,490.024 71.3437,482.035 71.7036,474.045C 72.8469,450.16
73.9506,426.274 74.8664,402.379C 75.2613,369.664 75.6731,336.949 75.9369,304.232C 74.9052,265.178
74.2086,226.09 71.5941,187.11C 68.6016,154.048 64.6779,121.032 63.3054,87.8633C 62.7922,80.1321
62.7507,72.3747 62.6921,64.6266L 62.7016,61.2933L 62.7157,57.96C 62.805,54.8864 62.9427,51.7909
62.5907,48.7363C 62.3045,46.5587 61.7426,44.4117 61.0241,42.3363C 60.6372,41.2189 59.9998,40.1678
59.8214,38.9988C 59.7739,38.6871 60.0065,39.602 60.0825,39.908C 60.2463,40.5673 60.3669,41.2379
60.4617,41.9106C 60.7422,43.8994 60.6745,45.9542 60.341,47.9348C 59.4311,53.3373 55.8866,58.6614
51.3033,61.6625C 47.3564,64.2469 42.1945,65.3972 37.5104,64.8353C 33.2336,64.3223 28.9392,62.2462
25.8697,59.2241C 24.4317,57.7697 23.2895,55.9694 22.5553,54.0604L 22.5697,54.1089C 22.6331,54.3461
22.696,54.5835 22.7585,54.8209C 22.9342,55.4881 23.1073,56.1561 23.3008,56.8184C 23.7776,58.4511
24.3673,60.0557 25.0708,61.6044C 26.0859,63.7443 27.291,65.8007 28.6342,67.7513C 29.3999,68.8634
29.8174,70.3577 30.9703,71.0604C 31.1016,71.1404 30.8639,70.7718 30.8087,70.6283C 30.6799,70.2932
30.568,69.9512 30.474,69.6047C 30.1831,68.5315 30.0598,67.4052 30.0711,66.2933C 30.1482,61.9102
31.8535,57.3047 34.7261,53.9933C 37.9769,50.2458 42.9078,47.5265 47.8347,46.9459C 51.6667,46.4944
55.7914,47.2226 59.232,48.969C 61.1357,49.9352 62.9213,51.2152 64.3923,52.7624C 64.8539,53.2479
65.2956,53.7548 65.6964,54.2916C 65.9012,54.5658 66.4857,55.4068 66.2591,55.1504C 64.0281,52.6265
62.9389,49.2838 61.1137,46.4526C 60.8486,46.0621 60.5783,45.6752 60.3051,45.2903C 56.3957,40.5719
52.3397,35.9761 48.2799,31.3864L 46.5161,29.428L 44.8905,27.6393C 41.3501,23.7719 37.7516,19.9581
34.1626,16.1357C 34.0426,16.5845 33.3736,15.6052 33.1095,15.223C 32.7566,14.7123 32.4189,14.1913
32.0804,13.671C 31.2823,12.4439 30.5269,11.1878 29.6829,9.99188C 26.8123,5.9245 22.5853,2.33911
17.8102,0.931458C 14.6711,0 11.0069,0.0841064 7.9971,1.37341C 5.18729,2.57703 2.72787,5.01599 1.4473,7.79156C
0.330048,10.2131 3.05176e-005,13.1066 0.468353,15.7319C 0.978241,18.59 2.51248,21.2363 4.18796,23.6072C
5.07822,24.8669 5.70261,26.4297 7.00143,27.3024C 8.73148,30.188 10.4896,33.0583 12.3285,35.8758C
14.9512,37.4676 17.6291,38.9717 20.3518,40.3857C 22.1541,43.1121 24.1667,45.7035 26.3064,48.1978C
27.6524,49.6299 29.0355,51.0314 30.4951,52.3476'/>

<Path Canvas.Left='512.513' Canvas.Top='299.052' Fill='#1A353838' Data='F1 M


44.3448,61.106L 45.891,53.1749L 45.9276,53.036C 42.3353,48.4838 40.4018,42.6124 39.4414,36.8936C
37.4282,30.8375 35.8336,24.6449 34.3341,18.4417C 33.7685,16.863 33.1371,15.3079 32.5951,13.721C
32.3889,13.1175 32.185,12.5132 31.9945,11.9045C 31.838,11.4045 31.2738,10.6013 31.7358,10.3543C
31.9378,10.2464 32.0434,10.7025 32.1385,10.9108C 32.3371,11.3455 32.4674,11.8101 32.5841,12.2736C
32.888,13.4796 33.0031,14.7411 32.9726,15.9844C 32.878,19.8268 31.3316,23.7948 28.9012,26.7724C
24.7341,31.8775 16.302,34.3253 9.97458,32.4839C 8.41464,32.0805 6.90561,31.3831 5.58499,30.46C 4.82761,29.9306
4.26059,29.0691 3.37979,28.7731C 2.94327,28.7897 3.43411,29.6544 3.56894,30.0699C 3.78305,30.7297
4.00211,31.3881 4.23691,32.0408C 5.04257,34.2806 6.12656,36.4303 7.38766,38.4492C 10.577,44.3668
13.7625,50.287 16.8625,56.252L 17.1151,56.7484C 19.8871,61.786 22.5948,66.8625 25.5417,71.7999C 25.457,71.6817
25.4154,71.4989 25.2776,71.4528C 24.9951,71.3584 25.5111,72.0007 25.6369,72.2706C 25.7657,72.547
25.8933,72.8239 26.0238,73.0995C 26.3573,73.8046 26.6871,74.5115 27.0288,75.2126C 27.9297,77.061
28.8575,78.9007 29.9103,80.6669C 33.4829,86.6599 39.8266,91.6955 46.6244,93.2665C 53.5994,94.8784
61.9546,93.0002 67.5824,88.5757C 73.4707,83.9464 77.1446,75.7706 77.2283,68.2809C 77.2049,62.4897
75.583,56.5685 72.8315,51.4727C 71.9391,49.8198 70.9297,48.2296 69.8727,46.6768C 69.2592,45.7755
68.7633,44.7759 68.0084,43.9894C 67.8581,43.8328 68.1935,44.3822 68.2828,44.5801C 68.4396,44.9324
68.5915,45.2875 68.718,45.6517C 68.782,45.8361 68.9543,46.3958 68.8903,46.2114C 68.2029,44.231 67.7679,42.1643
67.0043,40.212C 65.4139,36.1458 62.9602,32.3158 59.883,29.2181C 56.6443,26.0437 52.4751,23.5334
48.0644,22.4789C 43.8307,21.4667 39.1873,21.5683 35.0089,22.7891C 26.912,25.1547 19.6975,33.2163
17.9319,41.4649C 17.0632,45.5235 17.3519,49.9183 18.5143,53.9028C 18.817,54.9408 19.1803,55.9614
19.571,56.9697C 19.7398,57.4055 19.9128,57.8396 20.0855,58.2739C 20.1939,58.5467 20.4871,59.3724
20.4295,59.0846C 20.2676,58.1589 20.0639,57.2392 19.9506,56.3063C 19.9389,56.04 19.7797,55.6866
20.0216,55.5364C 20.0466,55.6417 20.0558,55.7507 20.06,55.8589C 20.0793,56.3547 20.0846,56.8511
20.0919,57.3473C 20.0976,57.7345 20.094,58.1218 20.0989,58.509C 20.1049,58.9885 20.1161,59.468
20.1247,59.9475L 20.2969,63.2808L 20.4604,66.6142C 20.8573,74.5136 21.4154,82.4149 21.3882,90.3242C
20.1247,59.9475L 20.2969,63.2808L 20.4604,66.6142C 20.8573,74.5136 21.4154,82.4149 21.3882,90.3242C
21.3321,106.646 20.3794,122.959 19.3108,139.246C 18.3644,160.273 17.0873,181.288 16.5278,202.329C
15.8523,227.732 16.009,253.151 15.9595,278.563C 17.2342,318.153 18.7055,357.736 19.9801,397.325C
20.5016,402.875 21.0196,408.424 21.5441,413.974C 21.9451,422.704 22.3569,431.434 22.7675,440.164C
24.6634,465.401 26.5711,490.638 28.2382,515.891C 29.0255,520.324 29.8043,524.758 30.5761,529.194C
30.9525,536.126 31.3092,543.06 31.6567,549.994C 34.3253,567.1 37.0077,584.206 39.382,601.356C 42.2582,608.608
45.7745,615.777 47.0296,623.477L 47.4939,626.125L 48.911,623.782C 53.0008,616.74 57.6272,610.008
61.4856,602.837C 62.138,597.097 62.7442,591.351 63.2763,585.599C 64.678,579.591 66.0481,573.576
67.3951,567.555C 70.2687,536.014 72.7399,504.437 75.4205,472.879C 75.7421,461.494 76.0512,450.108
76.333,438.721C 77.1545,411.239 77.7491,383.75 78.3672,356.262C 78.2478,329.643 78.0962,303.024
77.795,276.407C 77.2404,262.663 76.649,248.92 76.0193,235.18C 75.4646,214.998 74.6778,194.814 73.272,174.674C
72.3809,167.49 71.4746,160.308 70.5921,153.124C 69.7865,142.936 69.0027,132.746 68.3479,122.548C
66.4683,104.624 65.0822,86.6036 65.0681,68.5814L 65.1195,66.6142L 65.2323,63.2808L 65.3521,59.9475C
65.7202,56.8601 65.7554,53.7133 65.4397,50.6201C 65.1573,48.3812 64.597,46.1746 63.9078,44.0257C
63.716,43.4275 63.5158,42.8319 63.32,42.235C 63.1859,41.8263 63.0489,41.4186 62.9181,41.0089C 62.8847,40.9043
62.8554,40.7984 62.8276,40.6923L 62.8241,40.6507C 63.5985,41.1252 63.3394,42.3979 63.4804,43.2951C
63.7902,45.2652 63.8208,47.3013 63.5531,49.2775C 62.7447,55.2456 58.954,61.2607 53.9158,64.5603C
49.7605,67.2817 44.326,68.493 39.3941,67.9025C 34.8819,67.3623 30.368,65.1593 27.1083,61.9929C 25.6455,60.5473
24.4178,58.8047 23.5913,56.8961C 23.5319,56.7322 23.3799,56.2314 23.4301,56.3984C 23.7027,57.3043
23.9366,58.2214 24.2076,59.1276C 24.7114,60.8125 25.3284,62.4684 26.0614,64.067C 27.1131,66.2551
28.3573,68.359 29.7546,70.3444C 30.1878,70.9598 30.632,71.5675 31.0738,72.1769C 31.4128,72.6445
31.5473,73.4672 32.1173,73.5601C 32.3108,73.5917 31.9931,73.1882 31.9261,73.0039C 31.7899,72.63
31.6701,72.2496 31.5703,71.8644C 31.2688,70.7007 31.1428,69.4828 31.1648,68.2809C 31.2726,63.2858
33.4395,58.0338 36.9049,54.4348C 40.575,50.6232 46.0856,48.1152 51.3727,47.9026C 55.1311,47.7514
59.0597,48.691 62.3514,50.5112C 64.0823,51.4684 65.7006,52.6849 67.0611,54.1205C 67.5464,54.6328
68.0107,55.1677 68.4303,55.735C 68.5858,55.9451 68.7348,56.1605 68.8727,56.3825C 68.9314,56.4771
69.1189,56.7451 69.031,56.6766C 67.6571,55.6071 67.1834,53.7244 66.2999,52.2241C 65.2305,50.4079
64.1396,48.6007 62.9408,46.8673C 59.1903,42.0402 55.2769,37.3411 51.3575,32.6502C 46.8806,27.3884
42.3214,22.1968 37.7512,17.0159C 37.7842,17.1655 37.4214,16.9557 37.3293,16.8333C 37.2046,16.6677
37.0794,16.5021 36.9655,16.329C 36.7876,16.0584 36.6245,15.7783 36.454,15.503C 34.3087,12.6569 32.4129,9.57367
29.8612,7.08557C 27.219,4.50934 23.8568,2.4942 20.3032,1.49927C 15.1125,0 8.28659,1.56207 4.59872,5.51056C
0.926727,9.44202 3.05176e-005,16.6012 2.26663,21.48C 3.03891,23.1423 4.082,24.6801 5.21164,26.1236C
5.66165,26.6986 6.12119,27.2661 6.58206,27.8325C 6.77847,28.0738 6.98087,28.3102 7.18326,28.5465C
7.51041,28.9286 7.7554,29.4818 8.267,29.6132C 14.4379,38.8041 21.2804,47.8892 29.9606,54.7599C 33.0568,56.1566
36.2544,57.3742 39.5417,58.2294C 41.1025,59.2524 42.7327,60.1658 44.3448,61.106'/>

<Path Canvas.Left='419.603' Canvas.Top='350.927' Fill='#17000F7A' Data='F1 M


45.6578,58.5022C 50.0552,63.1395 53.3967,69.1172 54.8071,75.3503C 55.6809,75.3334 56.5544,75.3018
57.4272,75.2579C 57.953,76.6993 58.3983,78.1729 58.7538,79.6653C 61.5573,78.1433 64.2089,76.3238
66.6963,74.3266C 68.6341,69.8509 70.0236,65.1126 70.9252,60.3195C 71.0679,50.5452 69.0747,40.6522
65.7822,31.448C 64.219,28.7469 62.4803,26.1436 60.6272,23.6324C 59.4604,21.8096 58.235,20.0222
56.9361,18.2911C 50.9691,12.2468 44.1282,6.90442 36.6591,2.86084C 33.8409,1.98627 30.9781,1.23383
28.0804,0.676819C 22.19,0 16.1304,0.0661621 10.2734,1.14307C 7.34882,2.9303 4.53156,4.93463 1.98657,7.23041L
1.99341,8.03003L 1.98627,8.98944L 0.930786,10.3105L 0.257324,11.1924C 0.264465,13.1669 0.17334,15.1434
0,17.1103C 1.44324,19.0104 2.78589,20.9891 4.04926,23.0132C 8.23517,25.304 12.1152,28.2198 15.5665,31.5149C
17.4802,32.425 19.3563,33.4188 21.1848,34.4901C 22.2817,35.3492 23.3395,36.2595 24.366,37.2018C
25.5673,37.8944 26.7465,38.6266 27.9031,39.3915C 28.9808,40.4398 30.0085,41.5405 30.9996,42.6711C
32.373,43.5094 33.7075,44.4137 35.0044,45.366C 35.9308,46.4317 36.8029,47.5451 37.6442,48.6793C 40.47,51.2365
43.0448,54.1273 45.1481,57.3055C 45.3255,57.7011 45.4952,58.1003 45.6578,58.5022'/>

<Path Canvas.Left='401.704' Canvas.Top='339.865' Fill='#15000F7A' Data='F1 M


61.6081,85.7944C 63.2781,91.715 62.7286,98.0591 62.8058,104.21L 64.2863,104.881L 64.6061,108.519L
66.5801,109.867L 67.6398,111.8L 73.7355,114.243L 80.554,110.328C 83.1564,108.13 85.5833,105.694
87.7071,103.031C 91.8657,96.627 94.8547,89.3803 96.7537,81.9578C 98.1783,72.3463 97.8307,62.325
95.7963,52.8239C 92.7073,42.8661 87.8737,33.3183 81.7626,24.8712C 75.7171,18.1051 68.6526,12.118
60.9384,7.34094C 59.0322,6.42725 57.0946,5.57593 55.1294,4.7973C 50.7651,3.0365 46.2372,1.62292
41.6301,0.66217C 34.915,0 27.9425,0.287964 21.4366,2.07819C 19.7123,3.00787 18.0735,4.10217 16.5103,5.28278L
5.81372,13.1066L 4.13617,17.2328L 1.96362,19.0151L 1.88159,22.3574L 0,24.201L 1.68146,31.8341L 3.9126,33.6686L
9.49048,38.6266L 9.38275,39.0131L 9.35834,39.1103C 9.05817,40.043 10.1246,40.9478 10.7584,41.6951C
14.2811,41.7992 17.6901,43.3591 20.7887,45.0381C 25.3151,46.5399 29.613,48.8239 33.5334,51.5393C
38.3502,53.9123 42.8332,57.0987 46.6989,60.8466C 48.2539,62.1003 49.7435,63.443 51.1287,64.8821C
54.2005,68.072 56.7728,71.8834 58.3954,76.0039C 59.8704,78.0811 61.0643,80.3858 61.9204,82.7852C
61.8688,83.3679 61.7985,83.9492 61.7097,84.5273C 61.6843,84.9503 61.6508,85.3729 61.6081,85.7944'/>

<Path Canvas.Left='400.203' Canvas.Top='338.869' Fill='#14000F7A' Data='F1 M


62.9857,92.0096C 63.6315,96.7311 63.7072,101.513 64.0313,106.268L 66.2963,112.654L 70.2878,115.969L
73.263,116.611L 79.2701,115.137C 82.5637,112.373 85.9609,109.664 88.76,106.4C 95.5999,96.3145 99.4839,83.9286
100.529,71.7872C 100.239,60.5997 97.2579,49.3798 92.7985,39.1154C 91.7302,37.4039 90.5893,35.7366
89.4007,34.1063C 88.2162,32.0276 86.9721,29.9802 85.6364,27.9954C 80.8037,21.8688 75.2209,16.2779
69.1477,11.3783C 67.2063,10.3149 65.2089,9.35358 63.194,8.43707C 61.5413,7.26514 59.8363,6.16675
69.1477,11.3783C 67.2063,10.3149 65.2089,9.35358 63.194,8.43707C 61.5413,7.26514 59.8363,6.16675
58.1121,5.10071C 50.6229,2.27905 42.6472,0.329041 34.6509,0C 29.043,0.586365 23.3799,1.99982 18.3681,4.58356L
14.4528,6.6463L 1.81305,19.1034L 2.64502,20.9583L 0,25.4408L 3.52582,36.4718L 7.52026,38.5026L
10.8179,40.4467C 10.5937,40.9979 10.4818,41.6071 10.4954,42.2314C 11.6016,42.4753 12.6343,42.9993
13.638,43.5244C 14.9897,43.5837 16.3353,43.8366 17.6435,44.1819C 19.3535,45.0337 21.0016,46.0152
22.5882,47.0792C 23.8104,47.3286 25.0182,47.65 26.2137,48.0059C 27.2262,48.6577 28.2195,49.3409
29.1844,50.0613C 32.3005,51.2635 35.3168,52.7593 38.168,54.4988C 39.2307,55.3236 40.2567,56.1967 41.2535,57.1C
45.9786,60.0659 50.3017,63.8854 53.6399,68.3552C 57.6413,72.4094 60.7444,77.7524 61.8564,83.3391C
62.6741,85.7033 63.187,88.1997 63.3339,90.697C 63.2266,91.1367 63.1114,91.5747 62.9857,92.0096'/>

<Path Canvas.Left='186' Canvas.Top='910.333' Fill='#C0000F7A' Data='F1 M 0,0C


4.28027,5.54272 9.10501,10.7125 14.3906,15.3066C 20.4782,20.9566 27.2083,25.9489 34.2439,30.3628C
45.8384,37.9088 58.5847,43.7571 71.6028,48.437C 90.6818,55.94 110.83,60.876 131.073,64.1237C 152.707,68.2182
174.807,70.2058 196.824,70.467C 219.012,71.1737 241.353,70.1788 263.337,67.0947C 283.852,64.847
304.342,60.9698 323.981,54.6304C 337.511,50.5731 350.793,45.2982 363.139,38.4354C 372.191,33.6784
380.821,27.9176 388.47,21.1306C 393.564,16.8125 398.206,11.9166 402.333,6.66669L 402.333,6.66669C
399.088,13.0766 395.125,19.1718 390.564,24.723C 383.473,32.9823 375.227,40.3244 366.387,46.6772C
353.449,55.8702 339.224,63.3631 324.549,69.411C 304.614,77.1 283.756,82.584 262.716,86.3107C 239.271,89.9769
215.413,91.4456 191.685,91.0837C 167.984,90.0964 144.254,87.1021 121.124,81.837C 100.497,76.6034
80.1191,69.6003 61.1522,59.9515C 48.9635,53.3792 37.2233,45.7208 26.7558,36.6548C 20.539,30.8273
14.7771,24.4448 9.77652,17.5453C 5.98523,12.0271 2.71222,6.12109 0,0'/>

<Path Canvas.Left='202.95' Canvas.Top='814.456' Fill='#2E000000' Data='M 3.43388,0L


4.40695,0.922302L 4.50798,1.01379L 1.33708,87.6826L 1.21452,87.5716L -4.53663e-006,86.4202L 3.43388,0'/>

<Path Canvas.Left='205.608' Canvas.Top='816.454' Fill='#2E000000' Data='M 2.94271,0L


3.86313,0.797913L 4.05146,0.954468L 1.3093,88.0016L 1.09052,87.8197L 5.07507e-006,86.8743L 2.94271,0'/>

<Path Canvas.Left='208.217' Canvas.Top='818.335' Fill='#2E000000' Data='M 2.56406,0C


3.70299,0.910461 4.84302,1.78351 5.98366,2.63031L 3.85376,90.1599C 2.56829,89.2055 1.28354,88.2206 2.41694e-
006,87.1945L 2.56406,0'/>

<Path Canvas.Left='213.344' Canvas.Top='821.796' Fill='#2E000000' Data='M 2.01084,0L


2.28751,0.198425L 4.33561,1.59552L 2.53374,89.3544L 0.304913,87.8339L -4.63998e-006,87.6152L 2.01084,0'/>

<Path Canvas.Left='219.659' Canvas.Top='825.671' Fill='#2E000000' Data='M 1.53245,0L


1.66997,0.0880737L 2.71114,0.71698L 1.25413,88.6973L 0.147662,88.0289L 5.54698e-006,87.9343L 1.53245,0'/>

<Path Canvas.Left='223.419' Canvas.Top='827.803' Fill='#2E000000' Data='M 1.31182,0L


2.4968,0.676819L 1.24919,88.7809L -1.47111e-006,88.0674L 1.31182,0'/>

<Path Canvas.Left='225.917' Canvas.Top='829.157' Fill='#2E000000' Data='M 1.18339,0L


1.67913,0.283142L 3.56023,1.30176L 2.49301,89.5063L 0.522603,88.4393L -7.60639e-006,88.1409L 1.18339,0'/>

<Path Canvas.Left='230.9' Canvas.Top='831.723' Fill='#2E000000' Data='M 0.959161,0L


3.34472,1.22717L 2.48617,89.541L 4.67262e-007,88.262L 0.959161,0'/>

<Path Canvas.Left='234.627' Canvas.Top='833.537' Fill='#2E000000' Data='M


0.81284,6.10352e-005L 3.20399,1.17053L 2.48177,89.5513L 3.26074e-006,88.3364L 0.81284,6.10352e-005'/>

<Path Canvas.Left='240.826' Canvas.Top='836.385' Fill='#2E000000' Data='M 0.598226,0L


0.645653,0.0221558L 1.79778,0.534668L 1.2377,88.9902L 0.0490535,88.4615L 3.20848e-006,88.4386L 0.598226,0'/>

<Path Canvas.Left='245.776' Canvas.Top='838.499' Fill='#2E000000' Data='M 0.448412,0L


1.6495,0.509888L 1.23645,89.0295L 4.75779e-006,88.5046L 0.448412,0'/>

<Path Canvas.Left='248.249' Canvas.Top='839.519' Fill='#2E000000' Data='M 0.377702,0L


0.657864,0.118958L 1.57968,0.492493L 1.23571,89.041L 0.28844,88.6572L 5.80161e-006,88.5347L 0.377702,0'/>

<Path Canvas.Left='250.72' Canvas.Top='840.499' Fill='#2E000000' Data='M 0.310693,0L


1.99153,0.681213L 2.71573,0.961365L 2.47048,89.5495L 1.72728,89.262L 3.22951e-007,88.562L 0.310693,0'/>

<Path Canvas.Left='255.66' Canvas.Top='842.391' Fill='#2E000000' Data='M 0.182194,0L


0.901159,0.278076L 1.38563,0.456909L 1.23446,89.0813L 0.737832,88.8979L -5.36875e-006,88.6125L 0.182194,0'/>

<Path Canvas.Left='258.128' Canvas.Top='843.292' Fill='#2E000000' Data='M 0.120919,0L


1.32478,0.444336L 1.23409,89.091L -6.00066e-006,88.6355L 0.120919,0'/>

<Path Canvas.Left='260.596' Canvas.Top='844.177' Fill='#2E000000' Data='M 0.060638,0L


1.265,0.423767L 1.2336,89.0917L 6.83104e-006,88.6577L 0.060638,0'/>

<Path Canvas.Left='263.064' Canvas.Top='845.025' Fill='#2E000000' Data='M


0.00220676,0L 1.28946,0.452942L 3.61593,1.23248L 3.70015,89.9402L 1.31851,89.1422L 8.7343e-007,88.6782L
0.00220676,0'/>

<Path Canvas.Left='267.884' Canvas.Top='846.661' Fill='#2E000000' Data='M -1.28437e-


005,0L 0.391041,0.131042L 1.2048,0.390259L 1.34588,89.1167L 0.5131,88.8514L 0.112763,88.7173L -1.28437e-
005,0'/>

<Path Canvas.Left='271.499' Canvas.Top='847.819' Fill='#2E000000' Data='M -7.72316e-


006,0L 0.702673,0.223816L 2.40972,0.739624L 2.66337,89.5013L 0.916521,88.9735L 0.197419,88.7444L -7.72316e-
006,0'/>

<Path Canvas.Left='275.113' Canvas.Top='848.923' Fill='#2E000000' Data='M -2.36329e-


006,0L 1.00799,0.304565L 2.40956,0.705139L 2.74761,89.4918L 1.3132,89.0818L 0.281707,88.7701L -2.36329e-
006,0'/>

<Path Canvas.Left='279.932' Canvas.Top='850.316' Fill='#2E000000' Data='M 8.09422e-


006,0L 0.0925939,0.0264282L 2.40885,0.650391L 2.86065,89.4686L 0.489254,88.8298L 0.394493,88.8028L 8.09422e-
006,0'/>

<Path Canvas.Left='283.546' Canvas.Top='851.291' Fill='#2E000000' Data='M 8.18823e-


006,0L 0.356442,0.0960083L 2.408,0.614441L 2.9471,89.4554L 0.845413,88.9243L 0.480492,88.826L 8.18823e-
006,0'/>

<Path Canvas.Left='287.157' Canvas.Top='852.21' Fill='#2E000000' Data='M 3.01638e-


006,0L 0.585021,0.147827L 1.20359,0.29364L 1.80209,89.1493L 1.16783,88.9998L 0.568539,88.8484L 3.01638e-
006,0'/>

<Path Canvas.Left='291.97' Canvas.Top='853.347' Fill='#2E000000' Data='M 5.21584e-


006,0L 3.30229,0.72052L 3.60675,0.781433L 4.39372,89.6794L 4.08069,89.6168L 0.690569,88.8772L 5.21584e-
006,0'/>

<Path Canvas.Left='296.778' Canvas.Top='854.368' Fill='#2E000000' Data='M 2.98697e-


006,0L 1.2012,0.240295L 2.05592,89.1519L 0.820836,88.9048L 2.98697e-006,0'/>

<Path Canvas.Left='300.38' Canvas.Top='855.061' Fill='#2E000000' Data='M 4.39675e-


006,0L 1.19976,0.217163L 2.16143,89.1486L 0.925372,88.9249L 4.39675e-006,0'/>

<Path Canvas.Left='302.779' Canvas.Top='855.491' Fill='#2E000000' Data='M 7.2912e-


006,0L 2.39592,0.38562L 3.47328,89.3362L 0.998629,88.938L 7.2912e-006,0'/>

<Path Canvas.Left='307.568' Canvas.Top='856.229' Fill='#2E000000' Data='M -8.10325e-


006,0L 1.19573,0.166931L 2.39985,89.1358L 1.16096,88.9629L -8.10325e-006,0'/>

<Path Canvas.Left='309.959' Canvas.Top='856.551' Fill='#2E000000' Data='M 5.80094e-


006,0L 1.19293,0.13916L 2.49036,89.1195L 1.24939,88.9748L 5.80094e-006,0'/>

<Path Canvas.Left='312.344' Canvas.Top='856.829' Fill='#2E000000' Data='M -1.27275e-


005,0L 0.393707,0.0458984L 1.19052,0.119019L 2.58807,89.1101L 1.75498,89.0337L 1.34539,88.9859L -1.27275e-
005,0'/>

<Path Canvas.Left='241.87' Canvas.Top='364.131' Fill='#17000F7A' Data='F1 M


44.2998,20.1762C 43.7122,21.149 43.226,22.9735 42.1051,22.7855C 39.856,21.4949 38.6142,18.7757
37.7767,16.3215C 36.5259,18.22 35.7039,20.5144 35.6005,22.7855C 35.6024,24.8726 36.749,27.104 38.3934,28.3892C
39.902,29.5682 41.8211,30.1957 43.6899,30.6121C 44.6742,30.8315 45.6677,31.0079 46.6608,31.183C
47.2954,31.2949 47.9305,31.4039 48.5644,31.519C 48.6831,31.5405 48.8009,31.5665 48.9185,31.5928C
49.0119,31.6136 49.1047,31.6367 49.1973,31.6603C 49.5488,31.7499 49.438,31.7297 49.4334,31.7402C
49.217,32.2256 48.401,31.4371 47.95,31.1559C 47.0673,30.6057 46.3161,29.7932 45.8113,28.8837C 44.4899,26.5027
45.1706,22.6097 47.2405,20.8405C 47.678,20.4839 48.171,20.185 48.693,19.9705C 48.9609,19.8605 49.4483,19.973
49.5158,19.6913C 49.5742,19.4479 49.0351,19.5502 48.7914,19.4926C 48.2825,19.3723 47.7773,19.2355
47.2758,19.0875C 45.8167,18.6569 44.382,18.1451 42.9559,17.6158C 41.7639,16.4782 40.5235,15.3663
39.5323,14.0501C 39.2944,13.9456 39.0497,13.8528 38.8247,13.7226C 34.1064,11.6313 28.7802,11.3281
23.7079,10.3753C 21.2542,9.91443 18.7998,9.44556 16.3743,8.85431C 15.7143,8.69342 14.7666,8.8454
14.4258,8.25787C 14.2725,7.99371 15.0112,8.44287 15.2818,8.58447C 15.856,8.88495 16.3892,9.26721
16.8838,9.68597C 19.7562,12.2549 21.1302,17.1798 19.9243,20.8398C 19.4351,22.3243 18.5859,23.7339
17.4876,24.8461C 17.0962,25.2424 16.67,25.6071 16.2181,25.9328C 16.0149,26.0793 15.6127,26.1135
15.6023,26.3638C 15.5958,26.522 15.9197,26.3472 16.0748,26.3153C 16.3902,26.2504 16.7054,26.1843
17.0219,26.1243C 18.1259,25.9147 19.2384,25.748 20.3537,25.6105C 23.094,25.2729 25.863,25.0859 28.6234,25.141C
28.9847,25.1482 29.346,25.1594 29.707,25.1771C 30.0401,25.1934 30.3727,25.218 30.7053,25.243C 30.8588,25.2546
31.012,25.2708 31.1651,25.287C 31.3083,25.3022 31.4514,25.3188 31.5943,25.3374C 31.7256,25.3544
31.8566,25.3731 31.9873,25.3939C 32.1051,25.4126 32.2228,25.4329 32.3398,25.4559C 32.667,25.5201
33.3705,25.5049 33.2703,25.8229C 33.0877,26.4016 32.0441,25.7227 31.4776,25.5051C 30.4369,25.1053
29.4653,24.4978 28.6122,23.78C 25.9872,21.5709 24.3475,17.882 24.2613,14.4522C 24.2553,14.0981 24.5745,13.4897
24.2346,13.39C 23.8482,13.2767 23.8931,14.1202 23.7505,14.4968C 23.6057,14.8794 23.4626,15.2627
23.3158,15.6445C 23.141,16.0991 22.9654,16.5533 22.7858,17.006C 21.9579,19.0934 21.0854,21.1654
20.1226,23.1942C 19.7006,24.0833 19.2661,24.968 18.7812,25.8244C 18.5,26.321 18.334,27.3593 17.7819,27.2147C
17.4808,27.1359 17.9373,26.6047 18.0894,26.3332C 18.4157,25.7505 18.8155,25.2076 19.2476,24.6983C
20.5274,23.1897 22.1759,21.9666 23.9296,21.051C 19.8286,22.4814 16.061,25.0827 13.0346,28.1981C
7.83044,33.7441 5.07605,41.8544 4.73795,49.4522C 3.42017,74.5566 2.97266,99.7003 2.38297,124.832C
2.77637,172.844 3.17953,220.855 3.59222,268.866C 4.27716,280.565 4.965,292.264 5.65311,303.963C
6.01208,313.483 6.36496,323.003 6.72095,332.523C 9.2049,361.656 11.6836,390.79 14.1675,419.924C
15.4928,425.317 16.8183,430.711 18.1438,436.104C 21.2268,443.458 24.3096,450.811 27.3926,458.165C
29.8631,450.812 32.3337,443.46 34.8045,436.108C 35.2315,430.155 35.6587,424.201 36.0858,418.247C
36.8094,414.548 37.533,410.849 38.2565,407.151C 39.722,385.711 41.1835,364.271 42.6496,342.831C
43.4751,310.772 44.3086,278.713 45.1115,246.652C 44.733,202.385 44.4388,158.116 43.9945,113.849C
43.2527,102.12 42.4817,90.3919 41.6739,78.6667C 41.2852,69.2004 40.9409,59.731 40.378,50.2735L
40.2793,49.4522C 39.8878,48.7969 38.83,49.9345 38.1202,50.2155C 37.8955,50.3044 37.4388,50.4072
37.3968,50.1692C 37.3373,49.8325 37.8481,49.6457 38.1294,49.4512C 40.3119,48.3098 42.2917,46.6321
43.7329,44.6348C 46.8897,40.3425 47.9439,34.7559 48.9359,29.521C 49.8786,24.5463 50.8851,19.5154
50.8498,14.4522C 50.7677,10.4395 48.7053,6.13318 45.5656,3.63281C 42.0783,0.855652 37.0758,0 32.6251,0.255432C
27.0351,0.997986 21.6118,2.8421 16.3473,4.8631C 11.1838,6.40826 4.99124,8.00122 2.13367,12.571C 0,15.9832
0.912323,21.8282 3.91058,24.5126C 8.39069,28.324 15.1364,28.2714 20.9698,29.0256C 22.3454,29.0874
23.721,29.1499 25.0966,29.2109C 26.3522,29.2667 27.6079,29.3186 28.8633,29.376C 29.3745,29.3994
29.8855,29.4266 30.3965,29.4532C 30.6108,29.4644 30.825,29.4768 31.0392,29.4891C 31.2197,29.4995
31.4001,29.5107 31.5806,29.5212C 31.7196,29.5293 31.8586,29.5376 31.9976,29.5449C 32.0805,29.5493
31.9677,29.3551 31.893,29.3188C 36.035,30.7449 40.4391,31.4153 44.8062,31.7603C 48.1024,32.0208
52.0269,32.1152 54.5682,29.9999C 56.2932,28.4977 57.0997,25.2813 55.9829,23.2851C 54.8165,21.2003
51.76,20.4381 49.3724,20.5169C 47.6808,20.4476 45.9731,20.4645 44.2998,20.1762'/>

<Path Canvas.Left='232.816' Canvas.Top='332.488' Fill='#15000F7A' Data='F1 M


20.5197,57.0982C 21.7101,55.8575 22.8663,54.5721 24.1844,53.468C 25.2998,52.5335 27.3993,51.9747 28.514,52.91C
29.8763,54.0531 30.125,56.55 29.3891,58.1844C 30.0431,57.0997 30.2694,55.6316 29.9021,54.4194C 29.5027,53.1013
28.369,51.9402 27.1163,51.3676C 22.2183,49.1289 16.4118,49.6075 11.3922,47.6565C 11.0574,47.0661
10.7523,46.4304 10.6542,45.7588C 10.5273,45.6719 10.2651,45.5724 10.3282,45.4322C 10.4543,45.1519
10.8899,45.7123 11.0998,45.9368C 11.5079,46.3732 11.8011,46.9257 11.9906,47.4924C 12.201,48.1218
12.284,48.8058 12.2373,49.4678C 12.2122,49.8241 11.8127,50.4268 12.1732,50.5319C 11.9664,50.9305
12.953,50.0809 13.3082,49.8062C 13.5435,49.6243 13.7794,49.4432 14.0164,49.2636C 14.2897,49.0565
14.563,48.8492 14.8393,48.6459C 17.0159,47.0438 19.2325,45.4963 21.4557,43.9595C 24.6014,42.0114
27.7925,40.1369 30.9922,38.2789C 35.4915,35.2881 40.092,32.4419 44.4679,29.2734C 45.3322,28.5654
46.1695,27.8246 46.9972,27.0743C 47.2078,26.8834 47.4151,26.6889 47.6287,26.5013C 47.9591,26.2111
48.29,25.9211 48.6289,25.6409C 48.7459,25.5441 48.8716,25.4582 48.9957,25.3707C 49.5549,24.9769 49.4237,25.092
49.4433,25.2201C 49.5218,25.7328 48.7489,26.0131 48.3044,26.2805C 47.4418,26.7994 46.4569,27.1283
45.4684,27.3185C 43.9035,27.5461 42.2585,27.4404 40.7337,27.0211C 40.0363,26.8293 39.3586,26.559
38.7093,26.2403C 38.4806,26.128 38.2558,26.0076 38.0338,25.8827C 37.7664,25.7324 37.4194,25.2834
37.1986,25.4964C 36.9561,25.7303 37.3205,26.1636 37.4442,26.4772C 37.0078,26.2588 36.9845,27.3866
37.006,27.8741C 37.0531,28.9467 37.1359,30.0175 37.2196,31.0879C 37.3705,35.3494 36.9243,39.6116
36.6877,43.8692C 36.5434,42.215 36.6901,40.5034 37.1573,38.91C 37.3226,38.3463 37.5294,37.794 37.7607,37.2539C
38.0126,36.6653 37.9356,36.8378 37.9311,36.8359C 37.6577,36.7258 37.5303,37.2693 37.3501,37.5026C
33.8747,42.3997 31.2633,48.4238 31.1806,54.4282C 31.2394,60.8683 34.9962,67.8409 40.3351,71.4428C
43.2267,73.3936 46.6481,74.6068 50.0707,75.2797C 52.1717,75.6927 54.3744,75.598 56.4272,76.2073C
56.6286,76.2671 56.0087,76.1645 55.8024,76.1249C 55.4957,76.066 55.1918,75.9918 54.8905,75.9094C
53.7956,75.6097 52.7274,75.1942 51.7115,74.6876C 48.6709,73.1713 45.9686,70.7225 44.149,67.853C
41.7435,64.0593 40.6668,59.1346 41.2834,54.685C 41.9295,50.0228 44.5771,45.37 48.2146,42.3831C 49.8239,41.1091
51.6562,40.0627 53.5945,39.3873C 54.6441,39.0215 55.7334,38.751 56.8343,38.5975C 57.301,38.5324 57.7712,38.489
58.2419,38.4678C 58.4554,38.4581 58.6692,38.4542 58.883,38.4535C 59.1777,38.4525 59.5507,38.7131
59.2614,38.4479C 58.8588,38.0787 58.2106,38.1489 57.6835,38.0059C 56.5948,37.7104 55.5096,37.4005
54.4341,37.0603C 54.1393,36.9671 53.8457,36.8701 53.552,36.7734C 53.2935,36.6882 53.0351,36.6026
52.7775,36.5148C 52.4982,36.4195 51.6743,36.1001 51.9385,36.2318C 45.2178,33.2939 37.5708,33.2415
30.3248,32.1038C 28.9283,31.8845 27.5134,31.7036 26.1646,31.2802C 25.9309,31.2068 26.6338,31.4217
26.8651,31.5026C 27.3343,31.6669 27.7917,31.8665 28.2371,32.0873C 29.5484,32.7374 30.7689,33.5853
31.8813,34.5363C 35.1819,37.501 37.6111,41.8143 38.2977,46.1975C 38.8449,49.6912 38.3875,53.4681
37.0195,56.729C 36.1953,58.6936 35.0317,60.5474 33.6133,62.1371C 32.5686,63.308 31.368,64.3568
30.0642,65.2301C 29.6442,65.5114 29.2115,65.7741 28.772,66.0239C 28.5549,66.1474 28.0582,66.1956
28.1427,66.4307C 28.2449,66.7153 28.7469,66.3953 29.047,66.3578C 29.8575,66.2568 30.6685,66.1573
31.482,66.0839C 33.5864,65.8939 35.7078,65.7881 37.8181,65.8942C 38.12,65.9072 38.4221,65.9153
38.7238,65.9331C 39.0202,65.9506 39.3166,65.9711 39.6121,66C 39.871,66.0253 40.1289,66.0599 40.3866,66.0955C
38.7238,65.9331C 39.0202,65.9506 39.3166,65.9711 39.6121,66C 39.871,66.0253 40.1289,66.0599 40.3866,66.0955C
40.4987,66.111 40.6101,66.132 40.7213,66.1532C 40.8196,66.172 40.9177,66.1923 41.0151,66.2157C 41.0971,66.2354
41.1789,66.257 41.2594,66.2823C 41.9748,66.5077 41.6324,66.5237 41.5995,66.5622C 41.3232,66.8846
40.7493,66.6716 40.3274,66.6245C 39.4723,66.5289 38.6281,66.3176 37.8122,66.0448C 35.4052,65.2399
33.1493,63.8669 31.2499,62.1836C 26.8466,58.2814 24.1088,51.9772 23.9908,46.0949C 23.9868,45.5756
23.9961,45.0562 24.0127,44.5372C 24.0218,44.2532 24.2764,43.7111 23.9934,43.6849C 23.7534,43.6627
23.7262,44.0892 23.6302,44.3103C 23.4899,44.6333 23.3538,44.9581 23.2164,45.2823C 23.0444,45.6883
22.8752,46.0953 22.702,46.5008C 22.0906,47.9324 21.4643,49.3582 20.7948,50.7635C 20.5745,51.2258
20.3514,51.6868 20.1201,52.1437C 19.9103,52.558 19.6917,52.9678 19.4716,53.3767C 19.3751,53.5561
19.2736,53.7328 19.1704,53.9084C 19.0801,54.062 18.9879,54.2147 18.8913,54.3644C 18.8121,54.4871
18.7303,54.6082 18.6432,54.7254C 18.5796,54.8109 18.5153,54.8968 18.4398,54.9719C 18.3984,55.0131
18.3488,55.0475 18.2522,55.0553C 17.8657,54.5057 18.6545,53.7625 18.9846,53.1773C 19.5401,52.1926
20.2015,51.2643 20.9238,50.3946C 23.0464,47.8387 25.7991,45.7515 28.7466,44.2187C 22.0988,46.555
16.1991,51.4782 12.0319,57.1603C 7.05664,63.9442 4.43884,72.6923 4.02505,81.0949C 3.74942,84.8594
3.56042,88.6299 3.36896,92.3997C 2.35776,125.026 2.14432,157.674 1.90967,190.315C 2.48401,229.285
2.85712,268.258 3.37277,307.229C 5.00742,347.374 6.65833,387.518 8.29962,427.662C 10.6814,457.606
13.0672,487.55 15.4554,517.494C 16.1962,522.731 16.937,527.968 17.6779,533.204C 19.3087,545.32 20.9397,557.437
22.5703,569.553C 25.5155,581.449 28.4605,593.345 31.4054,605.242L 42.7956,602.115C 43.95,594.525
45.1044,586.934 46.2592,579.344L 47.8353,577.601L 48.0089,577.409C 48.8698,568.938 49.7308,560.467
50.5919,551.996L 51.4284,550.081L 52.338,547.999C 54.1959,525.254 56.0544,502.509 57.9116,479.765C
58.2512,470.975 58.5907,462.185 58.93,453.396C 60.0112,427.094 61.0847,400.793 62.1672,374.492C 62.793,338.564
63.4347,302.638 64.0118,266.71C 63.3348,223.987 62.8636,181.261 62.0337,138.541C 61.239,119.383
60.6148,100.207 59.0825,81.0949C 58.0601,83.7811 56.8523,86.6023 54.7254,88.5354C 54.3377,88.8878
53.9273,89.2171 53.4964,89.515C 53.0717,89.8086 52.6235,90.0735 52.1528,90.2856C 51.8756,90.4106
51.4153,90.8239 51.2802,90.5515L 51.307,90.4516C 51.4336,90.3428 51.5839,90.2648 51.7223,90.1714C
56.5376,87.6671 60.747,83.4681 63.2093,78.6312C 65.8838,73.3774 66.8763,67.3633 67.7076,61.527C
68.4361,56.4121 69.1805,51.2613 69.1515,46.0949C 69.0075,38.6608 64.5657,30.5849 58.2761,26.619C
51.5602,22.3843 42.4096,22.393 34.6136,23.896C 28.9309,25.1138 23.3584,26.8777 17.9215,28.9308C
12.6399,30.9253 7.09396,33.7285 3.84015,38.3421C 1.31058,41.9288 0.0457153,46.7126 0.498993,51.0782C
0.969299,55.6075 3.41312,60.157 6.80276,63.1978C 12.5454,68.1021 20.9532,68.8627 28.4243,69.9641C
29.8374,70.1724 31.252,70.37 32.6653,70.5766C 33.8625,70.7516 35.0595,70.9277 36.2558,71.1089C 37.0594,71.2307
37.8496,71.5527 38.6611,71.5079C 38.8926,71.4952 38.2166,71.3754 37.9968,71.3017C 37.5212,71.1422
37.054,70.9566 36.5946,70.7549C 43.7856,73.8084 51.7347,75.9769 59.5355,75.5522C 63.7079,75.3251
68.0382,73.8509 71.3109,71.2528C 74.4179,68.6926 76.8506,64.9228 77.6614,60.9794C 78.4065,57.3555
77.9313,53.3083 76.3653,49.9564C 73.8785,44.6335 67.7671,40.5925 61.9422,39.826C 60.148,39.5898
58.2325,38.9075 56.5228,39.5009C 56.3244,39.5698 56.9055,39.6748 57.1033,39.7454C 57.5469,39.9039
57.9847,40.0809 58.4109,40.2816C 59.7649,40.9192 61.0312,41.7798 62.1323,42.7933C 65.2456,45.6587
67.1744,50.1971 67.2076,54.4282C 67.1752,55.5021 67.007,56.5883 66.6564,57.6038C 66.5328,57.9619
66.3859,58.3127 66.2169,58.6516C 66.1583,58.769 66.0959,58.8847 66.0277,58.9968C 65.9349,59.149
65.9311,59.2907 65.9088,59.1514C 65.7907,58.4143 66.7145,57.8944 67.1283,57.2731C 67.9599,56.0243
68.7383,54.7332 69.3932,53.3832C 71.1109,49.8427 71.9749,45.7355 71.7183,41.8087L 71.3997,39.3632C
70.4548,34.5117 69.3423,29.6846 67.9518,24.9415C 66.336,19.9088 64.5914,14.7226 61.4264,10.4893C
60.7984,9.7171 60.1643,8.94849 59.4918,8.21466C 55.3172,3.66968 48.641,0 42.5232,0.810364C 38.0835,1.51514
33.7903,4.25122 30.9524,7.73737C 29.9827,8.92847 28.9031,10.1039 28.34,11.5328C 20.0888,21.4473
10.4193,30.1282 2.23981,40.1021C 1.83322,41.0982 1.41309,42.0887 0.996307,43.0806C 0.376343,45.0699 0,47.3023
0.539337,49.315C 0.929596,50.7714 1.91251,52.1783 3.18869,52.9813C 5.98877,55.7794 10.5266,56.2896
14.4623,56.7141C 16.4771,56.8978 18.4992,56.9937 20.5197,57.0982'/>

<Path Canvas.Left='231.176' Canvas.Top='331.645' Fill='#14000F7A' Data='F1 M


23.9022,62.178C 25.92,62.3046 28.0358,63.0015 29.9636,62.3925C 31.1283,62.0246 32.0668,60.7718
32.3049,59.5738C 32.4133,58.2376 31.9026,56.7721 31.0203,55.7628C 30.5062,55.1747 29.5206,54.9947
29.206,54.2797C 29.1495,54.1512 29.469,54.3852 29.5838,54.4661C 29.8354,54.6434 30.0646,54.8569
30.2611,55.0938C 30.8427,55.7949 31.2133,56.7216 31.2781,57.6301C 31.3326,58.394 31.1806,59.1957
30.8529,59.8879C 30.7836,60.0342 30.7061,60.1769 30.6223,60.3155C 30.5722,60.3984 30.5188,60.4792
30.4652,60.5598C 30.1803,60.988 30.2921,60.8766 30.32,60.8912C 31.6982,59.8457 32.6244,57.9102
32.5061,56.1843C 32.3803,54.3499 31.0341,52.4883 29.416,51.6151C 25.8826,49.7082 21.7175,49.3253
17.912,48.0453C 16.6555,47.6227 15.4032,47.1617 14.2262,46.5518C 13.6168,46.2361 12.8219,45.9519
12.5856,45.3075C 12.4705,45.0364 13.1704,45.4764 13.3906,45.6721C 13.8684,46.0968 14.2508,46.6392
14.5321,47.2133C 15.2462,48.6705 14.7732,50.4499 14.8993,52.0993C 14.7207,52.4269 15.5978,51.8148
15.8972,51.592C 16.1302,51.4185 16.3633,51.2454 16.5976,51.0736C 16.8699,50.8738 17.1421,50.6737
17.4169,50.4773C 19.623,48.9006 21.8597,47.3663 24.117,45.8637C 30.3911,41.6874 36.7996,37.7161
43.1816,33.7066C 44.4644,32.8546 45.7355,31.9836 46.9788,31.0748C 47.8713,30.3369 48.7358,29.5651
49.5902,28.7833C 49.8031,28.5885 50.0127,28.39 50.2288,28.1987C 50.5553,27.9097 50.8825,27.6212
51.218,27.3427C 51.4228,27.1727 51.7803,26.738 51.9207,26.964C 52.2426,27.4818 51.0989,27.889 50.5782,28.2064C
49.5702,28.8207 48.4079,29.196 47.2463,29.4065C 45.4557,29.6566 43.5685,29.5252 41.8371,29.0043C
40.9782,28.7459 40.1428,28.3926 39.3581,27.9581C 39.0987,27.8144 38.8435,27.663 38.5907,27.5079C
37.2587,26.6908 38.0751,27.9852 38.0774,27.9911C 37.2425,27.3907 37.5549,30.0206 37.6418,31.0453L
37.7605,32.1506C 38.0561,36.341 37.7408,40.5529 37.6423,44.7525C 37.5246,43.1416 37.6619,41.483
38.1011,39.9287C 38.2693,39.3332 38.4803,38.7482 38.731,38.1824C 38.8498,37.9146 39.3174,37.1804
39.1141,37.3914C 34.684,41.9883 32.3573,48.888 32.2491,55.2712C 32.3079,62.1152 36.4871,69.5421
39.1141,37.3914C 34.684,41.9883 32.3573,48.888 32.2491,55.2712C 32.3079,62.1152 36.4871,69.5421
42.2802,73.1868C 45.2366,75.0469 48.6679,76.2004 52.1021,76.8383C 54.0526,77.2005 56.1935,76.8956
57.9832,77.7515C 58.1923,77.8514 57.5201,77.7175 57.2923,77.6753C 56.9702,77.6157 56.6513,77.5388
56.3351,77.4532C 55.194,77.1445 54.0811,76.7128 53.0227,76.1862C 49.864,74.6142 47.0567,72.0718
45.1668,69.0925C 42.6693,65.1552 41.5512,60.0437 42.1905,55.4252C 42.8609,50.5817 45.6127,45.7507
49.3881,42.6434C 51.566,40.9163 54.1636,39.5898 56.8724,38.9664C 57.7915,38.7548 58.7296,38.6091
59.6708,38.5481C 60.1098,38.5197 60.9757,38.9366 60.9896,38.4969C 61.0059,37.9832 60.0183,38.1592
59.5257,38.0127C 58.4637,37.6968 57.4032,37.3741 56.353,37.0208C 56.0645,36.9237 55.7774,36.8231
55.4901,36.7226C 55.238,36.6344 54.986,36.546 54.7349,36.4549C 54.4821,36.3632 53.7317,36.0671 53.9797,36.171C
49.2293,34.0903 43.9157,33.5874 38.787,32.818C 37.8627,32.7032 36.9377,32.5945 36.0142,32.4736C
34.7203,32.3043 33.427,32.1307 32.135,31.9477C 30.7649,31.7536 29.4062,31.4847 28.0479,31.2204C 27.774,31.1671
28.5774,31.397 28.8401,31.4911C 29.3367,31.6691 29.8216,31.882 30.2937,32.1176C 31.6696,32.8041
32.9516,33.6949 34.1198,34.695C 37.0755,37.3517 39.3895,40.9857 40.4007,44.8292C 41.4544,48.8344
41.2176,53.3586 39.7662,57.2374C 38.6347,60.2614 36.6988,63.0813 34.28,65.22C 33.4315,65.9702 32.5128,66.6471
31.5467,67.2382C 31.0679,67.5311 30.1953,67.5436 30.098,68.0964C 30.0497,68.371 30.6551,68.0616
30.9314,68.0244C 31.7233,67.9174 32.5157,67.812 33.3108,67.7324C 34.6788,67.5956 36.0527,67.5031
37.4272,67.4748C 38.726,67.4481 40.0306,67.4658 41.3222,67.6046C 41.9805,67.6754 43.2922,67.4618
43.24,68.1218C 43.2102,68.4983 42.4937,68.3002 42.1171,68.2727C 41.3284,68.2151 40.5472,68.0442
39.7874,67.8251C 37.6325,67.2036 35.5883,66.1185 33.7855,64.7844C 28.4349,60.8245 24.9583,53.5931
24.8249,46.9379C 24.8209,46.3974 24.8306,45.8568 24.8482,45.3165C 24.8582,45.0134 25.1188,44.5062
24.8322,44.4067C 24.6148,44.3312 24.5621,44.7833 24.4683,44.9935C 24.3268,45.3109 24.1897,45.6303
24.0517,45.9492C 23.878,46.3504 23.7076,46.7529 23.5333,47.1538C 22.9165,48.5719 22.2863,49.9849
21.6121,51.3766C 21.3907,51.8337 21.1664,52.2896 20.9337,52.7411C 20.7233,53.1494 20.5039,53.5529
20.283,53.9556C 20.1865,54.1315 20.0848,54.3045 19.9814,54.4764C 19.8914,54.6261 19.7995,54.7747
19.7028,54.9202C 19.6243,55.0383 19.5431,55.1549 19.4562,55.267C 19.3939,55.3474 19.331,55.4286
19.2558,55.4971C 19.2162,55.5331 19.1677,55.5617 19.0763,55.5493C 18.7651,54.9044 19.5112,54.1739
19.8634,53.5504C 20.4419,52.5263 21.1297,51.5605 21.8813,50.6558C 24.0803,48.0086 26.9312,45.8461
29.9844,44.2581C 23.1844,46.6226 17.1661,51.6765 12.9077,57.4813C 7.82224,64.4134 5.14041,73.351
4.71527,81.9379C 4.45816,85.3662 4.27512,88.7997 4.09604,92.233C 2.67331,143.193 3.01428,194.186
2.6665,245.165C 3.74146,288.477 4.94565,331.785 6.12155,375.095C 6.63489,381.122 7.14828,387.149
7.6604,393.177C 8.03256,402.716 8.40411,412.256 8.77673,421.795C 10.5691,449.291 12.3658,476.788
14.1633,504.284C 14.9946,509.044 15.826,513.804 16.657,518.564C 17.1101,526.127 17.5632,533.691
18.0163,541.255C 20.9745,559.681 23.9325,578.107 26.8902,596.533C 28.8397,601.175 30.7893,605.817
32.7389,610.459C 33.1826,611.516 33.6264,612.572 34.0702,613.629C 34.6688,615.054 36.0993,616.376
35.866,617.904C 35.7157,618.889 34.0946,618.816 33.2089,619.271L 32.1941,616.842L 31.1443,619.271C
33.7931,618.813 36.7632,619.243 39.0905,617.898C 40.4358,617.12 40.3176,615.043 40.9312,613.616C
41.3861,612.557 41.8411,611.499 42.296,610.441C 44.6072,605.064 46.9184,599.687 49.2402,594.286C
49.6667,587.989 50.0933,581.691 50.5199,575.394C 51.8222,568.645 53.1253,561.895 54.4276,555.146C
57.0486,520.283 59.6706,485.42 62.2888,450.557C 62.5747,438.053 62.8602,425.55 63.1448,413.047C
63.9764,382.829 64.8188,352.612 65.6528,322.395C 65.7303,293.213 65.7934,264.031 65.7994,234.849C
65.3944,219.832 65.0223,204.813 64.677,189.794C 64.5646,167.693 64.4547,145.592 64.0984,123.494C
63.541,115.671 62.9582,107.85 62.3456,100.031C 62.137,93.9983 61.9614,87.9628 61.5905,81.9379C 60.4592,86.1859
57.7818,91.2397 53.5279,92.3819C 53.3573,92.3719 53.7051,92.078 53.8438,91.9782C 58.9816,89.3031
63.4687,84.7559 65.9707,79.5316C 68.4846,74.2826 69.3355,68.3284 70.0283,62.5499C 70.6495,57.3672
71.2826,52.1575 71.2428,46.9379C 71.1445,42.1805 69.572,37.2466 66.8191,33.3654C 63.9261,29.2868
59.4218,26.1038 54.659,24.5806C 48.0406,22.4641 40.5727,23.4667 33.8196,25.1037C 27.4238,26.6541
21.0758,28.6113 15.0882,31.3423C 9.05948,34.092 3.35593,39.8889 2.10565,46.3961C 0.917816,52.5784
3.57178,60.0477 8.25699,64.2526C 11.5928,67.1031 16.0167,68.6666 20.3207,69.52C 24.9191,70.5179
29.5737,71.2372 34.2099,72.0412C 35.3996,72.2475 36.5887,72.4566 37.7768,72.6718C 38.5598,72.8137
39.5493,72.5948 40.1144,73.1548C 40.2967,73.3354 39.616,73.0308 39.3719,72.9517C 38.8672,72.7881
38.3723,72.5936 37.8859,72.3817C 40.8467,73.6787 43.9279,74.7034 47.0338,75.5991C 52.4881,76.9774
58.2967,77.9642 63.8483,77.0538C 67.3238,76.4838 70.7709,75.0092 73.5277,72.8173C 76.7928,70.1227
79.3481,66.1578 80.2002,62.011C 80.9839,58.1967 80.4833,53.9368 78.8346,50.409C 76.2848,44.9527 70.137,40.7139
64.1775,39.8436C 62.2354,39.56 60.1485,38.8742 58.2979,39.528C 58.0653,39.6101 58.7472,39.7329 58.979,39.8173C
59.4531,39.9898 59.9214,40.1806 60.3772,40.3968C 61.8046,41.0737 63.1406,41.9823 64.3018,43.0534C
67.567,46.0654 69.5916,50.8291 69.6243,55.2712C 69.5829,56.4719 69.3808,57.6874 68.9653,58.8146C
68.765,59.3578 68.7574,60.4687 68.1803,60.3216C 68.2366,60.2051 68.3046,60.0945 68.3726,59.9845C
68.4986,59.7806 68.6309,59.5806 68.7619,59.3799C 68.9519,59.0886 69.1452,58.7996 69.3355,58.5085C
70.0773,57.374 70.7823,56.2108 71.3914,54.9998C 73.2861,51.2322 74.2641,46.8227 73.9773,42.6152C
73.0904,36.8953 71.9584,31.1993 70.4271,25.6173C 68.8748,20.4371 67.1365,15.1119 63.9486,10.7438C
61.2475,7.31927 58.0275,4.0285 54.1028,2.12567C 51.0377,0.639587 47.4061,0 44.0263,0.424805C 39.6494,1.0824
35.3634,3.52655 32.3735,6.78998C 31.1049,8.17462 29.4425,9.48254 29.0108,11.3102C 28.1188,12.3461
27.1706,13.3326 26.2267,14.3215C 21.3521,20.0693 16.3919,25.7438 11.4843,31.4634C 8.15582,35.3427
4.53522,39.0527 1.89386,43.429C 0.755798,45.4915 0,47.9711 0.282715,50.3098C 0.531464,52.3674 1.6452,54.431
3.20117,55.8002C 7.73056,59.7861 14.9251,59.3549 20.9584,59.3078C 22.1235,59.0661 23.2871,58.8165
24.455,58.5881C 25.0217,58.4773 25.8338,58.7169 26.1507,58.2342C 26.3399,57.9459 25.6989,57.7003
25.5606,57.3843C 25.3022,56.794 25.3646,55.6989 26.0016,55.4933C 25.451,56.2086 24.8473,57.0949
24.9554,57.9911C 25.0432,58.7194 25.7817,59.4048 26.4987,59.5601C 26.6447,59.6296 26.4932,59.0949
26.6547,59.1009C 26.8145,59.1068 26.4883,59.3764 26.38,59.4939C 25.5544,60.3889 24.7281,61.2833
23.9022,62.178'/>
23.9022,62.178'/>

<Path Canvas.Left='355.129' Canvas.Top='404.431' Fill='#07000F7A' Data='F1 M


24.9464,9.22559C 23.2963,8.43958 21.656,7.54187 20.2958,6.32104C 18.082,4.23206 15.3646,2.55212 13.7059,0C
13.2031,1.56201 13.0507,3.24976 12.3442,4.73083C 11.4792,7.91931 11.752,11.3218 11.1454,14.5695C
10.806,17.3281 10.4692,20.0873 10.1383,22.847L 7.72186,25.5746L 7.04858,26.3348C 5.10852,49.8474
3.2569,73.3671 1.41113,96.8872C 0.930054,120.427 0.464966,143.966 0,167.506C 0.754395,207.361 1.4845,247.217
2.08868,287.075C 2.82111,296.915 3.54309,306.755 4.25708,316.596C 4.63214,324.561 5.06354,332.522
5.508,340.483C 8.25519,365.156 10.9837,389.833 13.4553,414.535C 14.7129,419.301 15.9465,424.073
17.1596,428.85C 19.9568,435.634 22.6957,442.442 25.3607,449.279C 27.6284,443.746 29.9237,438.224
32.2514,432.715C 32.7256,427.875 33.2018,423.035 33.6801,418.195C 34.399,415.293 35.1234,412.391 35.85,409.49C
37.5449,392.038 39.2634,374.588 40.9512,357.135C 42.1346,330.742 42.9097,304.331 43.6682,277.923C
43.2258,241.144 42.7527,204.366 42.2294,167.589C 41.4595,157.711 40.6843,147.833 39.9045,137.956C
39.5466,130.038 39.1854,122.12 38.8226,114.202C 38.2169,109.034 37.6044,103.867 36.9937,98.7004C
36.5614,90.7147 36.1271,82.7291 35.6919,74.7435C 34.8294,70.6281 33.9664,66.5127 33.1036,62.3972C
32.5999,56.0334 32.0964,49.6697 31.5956,43.3058C 29.6036,33.7312 27.6136,24.156 25.6801,14.5695L
25.6298,14.2754C 25.4904,12.5927 25.1769,10.929 24.9464,9.22559'/>

<Path Canvas.Left='345.674' Canvas.Top='350.234' Fill='#07000F7A' Data='F1 M


18.8118,38.7074C 21.2468,42.0334 23.6741,45.3657 26.0509,48.7336C 27.9327,44.7751 29.8636,40.8385
31.8986,36.9565L 33.0494,36.845L 34.415,36.6886C 36.4921,32.985 38.5661,29.2316 41.2364,25.9301C
42.129,24.2976 42.8447,22.571 43.7642,20.9536C 43.8779,20.7928 43.9773,20.6208 44.1055,20.4714C
44.2703,20.2792 44.6795,19.925 44.7943,20.1508C 45.0959,20.7445 44.5889,21.4974 44.2578,22.0751C
43.6468,23.141 42.8009,24.0896 41.8453,24.8617C 38.9875,27.1705 34.841,28.2196 31.2011,27.7213C
28.3014,27.3245 25.4512,25.8114 23.3401,23.7301C 22.4852,22.8206 21.7622,21.778 21.165,20.6819C
20.8464,20.0972 20.827,19.1366 20.1915,18.9373C 19.7409,18.7958 19.8158,19.8191 19.7667,20.2888C
19.6146,21.7426 19.5672,23.2128 19.6478,24.6722C 19.1006,25.026 19.0613,25.8499 18.9179,26.4854C
18.8208,26.9159 18.7248,27.3468 18.638,27.7795C 18.5276,28.3297 18.4202,28.8807 18.3265,29.434C
17.9213,31.8281 17.6766,34.2571 17.6251,36.6847C 17.4634,41.818 17.5947,46.9574 17.7061,52.0922C
18.0423,54.4598 18.6656,56.7948 19.4753,59.045C 19.7509,59.8109 20.0462,60.5696 20.3188,61.3365C
20.4507,61.7075 20.9843,62.3389 20.6166,62.4797C 20.2983,62.6016 20.2314,61.9116 20.1012,61.5967C
19.7999,60.8679 19.5789,60.1044 19.4109,59.334C 18.9382,57.167 18.8779,54.8827 19.1728,52.6844C
20.0547,46.1102 24.7825,39.5095 30.6605,36.4359C 35.571,33.9669 41.8668,33.4384 47.0975,35.1266C
49.3137,35.8418 51.4362,36.9386 53.3113,38.3197C 53.7275,38.6262 54.1312,38.95 54.5337,39.2743C 54.5941,39.323
54.6542,39.3721 54.7151,39.4203C 54.7614,39.457 54.8079,39.4935 54.8552,39.5289C 55.0327,39.6622
55.1721,39.8741 55.0914,39.6364C 54.6694,38.3928 53.5994,37.4653 52.7167,36.493C 51.9558,35.6552
51.1437,34.861 50.288,34.12C 47.9581,32.1027 45.2535,30.4275 42.3635,29.3568C 37.2178,27.4894 31.2407,27.2123
25.9568,28.6427C 18.6777,30.7594 11.8685,36.4557 8.54077,43.2668C 7.30994,45.786 6.40717,48.4802
5.7854,51.2142C 5.52332,52.3666 5.32684,53.5328 5.10004,54.6926C 5.0437,54.9808 4.82208,55.8301
4.85284,55.5381C 4.30652,58.1085 4.02014,60.7434 3.95734,63.3705C 3.92651,64.6595 3.95679,65.9493
3.96777,67.2386C 3.97058,67.5643 3.97565,67.89 3.9682,68.2156C 3.96429,68.3876 3.9519,68.5593 3.93378,68.7305L
3.90552,68.8062L 3.87451,68.766C 3.03052,83.8704 2.30151,98.981 1.5766,114.092C 1.07336,131.63 0.598755,149.17
0.134888,166.709C 0.0783081,193.68 0.0476074,220.651 0,247.621C 0.813416,280.003 1.591,312.385 2.27209,344.77C
4.06897,378.376 6.24731,411.961 8.56799,445.534C 11.397,470.82 14.108,496.121 16.369,521.464C 17.0408,525.963
17.708,530.464 18.3467,534.968C 19.7426,545.349 21.072,555.741 22.2353,566.151C 24.4632,576.661 26.5471,587.21
28.2278,597.822L 37.3264,598.491C 38.684,592.426 39.9575,586.342 41.1822,580.249L 42.6612,579.08C
43.688,572.228 44.658,565.367 45.627,558.506L 47.1903,555.603C 49.4539,537.123 51.6798,518.638
53.9794,500.162C 54.5369,492.939 55.0918,485.715 55.644,478.49C 57.3571,456.904 59.0507,435.315
60.6123,413.717C 61.9012,384.065 62.4269,354.383 62.9938,324.708C 62.3004,289.143 61.5874,253.578
60.8198,218.014C 59.3654,187.78 57.8743,157.548 56.3322,127.319C 54.5167,107.802 52.6514,88.2899
50.9147,68.766C 50.8303,67.2609 50.697,65.755 50.4583,64.2665C 50.4196,64.0248 50.3737,63.7843
50.3259,63.5442C 50.1793,62.8079 50.2348,63.1576 50.1788,63.1947C 49.7936,63.45 49.9236,64.0829
49.793,64.5261C 50.0157,63.073 50.671,61.5032 50.1458,60.1301C 50.038,59.8481 49.8726,60.6694 49.7622,60.9503C
49.5223,61.5608 49.2545,62.1614 48.9539,62.7444C 48.0931,64.4138 46.9158,65.9448 45.5526,67.2372C
43.4862,69.1525 40.8694,70.5807 38.1498,71.317C 34.341,72.3035 29.9712,72.0603 26.3776,70.4583C
25.1791,69.9241 24.0306,69.2415 23.0176,68.4076C 22.5226,68 21.642,67.6323 21.7118,66.9949C 21.7386,66.7502
22.1504,67.2286 22.3344,67.3922C 22.5965,67.6254 22.8472,67.8711 23.1023,68.1119C 23.5844,68.5669
24.0608,69.0281 24.552,69.4731C 26.2487,71.0104 28.1161,72.3945 30.1354,73.4738C 35.767,76.4836
43.5902,76.5739 49.2908,73.6965C 52.6404,71.9447 55.6158,69.1595 57.5206,65.8945C 59.5493,62.4174
60.4571,58.1017 60.0863,54.0931C 59.8607,51.6547 59.1774,49.222 58.1135,47.0164C 57.7065,46.1729
57.2589,45.3464 56.7564,44.556C 56.5521,44.2347 56.4251,43.7677 56.0637,43.6477C 55.7987,43.5597
56.0923,44.2074 56.147,44.4813C 56.2564,45.0294 56.3485,45.5817 56.416,46.1366L 56.1988,45.4125C
55.0927,41.7794 53.9578,38.152 53.0159,34.4729C 52.1319,32.3099 52.2496,29.8575 52.0578,27.5288C
51.855,25.0667 51.5157,22.6057 50.953,20.2002C 50.051,19.868 50.3196,18.3801 50.1143,17.4412C 49.6321,15.2354
49.1249,13.0167 48.2993,10.9153C 46.4164,6.12256 41.647,1.7406 36.574,0.857422C 31.341,0 24.7262,3.27966
22.376,8.0332C 21.564,9.67566 21.0264,11.4739 20.7567,13.2861C 20.674,13.8417 20.6066,14.3994 20.5414,14.9573C
20.5165,15.1708 20.5031,15.3854 20.4866,15.5997C 20.4655,15.8728 20.3022,16.3268 20.5855,16.4081L
20.6191,16.4143C 21.0028,19.4744 21.5533,22.5194 22.2877,25.5148L 21.3311,28.9646L 20.3927,32.3779L
20.0176,33.7355L 19.3904,36.2739L 18.8118,38.7074'/>
<Path Canvas.Left='344.826' Canvas.Top='349.71' Fill='#07000F7A' Data='F1 M
18.0055,51.3374L 26.2379,52.269C 29.4934,47.4803 32.9479,42.8207 36.5903,38.3193L 37.0895,37.6909C
39.1846,34.1082 41.2881,30.4708 44.0224,27.3485C 44.6873,26.1339 45.2708,24.8767 45.8914,23.6389C
46.0328,23.3568 46.1652,23.0698 46.3205,22.7953C 46.5436,22.4009 46.7717,22.0083 47.0259,21.6332C
47.1281,21.4825 47.4357,21.2103 47.5085,21.3772C 47.8156,22.0809 47.1419,22.8921 46.7493,23.552C
46.0173,24.782 45.0035,25.8523 43.9021,26.7665C 40.6733,29.4467 35.8604,30.5669 31.7145,29.9189C
28.8145,29.447 25.9538,28.0433 23.794,26.0515C 22.7485,25.0873 21.8312,23.9674 21.0768,22.7617C
20.6495,22.0787 20.2777,21.3616 19.9185,20.6404C 19.7462,20.2946 19.5902,19.5637 19.2312,19.7068C
18.8307,19.8663 18.866,20.5012 18.8054,20.928C 18.6423,22.076 18.5439,23.2378 18.5501,24.3973L
18.5582,24.6713L 18.6087,25.4658C 18.0632,25.479 18.0348,26.4177 17.9213,26.9514C 17.8322,27.3705
17.7448,27.7899 17.6663,28.2112C 17.5638,28.7616 17.4644,29.3129 17.3785,29.8662C 16.9959,32.329
16.7758,34.8243 16.7491,37.3165C 16.6547,42.3434 16.8409,47.3728 17.02,52.3975L 17.0514,52.8474C
17.3582,54.8864 17.8628,56.9036 18.5385,58.8517C 18.8434,59.7311 19.1826,60.5986 19.5323,61.4612C
19.6663,61.7916 19.8036,62.1207 19.936,62.4519C 20.0259,62.6769 20.1176,62.9015 20.1993,63.1296C
20.2413,63.2468 20.2775,63.3663 20.3068,63.4873L 20.2965,63.5314C 19.9279,63.4401 19.9279,62.8644
19.7932,62.5093C 19.494,61.7211 19.2676,60.9032 19.0977,60.0774C 18.6453,57.879 18.5827,55.5764
18.8544,53.3485C 19.7094,46.337 24.7541,39.2439 31.0322,36.007C 35.5793,33.7407 41.2023,33.0032
46.1572,34.126C 48.5724,34.6732 50.9307,35.6284 53.0363,36.9319C 53.8965,37.4644 54.7188,38.0621
55.4971,38.7086C 55.7342,38.9056 55.9664,39.1085 56.1987,39.3113C 56.3171,39.4146 56.643,39.7362
56.5756,39.5942C 55.3279,36.9648 52.8438,35.062 50.5356,33.2892C 44.0924,28.3402 34.4736,26.4369
26.628,28.5474C 19.2858,30.6624 12.439,36.3293 8.9325,43.118C 7.55554,45.7839 6.57379,48.6672 5.88171,51.5869C
5.6051,52.7539 5.39868,53.9365 5.14142,55.1079C 5.08154,55.3805 4.82208,56.1691 4.84448,55.8909C
4.22772,58.6991 3.90887,61.584 3.84631,64.4586C 3.8219,65.5811 3.83167,66.7039 3.81793,67.8265C
3.81396,68.1517 3.81177,68.4772 3.79272,68.8019C 3.78302,68.9677 3.76208,69.1331 3.73175,69.2963L
3.69019,69.3536L 3.6463,69.29C 3.17035,75.2739 2.71222,81.2593 2.26318,87.2452C 1.41858,113.556
0.704102,139.871 0,166.187C 0.113953,208.351 0.292358,250.515 0.37384,292.68C 1.82379,328.789 2.84088,364.918
4.71503,401.008C 5.32477,406.11 5.93622,411.213 6.54816,416.315C 7.08435,424.292 7.63135,432.267
8.17432,440.243C 10.4283,463.378 12.6151,486.521 14.5212,509.687C 15.3065,513.813 16.0835,517.94
16.838,522.071C 17.2782,528.424 17.7042,534.777 18.0969,541.132C 20.6039,556.989 22.9133,572.887
24.6518,588.846C 26.0291,593.118 27.3398,597.413 28.5184,601.743C 28.8849,603.09 29.2091,604.448
29.4982,605.814C 29.6354,606.461 29.7468,607.115 29.8278,607.773C 29.9179,608.503 30.0065,609.388
29.5471,609.963C 29.2012,610.396 28.4159,610.514 27.9144,610.278L 25.1925,609.739L 26.8004,612.134C
27.9401,612.851 29.7205,612.802 30.8385,612.052C 32.7119,610.795 33.6826,608.531 34.8464,606.599C
37.5261,602.149 39.9961,597.576 42.4574,593.002C 43.127,587.82 43.7324,582.629 44.3177,577.436C
45.6219,572.125 46.9103,566.811 48.202,561.497C 51.5172,533.115 54.7632,504.726 58.1591,476.354C
58.7826,466.036 59.3912,455.717 59.9781,445.398C 61.5292,420.52 63.1075,395.636 63.8975,370.723C
63.9349,346.533 63.9704,322.344 63.9963,298.155C 63.5997,285.619 63.199,273.083 62.7939,260.548C
62.5966,242.193 62.3882,223.839 62.1647,205.485C 61.6497,198.896 61.1313,192.307 60.6118,185.718C
60.3856,176.43 60.1556,167.141 59.9203,157.852C 58.55,141.335 57.1623,124.819 55.7713,108.304C 55.3333,100.333
54.8918,92.3625 54.463,84.3914C 53.9023,79.3582 53.3448,74.3247 52.7983,69.29C 52.6994,67.7629 52.556,66.2336
52.2801,64.7284C 52.2366,64.4913 52.1841,64.2561 52.1285,64.0216C 52.1021,63.9103 52.0526,63.6711
51.9526,63.7268C 51.4976,63.98 51.6531,64.7242 51.5003,65.222C 51.7148,63.7563 52.594,62.03 51.7875,60.7876C
51.6685,60.6042 51.5563,61.1615 51.4773,61.3652C 51.3102,61.7958 51.1352,62.2235 50.944,62.6439C
50.3825,63.8784 49.6726,65.0541 48.8489,66.1313C 46.5005,69.2024 42.9339,71.5447 39.2093,72.5808C
35.2356,73.6278 30.6736,73.385 26.9104,71.7343C 25.5834,71.1522 24.3091,70.4031 23.1973,69.4738C
22.8561,69.1885 22.5271,68.8862 22.2286,68.5566C 22.1837,68.507 22.1399,68.4563 22.0972,68.4048C
22.0653,68.3662 22.0347,68.3267 22.0049,68.2864C 21.8266,68.0447 21.804,68.0751 21.9196,68.0851C
22.5078,68.1359 22.8069,68.8651 23.2272,69.2798C 23.8354,69.8799 24.4433,70.4812 25.077,71.0546C
26.9456,72.7451 29.0397,74.2367 31.3068,75.3368C 37.1031,78.1498 44.8751,78.0994 50.6348,75.2124C
54.2765,73.3253 57.5165,70.2786 59.5187,66.699C 61.5432,63.0792 62.465,58.66 62.1042,54.5283C 61.8804,51.9664
61.1822,49.4114 60.1014,47.0779C 59.6971,46.205 59.2532,45.3486 58.7608,44.5222C 58.575,44.2102
58.4977,43.6638 58.1362,43.6295C 57.8051,43.5981 58.2471,44.2859 58.3225,44.6099C 58.4637,45.2158
58.5727,45.8298 58.6556,46.4465C 57.6376,42.6039 56.5852,38.7665 55.7563,34.8787C 55.3058,33.6746
55.3119,32.3397 55.2449,31.0559C 54.7201,27.5215 54.3373,23.9458 53.4149,20.4937C 52.7986,20.6385
52.7891,19.3823 52.6002,18.7781C 52.5059,18.4762 52.4305,18.1688 52.3487,17.8634C 52.2543,17.5111
52.1642,17.1576 52.0717,16.8048C 51.5638,14.8685 51.0073,12.9346 50.2404,11.0856C 48.1337,6.00623
43.0284,1.3717 37.6017,0.483765C 34.4824,0 31.0217,0.554321 28.2716,2.10388C 25.7289,3.53662 23.5964,5.94104
22.4092,8.60718C 21.7022,10.1949 21.2623,11.9219 21.088,13.6511C 21.0309,14.2178 20.9916,14.786
20.9572,15.3545C 20.9441,15.5708 20.9468,15.788 20.9456,16.0048C 20.9451,16.0929 20.9482,16.181
20.9521,16.2692C 20.9554,16.3429 20.9595,16.4166 20.9672,16.4901C 20.9806,16.6168 21.0613,16.8481
21.1818,16.8065C 20.006,21.8064 19.4032,26.9274 18.7455,32.0212L 18.1647,36.0991L 18.0273,37.1221C
18.4467,40.2273 18.8652,43.3328 19.2458,46.443L 18.6623,48.7863L 18.0055,51.3374'/>

<Path Canvas.Left='497.72' Canvas.Top='341.776' Fill='#1DC4DEFF' Data='F1 M


6.95239,6.96326L 3.81732,11.0079L 1.49744,13.7304L 1.65277,14.4596C 1.91193,15.1557 2.19458,15.8431
2.48553,16.5266C 2.28241,17.4495 2.0929,18.3754 1.90857,19.3023C 3.23523,21.4387 5.62964,24.2574
4.36975,26.4338C 4.08319,26.5886 3.71814,26.3055 3.43805,26.1393C 2.11743,25.0347 1.22546,23.4941 0,22.2848C
0.0145874,22.179 0.233337,22.3209 0.296265,22.4073C 0.599548,22.8235 0.868896,23.2636 1.14801,23.6965C
1.25458,23.8617 1.35114,24.0331 1.453,24.2014C 1.57111,24.3964 1.68842,24.5918 1.8078,24.786C 2.823,26.4374
1.25458,23.8617 1.35114,24.0331 1.453,24.2014C 1.57111,24.3964 1.68842,24.5918 1.8078,24.786C 2.823,26.4374
3.93463,28.0488 5.24744,29.4751C 9.03326,33.5881 15.0244,36.2889 20.6137,36.1924C 22.1102,36.0723
23.6031,35.837 25.0605,35.4763C 29.9158,33.5793 34.5666,29.6432 36.4828,24.7955C 38.0476,20.837
37.6028,15.6162 35.2211,12.0884C 32.0238,9.86438 28.1329,8.71466 24.3391,7.8338L 16.4148,9.89679C
14.4644,11.486 12.3784,12.9499 10.1249,14.0685C 9.66455,14.4171 9.12726,14.6664 8.58148,14.8552C
7.91101,15.1439 7.52936,13.673 7.51343,12.9432C 7.48328,11.5607 7.84424,10.1592 8.3891,8.88831C
9.96191,5.21991 13.4501,2.17511 17.1825,0.760925C 18.3105,0.571472 19.4896,0.518982 20.6137,0.730164C
24.4847,0.971497 28.6016,2.63239 31.2359,5.47894C 31.9475,6.24786 32.5931,7.10583 33.0369,8.05493C
33.1642,8.32733 33.2789,8.61017 33.3406,8.90448C 33.444,9.39764 33.5236,9.63757 33.2108,9.39404C
31.8937,8.36847 31.1115,6.7973 30.1066,5.46429C 28.5355,3.99097 26.894,2.56049 25.0657,1.42181C
22.0411,0.315308 18.5023,0 15.4166,0.922729C 13.5132,2.31842 11.7286,3.87915 9.76257,5.185C 9.11066,5.7937
8.42596,6.36841 7.71973,6.91315L 7.50732,6.93237L 6.95239,6.96326'/>

<Path Canvas.Left='490.144' Canvas.Top='334.745' Fill='#1AC4DEFF' Data='F1 M


15.5926,7.00555C 11.5701,9.79462 7.3313,12.2639 3.08917,14.7059C 2.79156,15.9467 2.53406,17.1979
2.32416,18.4564L 0.686096,19.4821C 0.363831,21.5731 0.0508423,23.6768 0,25.7919C 0.528931,27.524 1.1814,29.222
1.93457,30.8691C 3.1012,32.5825 4.39459,34.2065 5.5874,35.9018C 6.38953,37.0418 7.48682,38.1697
7.61829,39.5574C 7.79694,39.6744 7.9787,39.7868 8.21027,39.9674C 8.31702,40.2428 7.68756,39.6896
7.44427,39.5221C 7.03296,39.239 6.64374,38.9235 6.26715,38.5955C 4.91339,37.3852 3.66071,36.0285
2.65942,34.5136C 2.32239,34.0037 2.00269,33.4807 1.72052,32.9385C 1.62671,32.7582 1.53558,32.5762
1.45483,32.3896C 1.42285,32.3158 1.39081,32.2419 1.36218,32.1667C 1.34979,32.1342 1.29877,32.0557
1.33185,32.0667C 1.37799,32.0821 1.39532,32.1416 1.41718,32.1851C 1.66394,32.6753 1.8963,33.1727
2.13684,33.666C 2.50507,34.4212 2.88843,35.1693 3.29102,35.9067C 4.59528,38.2956 6.2124,40.5434
8.09454,42.5095C 13.1302,47.7697 20.9078,51.0429 28.1898,51.0786C 29.7011,51.0339 31.2155,50.9119
32.7065,50.6614C 38.7632,48.8792 44.7329,45.2487 48.4681,40.1586C 51.3665,36.2089 53.1393,31.0838
53.0262,26.186C 53.1325,23.4789 52.7034,20.7055 51.7993,18.1517C 49.6996,14.9985 46.4764,12.6333
43.2191,10.6992C 40.8042,10.0073 38.33,9.53986 35.873,9.01672C 32.4534,9.01331 29.0339,9.07477
25.6143,9.06494L 25.1857,9.46521L 23.8374,10.7134L 19.496,11.4357L 16.8813,14.0739L 14.8109,14.7645C
13.3677,16.6332 11.873,18.4861 10.1392,20.0888C 10.0186,20.4022 9.91217,20.7215 9.7774,21.0291C 9.65393,21.311
9.5119,21.5847 9.36548,21.8553C 8.9826,22.5631 7.56885,23.1366 7.0423,22.5197C 6.23682,18.4148 7.89258,13.8727
10.1759,10.3677C 13.9515,4.57202 21.2803,0.391541 28.1898,0.0665283C 31.5294,0.0755005 34.9495,0.735962
38.0019,2.091C 42.1268,4.18744 46.3876,7.74561 47.4668,12.2451C 47.5659,12.4768 47.6566,12.7135
47.7203,12.9573C 47.7414,13.0381 47.7589,13.1205 47.7638,13.2039C 47.7662,13.2441 47.7732,13.3481
47.7419,13.3227C 46.4727,12.2902 45.9127,10.6093 45.0184,9.23914C 42.8801,6.7514 40.5603,4.36249
37.8984,2.44531C 35.2314,1.10181 32.2398,0 29.2549,0.0895996C 27.6707,0.137146 25.8901,0.363342
24.6808,1.38788C 24.0068,2.22296 23.4243,3.1283 22.8206,4.01556C 21.2551,4.98859 19.5356,5.73425
17.7733,6.27435L 17.653,6.3374L 16.324,6.9895L 15.5926,7.00555'/>

<Path Canvas.Left='481.15' Canvas.Top='326.828' Fill='#18C4DEFF' Data='F1 M


19.7901,10.0944C 15.4309,12.2136 10.9563,14.088 6.50464,16.0053L 5.74585,18.1586L 3.31,19.2396C
2.46783,21.7354 1.79413,24.324 1.57458,26.9489L 1.39093,27.054L 0,27.8589C 0.142334,28.602 0.347839,29.3319
0.546265,30.062L 0.782593,32.8726C 0.414673,34.8423 0.234253,36.8569 0.251404,38.8607C 1.49188,41.1116
2.84448,43.324 4.47125,45.3137L 5.07349,46.3127C 7.3573,49.0536 10.2579,51.3425 12.0578,54.4229C
12.3063,54.587 12.5642,54.7376 12.8034,54.915C 12.9465,55.0211 13.0895,55.1329 13.2017,55.2713C
13.2974,55.3895 12.9039,55.1983 12.7677,55.1307C 12.4765,54.9861 12.1933,54.8251 11.917,54.6539C
11.1082,54.1527 10.3502,53.5685 9.62402,52.9537C 7.72388,51.2663 5.97009,49.3704 4.55383,47.2604C
3.98718,46.4162 3.45453,45.546 2.98846,44.6424C 2.83264,44.3403 2.68463,44.0341 2.54785,43.7229C
2.51569,43.6497 2.42096,43.4294 2.45685,43.5009C 4.36273,47.2974 6.34589,51.1318 9.05499,54.4037C
12.4135,58.46 16.7501,61.8584 21.4955,64.1418C 26.3688,66.2621 31.8728,67.201 37.1832,66.9882C 40.2307,66.5434
43.2562,65.8474 46.1753,64.8655C 56.289,61.9764 65.9869,53.6708 69.6933,43.8271C 71.3279,38.6147
71.6398,32.7032 70.1572,27.4455C 68.9605,23.202 66.4512,19.2473 63.3729,16.0908C 59.5029,13.9483
55.2827,12.4608 51.0627,11.1345C 47.9377,10.7949 44.8091,10.4777 41.6957,10.0445C 36.2156,10.5804
30.713,11.0098 25.2068,11.0374C 24.59,11.6611 23.9762,12.2879 23.3671,12.9192L 21.661,13.1015L
20.1006,13.2519C 17.1613,16.959 14.2131,20.66 11.1901,24.2993L 11.1729,24.4354L 10.7405,26.9474C
10.3668,27.9899 9.92999,29.0189 9.36725,29.9727C 9.31708,30.2529 9.27887,30.5355 9.21674,30.8132C
9.15802,31.0759 9.0929,31.3379 9.00513,31.5923C 8.86768,31.9907 8.66119,32.5241 8.2475,32.6045C
7.90161,32.6717 7.56116,32.2983 7.38538,31.993C 6.93616,24.0764 10.302,15.4775 15.7639,9.72919C
21.1169,4.09564 29.4124,0.452026 37.1832,0.524048C 44.4268,0.659668 52.0375,3.46387 57.5153,8.20557C
59.8601,10.2354 61.8987,12.6904 63.431,15.3868C 63.7535,15.9543 64.0501,16.538 64.3084,17.1375C
64.3645,17.2676 64.4167,17.3994 64.4651,17.5326C 64.4922,17.6071 64.5912,17.8157 64.535,17.7598C
64.3818,17.6077 64.2693,17.4177 64.1613,17.2308C 63.9604,16.8834 63.7943,16.517 63.6105,16.1603C
63.5411,16.0256 63.4713,15.8911 63.4017,15.7564C 59.8184,11.7943 56.4935,7.47455 52.2026,4.29224C
51.397,3.86493 50.5798,3.45599 49.7395,3.10168C 47.1738,1.64606 44.3718,0.414673 41.4513,0C 41.0839,0.0725098
40.6993,0.085144 40.3489,0.217529C 39.8161,0.418823 39.3334,0.733826 38.8256,0.992004C 38.2277,1.1131
37.8528,1.99133 37.9419,2.59491C 37.871,3.11829 37.8608,3.64856 37.846,4.17651C 35.9609,6.01746
33.2706,7.11163 30.6602,7.4704C 30.1045,7.65564 29.5588,7.87396 28.9931,8.02606C 27.491,8.42993
25.9717,8.76672 24.461,9.13708C 23.1506,9.58038 21.8044,9.94086 20.4378,10.1554L 19.7901,10.0944'/>

<Path Canvas.Left='195.392' Canvas.Top='299.397' Fill='#0BFFFFFF' Data='F1 M


9.16724,28.4007C 15.1577,33.8283 22.7307,37.4866 30.3297,40.2433C 42.3451,44.6022 55.0782,46.869
66.9612,51.5768C 83.3445,58.0677 99.3385,65.5357 115.839,71.7235C 125.403,75.3104 135.146,78.7107
145.208,80.4741C 165.18,83.4549 185.562,83.8677 205.736,82.9918C 230.7,81.9081 255.878,78.5641
279.776,71.2646C 290.016,68.1369 300.043,64.093 309.471,59.0191C 312.547,57.3643 315.56,55.5853
318.478,53.6677C 319.894,52.7375 321.214,51.6227 322.762,50.935C 326.711,49.1807 331.073,48.5516
335.287,47.5955C 342.207,46.0251 349.161,44.4485 355.84,42.051C 368.592,37.4736 381.032,29.0035
388.271,17.5515L 393.913,0L 393.691,7.67468L 390.306,18.2055C 384.651,29.4542 375.527,39.2471 365.155,46.3835C
354.92,53.4261 343.065,57.7786 332.277,63.9413C 327.735,66.5355 323.557,69.7377 318.993,72.2916C
310.609,76.9833 301.739,80.8506 292.69,84.0781C 269.229,92.4453 244.177,96.5443 219.33,98.2936C
193.927,100.082 168.171,99.6116 142.968,95.9592C 131.957,94.1539 121.23,90.7247 110.724,86.9653C
92.1394,80.315 74.2321,71.8701 56.3553,63.5018C 43.9037,57.6731 30.9771,52.5536 19.503,44.9797C
11.8763,39.9453 4.70587,33.546 0,25.7123C 2.90372,27.0197 6.02472,27.8857 9.16724,28.4007'/>

<Path Canvas.Left='188.035' Canvas.Top='307.071' Fill='#15FFFFFF' Data='F1 M


7.3566,18.0377C 12.0625,25.8713 19.2329,32.2706 26.8596,37.305C 38.3336,44.879 51.2603,49.9984
63.7119,55.8271C 81.5887,64.1954 99.496,72.6403 118.08,79.2906C 128.586,83.05 139.313,86.4792 150.324,88.2845C
175.527,91.9369 201.284,92.4073 226.687,90.6189C 251.533,88.8696 276.586,84.7706 300.046,76.4034C
309.096,73.176 317.965,69.3087 326.35,64.6169C 330.914,62.063 335.092,58.8608 339.633,56.2666C 350.421,50.1039
362.276,45.7514 372.512,38.7089C 382.884,31.5724 392.008,21.7795 397.663,10.5308L 401.048,0L 400.826,7.67456L
399.697,11.1848C 395.641,21.6917 389.864,31.7017 382.676,40.3724C 373.259,51.7317 361.34,60.9622
349.148,69.2728C 341.23,74.6703 333.037,79.7544 324.392,83.8893C 301.458,94.8588 276.139,101.073
250.935,104.401C 216.946,108.89 182.033,108.556 148.085,103.769C 134.228,101.604 120.701,97.3915
107.516,92.6107C 89.6569,86.1353 72.2766,78.14 55.7549,68.7643C 41.3441,60.5865 26.9979,51.4404
15.7173,39.304C 8.81592,31.879 2.99496,22.9538 0,13.2693C 2.22131,15.1681 4.72168,16.774 7.3566,18.0377'/>

<Path Canvas.Left='182.169' Canvas.Top='314.148' Fill='#24FFFFFF' Data='F1 M


5.86661,6.19275C 8.86157,15.8773 14.6825,24.8024 21.5839,32.2274C 32.8645,44.3639 47.2108,53.5099
61.6215,61.6877C 78.1432,71.0635 95.5235,79.0587 113.382,85.5342C 126.568,90.315 140.094,94.527
153.951,96.6929C 187.9,101.48 222.813,101.813 256.802,97.3246C 282.005,93.9961 307.325,87.7822
330.259,76.8127C 338.904,72.6779 347.096,67.5938 355.015,62.1963C 367.206,53.8857 379.126,44.6552
388.543,33.2958C 395.731,24.6251 401.508,14.6152 405.564,4.10828L 406.692,0.598022L 406.581,4.4353L
406.557,7.14771L 406.577,8.34235C 401.398,26.1171 393.369,43.6141 381.744,58.0235C 373.124,68.7085
362.118,77.6587 350.259,84.5754C 328.304,97.3807 303.414,105.423 278.456,110.233C 236.967,118.229
193.571,117.931 151.711,112.178C 131.566,109.139 111.874,102.823 93.0394,95.0553C 70.988,85.9613
49.3723,73.9714 32.1415,57.4769C 22.0566,47.823 13.1161,36.4785 7.19189,23.837C 3.6701,16.3218 1.65955,8.13184
0,0C 1.88907,2.12524 3.74274,4.30212 5.86661,6.19275'/>

<Path Canvas.Left='176.506' Canvas.Top='307.777' Fill='#15FFFFFF' Data='F1 M


5.66287,6.37067C 7.32242,14.5025 9.33298,22.6925 12.8548,30.2076C 18.7789,42.8491 27.7195,54.1937
37.8044,63.8476C 55.0351,80.342 76.6509,92.332 98.7023,101.426C 117.537,109.193 137.229,115.51
157.374,118.548C 199.234,124.302 242.629,124.6 284.119,116.604C 309.077,111.794 333.967,103.751
355.922,90.9461C 367.781,84.0294 378.787,75.0792 387.407,64.3942C 399.032,49.9848 407.06,32.4877
412.24,14.713C 412.385,17.5458 412.696,20.376 413.187,23.1697C 409.798,41.3376 404.78,59.8322 395.118,75.587C
390.397,83.2855 384.844,90.8654 377.59,96.2452C 355.66,112.511 329.096,122.632 302.585,129.166C
254.837,140.934 203.875,140.574 155.135,134.033C 133.68,130.886 112.559,124.688 92.5061,116.435C
73.5291,108.626 54.7781,98.5003 40.0512,84.2094C 26.3458,70.9098 15.2178,54.2681 8.48596,36.3964C
4.09467,24.7385 2.491,12.2059 0,0L 5.66287,6.37067'/>

<Path Canvas.Left='170.843' Canvas.Top='301.407' Fill='#0BFFFFFF' Data='F1 M


5.66284,6.37073C 8.15384,18.5767 9.75751,31.1093 14.1488,42.7672C 20.8807,60.6389 32.0087,77.2805
45.714,90.5801C 60.441,104.871 79.1919,114.997 98.1689,122.806C 118.222,131.058 139.342,137.257
160.797,140.404C 209.538,146.945 260.5,147.304 308.248,135.537C 334.759,129.003 361.323,118.882
383.253,102.616C 390.507,97.2361 396.06,89.6562 400.781,81.9578C 410.443,66.2029 415.46,47.7084
418.85,29.5404C 419.549,32.8535 420.436,36.1308 421.478,39.3528C 420.262,57.0321 417.463,75.1791
410.041,91.2712C 405.836,100.388 400.602,109.758 392.608,115.833C 385.66,121.112 378.026,125.468
370.325,129.572C 352.056,139.307 332.248,146.351 312.146,151.293C 282.887,158.486 252.405,161.341
222.277,160.995C 200.97,160.75 179.684,158.661 158.558,155.889C 134.603,152.452 110.854,145.964
88.6201,136.408C 70.9781,128.825 53.4948,118.957 40.3623,104.947C 25.9446,89.5665 15.5068,69.9648
9.44882,49.7724C 7.35947,42.8082 5.78204,35.6675 4.77164,28.4672C 4.28711,25.0143 4.34622,21.4872
3.68643,18.0635C 2.52356,12.0293 1.22882,6.02118 0,0L 5.66284,6.37073'/>

<Path Canvas.Left='357.949' Canvas.Top='210.203' Data='F1 M 0,46.1263L


2.25165,50.6733L 7.34521,55.0236L 8.74432,55.3953L 10.843,56.9911L 12.5918,57.7999L 13.6411,59.0679L
15.39,59.9205L 19.5873,62.6531L 24.1343,65.4512L 25.8832,66.0852L 31.8293,69.6485L 33.5782,70.2825L
38.1252,73.1681L 39.5243,73.6272L 40.9234,74.6109L 45.1207,75.223L 46.17,74.1081L 47.1537,68.162L
49.3179,62.5656L 51.0668,61.713L 52.1161,60.467L 61.9098,56.6413L 73.8021,56.532L 75.2012,55.2859L
82.8962,55.1985L 83.5957,54.1711L 88.1428,53.4278L 91.2907,51.2198L 92.6898,50.8482L 94.7885,49.2524L
101.434,46.3886L 110.528,42.1476L 119.622,37.9503L 130.115,32.8349L 130.815,30.7363L 129.066,27.5883L
127.317,26.7357L 122.836,21.6422L 122.77,19.1938L 121.021,18.3412L 113.676,13.4881L 112.277,13.0291L
127.317,26.7357L 122.836,21.6422L 122.77,19.1938L 121.021,18.3412L 113.676,13.4881L 112.277,13.0291L
110.178,11.4988L 108.43,10.6462L 105.981,9.3783L 102.833,8.65686L 98.9857,6.42706L 93.0396,4.9624L
88.4925,2.77631L 83.5957,2.71069L 82.1966,1.3772L 75.2012,1.28979L 73.8021,0L 59.8112,0.677673L
57.0129,3.41028L 54.9143,3.51959L 52.1161,6.07727L 49.6677,6.66754L 36.7261,13.7067L 35.327,14.1658L
32.5289,16.5486L 30.0804,17.2263L 29.0311,18.4942L 27.2823,19.3468L 19.937,24.1562L 17.8384,24.5715L
12.9416,29.1841L 11.5425,29.4683L 8.39453,32.8349L 7.54199,34.5838L 4.19727,37.7318L 0.349731,45.7765L
0,46.1263'>
<Shape.Fill>
<!-- black transparency -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='165.385,3.7973'
EndPoint='-39.6154,117.131'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#00000000' Offset='0'/>
<GradientStop Color='#80000000' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='357.949' Canvas.Top='209.612' Data='F1 M 0,45.3174L


0.502808,49.5147L 5.94611,54.7614L 7.69501,55.6139L 8.74432,56.86L 11.8923,58.4121L 12.9416,59.6581L
14.6904,60.5107L 17.4886,61.9316L 19.2375,63.8554L 20.9864,64.708L 23.4348,65.9759L 25.1837,66.7848L
31.1298,70.3699L 32.5289,70.6104L 34.6275,72.403L 36.0266,72.7746L 37.4257,73.8458L 38.8248,74.13L
40.2239,75.2886L 45.1207,75.7477L 46.17,74.6984L 47.5909,68.0527L 50.7608,62.1066L 59.8112,58.1716L
66.4568,57.3627L 71.7034,56.5757L 82.1966,56.4883L 82.8962,55.4609L 88.8423,53.9962L 91.9902,51.8101L
93.3893,51.4385L 95.488,49.8427L 102.134,46.9789L 108.43,44.1588L 112.277,42.1476L 120.322,38.5625L
130.115,33.6001L 131.034,31.3265L 129.875,29.9274L 129.678,28.5284L 127.667,26.7795L 125.918,25.9269L
125.175,23.9813L 123.12,22.2324L 122.661,19.4343L 119.972,17.9915L 117.174,15.3463L 115.075,15.0402L
110.878,12.0016L 109.129,11.3676L 106.681,9.9248L 100.735,7.84802L 95.488,5.68384L 93.3893,5.33405L
91.9902,4.13171L 89.1921,3.80377L 87.793,2.86377L 82.8962,2.36096L 81.4971,1.50842L 72.0532,0.808838L
68.9052,0L 59.8112,0.699585L 56.3134,3.82568L 53.865,4.56891L 48.6184,7.95734L 46.5198,8.37268L
44.4211,10.0997L 40.5737,11.4114L 36.0266,14.297L 34.6275,14.756L 31.8293,17.1389L 29.3809,17.8166L
28.3316,19.0845L 26.5827,19.9371L 19.2375,24.7465L 17.4886,25.446L 16.4393,26.7795L 14.6904,27.6321L
9.09406,32.3977L 1.31165,42.5193L 0.415344,44.9677L 0,45.3174'>
<Shape.Fill>
<!-- black transparency -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='165.385,4.38757'
EndPoint='-39.6154,117.721'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#00000000' Offset='0'/>
<GradientStop Color='#56000000' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='356.55' Canvas.Top='208.235' Data='F1 M 0,46.6946L


0.502808,50.8919L 5.15918,56.1385L 6.99548,56.9474L 16.4393,63.8335L 18.1882,64.6861L 24.1343,68.7303L
26.233,69.2332L 28.3316,70.8946L 30.0804,71.5941L 32.5289,72.9932L 34.2778,73.6927L 38.8248,76.5128L
40.5737,77.1467L 44.4211,78.7645L 48.2687,77.6933L 49.9301,71.8783L 50.1705,69.7797L 51.2855,68.3806L
51.6571,66.2819L 54.2148,63.8335L 59.4614,61.6693L 64.708,60.0079L 78.3491,59.5925L 81.4971,58.6525L
85.6943,58.4776L 87.0934,57.2753L 89.1921,57.0348L 91.2907,55.3734L 96.5373,53.2529L 97.5866,51.9412L
100.735,51.1761L 104.582,48.9901L 107.031,48.3124L 110.878,46.2793L 114.726,44.7272L 115.775,43.5467L
118.923,42.7816L 122.77,40.5955L 125.219,39.9178L 132.914,35.48L 133.635,32.7037L 132.87,31.3046L
131.864,28.8563L 130.115,28.0037L 125.634,22.9101L 125.568,20.4617L 123.82,19.6091L 122.77,18.363L
121.021,17.5105L 117.873,15.4556L 116.474,14.9965L 114.376,13.4662L 112.627,12.6136L 108.08,9.88104L
105.282,9.37823L 103.883,8.43823L 101.434,7.69501L 97.5866,6.31775L 95.1382,5.64008L 88.4926,2.84186L
82.5464,2.2298L 79.3984,1.28979L 70.3043,1.02747L 68.9053,0L 62.6094,1.20233L 60.5107,1.24603L
57.7125,3.97864L 56.3134,4.04425L 54.2148,6.09912L 52.1161,6.14288L 50.717,7.86987L 37.0759,14.2969L
18.538,26.058L 16.7891,26.9106L 15.7398,28.1567L 13.9909,29.0093L 8.39453,33.7749L 5.13727,38.3001L
2.53589,41.0983L 2.29541,43.1969L 0.633972,45.2956L 0.349792,46.3449L 0,46.6946'>
<Shape.Fill>
<!-- black transparency -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='166.784,5.76477'
EndPoint='-38.2162,119.098'>
<GradientBrush.GradientStops>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#00000000' Offset='0'/>
<GradientStop Color='#40000000' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='327.487' Canvas.Top='169.781' Data='F1 M 6.11859,86.8539C


10.5705,79.0605 37.7747,31.5833 41.2338,16.0237C 44.7961,0 125.313,27.6862 114.113,39.6862C 84.7654,71.13
71.0471,102.796 61.8223,109.764C 56.5026,113.782 31.2289,110.497 25.0466,108.003C 13.6072,103.388 0,97.5649
6.11859,86.8539M 74.118,24.5605C 61.493,20.5229 48.7491,25.0961 45.6536,34.7753C 42.558,44.4544 50.2831,55.574
62.908,59.6117C 75.5329,63.6494 88.2769,59.076 91.3724,49.3969C 94.468,39.7178 86.7429,28.5982 74.118,24.5605M
43.6238,68.4397C 33.8737,66.7836 24.961,71.3799 23.7167,78.7057C 23.2955,81.1852 23.8068,83.6595
25.0456,85.9125C 26.491,82.1928 34.616,72.6575 47.513,75.5528C 62.1796,80.2194 51.8463,90.2194 50.1796,93.886L
49.6543,94.2901C 54.6124,92.6638 58.2617,89.1969 59.025,84.7028C 60.2692,77.3769 53.3739,70.0957
43.6238,68.4397'>
<Shape.Fill>
<!-- fade -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='0,56.8909'
EndPoint='125.313,56.8909'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FFFFFFFF' Offset='0'/>
<GradientStop Color='#FF646464' Offset='0.734375'/>
<GradientStop Color='#FF828282' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='410.756' Canvas.Top='252.354' Fill='#34FFFFFF' Data='F1 M


0,67.7446C 2.08478,67.3273 3.74945,65.61 5.20978,64.0647C 6.91315,62.2622 8.60797,60.4509 10.3549,58.6906C
12.6744,56.4174 15.4205,54.0102 16.1248,50.8398C 17.1721,43.1564 14.4272,35.4232 13.7249,27.7006C
13.3411,23.4803 13.6236,18.9871 15.2684,15.0817C 16.7913,12.0491 19.2679,9.36084 22.1643,7.59253C
27.0517,4.60858 32.915,3.32886 37.5743,0L 38.0807,0.632996C 33.3998,3.98413 27.5107,5.28796 22.6078,8.30505C
19.8582,9.99707 17.4988,12.5513 16.0587,15.4409C 14.338,19.5628 14.2465,24.3422 14.7672,28.7783C
15.635,36.1715 18.0989,43.5848 17.2125,50.9758C 16.5406,54.3965 13.6693,57.0749 11.1906,59.5262C
7.86511,62.8911 4.81641,67.5496 0.177612,68.4786L 0,67.7446'/>

<Path Canvas.Left='410.934' Canvas.Top='252.987' Fill='#67FFFFFF' Data='F1 M


0,67.8456C 4.63879,66.9166 7.6875,62.2581 11.013,58.8932C 13.4916,56.4419 16.363,53.7635 17.0349,50.3428C
17.9213,42.9518 15.4574,35.5385 14.5896,28.1453C 14.0689,23.7092 14.1603,18.9298 15.881,14.8079C
17.3212,11.9183 19.6806,9.36407 22.4302,7.67206C 27.3331,4.65497 33.2222,3.35114 37.9031,0L 38.4116,0.63147C
33.708,4.00494 27.7919,5.33246 22.8738,8.38464C 20.2707,10.0001 18.0288,12.4207 16.6713,15.1671C
15.0269,19.1457 14.9866,23.7567 15.5095,28.0299C 16.4245,35.5076 18.9128,42.9868 18.1226,50.4788C
17.4673,54.1464 14.4858,57.0971 11.8486,59.7289C 8.42712,63.2056 4.91394,67.351 0.177673,68.5797L 0,67.8456'/>

<Path Canvas.Left='411.111' Canvas.Top='253.618' Fill='#B3FFFFFF' Data='F1 M


0,67.9482C 4.72693,66.7257 8.24628,62.5774 11.671,59.0974C 14.3081,56.4656 17.2897,53.5149 17.9449,49.8473C
18.7352,42.3553 16.2468,34.8762 15.3318,27.3984C 14.809,23.1252 14.8492,18.5142 16.4937,14.5356C
17.8511,11.7892 20.093,9.36865 22.6961,7.75317C 27.6143,4.70099 33.5303,3.37347 38.2339,0L 38.4888,0.315308L
38.7437,0.630005L 38.7316,0.639099C 34.2233,3.87854 28.6613,5.33954 23.8198,8.05615C 21.0699,9.59918
18.6701,12.0627 17.2839,14.8949C 15.5741,19.0787 15.7562,23.9534 16.4089,28.4257C 17.4543,35.5887
19.7004,42.7753 19.0326,49.9833C 18.3844,53.8963 15.3016,57.1188 12.5067,59.9331C 8.97974,63.5322
5.08801,67.5483 0.17804,68.6817L 0.0888062,68.3152L 0,67.9482'/>

<Path Canvas.Left='411.289' Canvas.Top='254.248' Fill='#67FFFFFF' Data='F1 M


0,68.0517C 4.90997,66.9183 8.8017,62.9022 12.3286,59.3031C 15.1236,56.4888 18.2064,53.2663 18.8546,49.3533C
19.5223,42.1453 17.2762,34.9587 16.2308,27.7957C 15.5781,23.3234 15.3961,18.4487 17.1059,14.2649C
18.4921,11.4327 20.8918,8.96918 23.6418,7.42615C 28.4832,4.70953 34.0452,3.24854 38.5536,0.00909424L
38.5657,0L 39.0757,0.629517L 39.0394,0.656738C 34.5077,3.91809 28.9164,5.39667 24.0592,8.14996C
21.4672,9.61926 19.1947,11.9424 17.8962,14.6241C 16.127,19.0096 16.5592,24.1352 17.3359,28.7999C
18.4776,35.6564 20.5039,42.561 19.9423,49.4892C 19.295,53.647 16.1161,57.14 13.1642,60.1388C 9.53333,63.8604
5.27429,67.7368 0.181641,68.7849L 0,68.0517'/>

<Path Canvas.Left='411.471' Canvas.Top='254.878' Fill='#34FFFFFF' Data='F1 M


<Path Canvas.Left='411.471' Canvas.Top='254.878' Fill='#34FFFFFF' Data='F1 M
0,68.1553C 5.09265,67.1072 9.35168,63.2308 12.9826,59.5093C 15.9344,56.5105 19.1133,53.0175 19.7606,48.8597C
20.3223,41.9315 18.296,35.0269 17.1543,28.1704C 16.3776,23.5057 15.9454,18.3801 17.7145,13.9946C
19.0131,11.3129 21.2855,8.98975 23.8776,7.52045C 28.7347,4.76715 34.326,3.28857 38.8577,0.0272217L 38.894,0L
39.404,0.629578L 39.3435,0.674927C 35.1974,3.66302 30.1548,5.15442 25.6205,7.51208C 22.7011,9.03003
19.9243,11.3853 18.5048,14.3538C 16.8214,18.5902 17.309,23.5304 18.0817,28.023C 19.277,34.9724 21.3446,41.9617
20.8483,48.9957C 20.1978,53.3979 16.9261,57.1599 13.8183,60.3449C 10.0817,64.1918 5.46051,67.9196
0.185974,68.889L 0,68.1553'/>

<Path Canvas.Left='258.916' Canvas.Top='234.899' Fill='#34FFFFFF' Data='F1 M


9.34036,67.1276C 7.74176,64.4633 5.58368,62.1164 4.29852,59.2875C 1.45831,53.0355 0,44.9661 2.88663,38.7354C
7.55756,30.1216 15.816,23.8082 23.6617,17.938C 31.5511,12.2804 42.2499,12.2303 51.7554,10.2565C
61.7777,7.87329 71.3441,3.82593 80.909,0L 81.299,0.893555C 71.6789,4.74982 62.0527,8.82172 51.9668,11.2075C
42.5879,13.1431 32.0143,13.1177 24.2305,18.6964C 16.5043,24.4789 8.35754,30.687 3.76547,39.1749C
2.00134,42.9901 1.77084,47.6577 2.75455,51.7443C 4.05179,57.1332 7.02481,62.0178 9.87772,66.7701L
9.34036,67.1276'/>

<Path Canvas.Left='260.687' Canvas.Top='235.793' Fill='#67FFFFFF' Data='F1 M


8.10687,65.8766C 5.25397,61.1242 2.28094,56.2397 0.983704,50.8507C 0,46.7641 0.230499,42.0965 1.99463,38.2813C
6.5867,29.7934 14.7335,23.5854 22.4597,17.8029C 30.2435,12.2242 40.8171,12.2495 50.1959,10.3139C
60.2818,7.92816 69.908,3.85626 79.5281,0L 79.918,0.893677C 70.2426,4.78003 60.5567,8.8764 50.4073,11.2649C
41.1552,13.1633 30.707,13.0617 23.0285,18.5612C 15.4217,24.2559 7.38654,30.3586 2.87347,38.7207C
1.3252,42.0768 1.0719,46.1216 1.76151,49.7527C 2.83054,55.3816 5.65121,60.616 8.64423,65.5192L
8.10687,65.8766'/>

<Path Canvas.Left='261.759' Canvas.Top='236.687' Fill='#B3FFFFFF' Data='F1 M


7.57233,64.6255C 4.58481,59.7308 1.75955,54.4928 0.689606,48.8591C 0,45.228 0.253296,41.1831 1.80157,37.827C
6.31464,29.465 14.3498,23.3622 21.9566,17.6675C 29.6351,12.168 40.0833,12.2697 49.3354,10.3712C
59.4848,7.98273 69.1707,3.88635 78.8461,0L 79.0409,0.446655L 79.2359,0.893616L 79.222,0.89917C 69.4962,4.81415
59.7547,8.93176 49.5467,11.3223C 40.4214,13.1837 30.0983,13.0051 22.5254,18.426C 15.0381,24.0328
7.11377,30.0298 2.68042,38.2665C 1.22299,41.4335 1.00943,45.2498 1.65762,48.6752C 2.70346,54.2021
5.34033,59.3721 8.10999,64.2679L 7.841,64.4468L 7.57233,64.6255'/>

<Path Canvas.Left='262.768' Canvas.Top='237.58' Fill='#67FFFFFF' Data='F1 M


7.10056,63.3743C 4.3309,58.4785 1.69403,53.3085 0.648193,47.7816C 0,44.3561 0.213562,40.5399 1.67099,37.3729C
6.10434,29.1362 14.0287,23.1392 21.516,17.5323C 29.0889,12.1115 39.412,12.29 48.5372,10.4286C 58.7453,8.03815
68.4867,3.92053 78.2125,0.0055542L 78.2265,0L 78.6163,0.893677L 78.5745,0.9104C 68.8029,4.85205
59.0103,8.98846 48.7486,11.3796C 39.7502,13.2052 29.5528,12.9492 22.0848,18.2907C 14.7168,23.8096
6.9035,29.7011 2.54984,37.8123C 1.07181,41.034 0.96524,44.97 1.785,48.4185C 2.99747,53.5191 5.21484,58.3681
7.63962,63.0164L 7.10056,63.3743'/>

<Path Canvas.Left='263.734' Canvas.Top='238.474' Fill='#34FFFFFF' Data='F1 M


6.67438,62.1227C 4.2496,57.4744 2.03223,52.6254 0.819763,47.5248C 0,44.0764 0.106567,40.1403 1.58459,36.9186C
5.93826,28.8074 13.7516,22.916 21.1195,17.397C 28.5875,12.0555 38.785,12.3115 47.7833,10.486C 58.0451,8.09479
67.8376,3.95837 77.6092,0.0167236L 77.651,0L 78.0408,0.893616L 77.9711,0.921509C 68.1537,4.89001
58.3101,9.04492 47.9947,11.437C 39.1232,13.227 29.0515,12.8933 21.6883,18.1555C 14.4398,23.5865
6.73688,29.3721 2.46344,37.358C 0.862305,40.8607 1.14102,45.2012 2.18402,48.9085C 3.43027,53.3382
5.22934,57.613 7.21494,61.7642L 6.67438,62.1227'/>

<Path Canvas.Left='339.642' Canvas.Top='204.55' Fill='#34FFFFFF' Data='F1 M


0.294922,57.1851C 3.99194,58.9359 8.06232,59.7617 11.8892,61.2068C 21.8054,64.9515 33.8701,67.807
43.5982,63.598C 44.7615,63.2772 45.5107,62.1172 46.3746,61.2747C 47.5225,60.1553 48.624,58.9884
49.7097,57.8085C 53.3466,53.8562 56.7667,49.7014 60.0459,45.4476C 71.668,30.3716 80.6523,12.9271 94.6255,0L
95.4532,0.845581C 81.6072,13.8033 72.4127,30.9731 61.0871,46.1832C 57.8654,50.5098 54.5494,54.7747
51.0124,58.8475C 49.0028,61.1615 47.1854,63.9196 44.4353,65.2722C 37.8188,68.2621 29.7314,67.3256
22.6573,65.6903C 17.858,64.5809 13.2344,62.8023 8.59973,61.134C 5.71863,60.0969 2.76703,59.2157 0,57.9044L
0.294922,57.1851'/>

<Path Canvas.Left='339.347' Canvas.Top='205.396' Fill='#67FFFFFF' Data='F1 M


0.294922,57.0588C 3.06195,58.3701 6.01355,59.2513 8.89465,60.2884C 13.5294,61.9567 18.153,63.7353
22.9522,64.8447C 30.0263,66.48 38.1138,67.4165 44.7302,64.4266C 47.4803,63.074 49.2977,60.3159 51.3073,58.002C
54.8444,53.9291 58.1603,49.6642 61.382,45.3376C 72.7076,30.1276 81.9022,12.9577 95.7482,0L 96.5738,0.847046C
90.6726,6.43646 85.7949,13.049 81.0219,19.6279C 74.6934,28.3509 68.715,37.3236 62.4233,46.0731C
59.2585,50.4742 56.0483,54.8502 52.61,59.041C 50.5016,61.6107 48.5097,64.5544 45.5673,66.1008C 39.6474,68.8519
32.3853,67.9818 25.9916,66.6644C 17.0305,64.8181 8.34656,61.5762 0,57.7781L 0.294922,57.0588'/>

<Path Canvas.Left='339.053' Canvas.Top='206.243' Fill='#B3FFFFFF' Data='F1 M


0.2948,56.931C 8.62787,60.7253 17.3185,63.9697 26.2864,65.8174C 32.6801,67.1347 39.9422,68.0048
45.8621,65.2537C 48.8045,63.7074 50.7964,60.7637 52.9048,58.1939C 56.3431,54.0031 59.5533,49.6271
62.7181,45.2261C 69.0098,36.4766 74.9882,27.5038 81.3167,18.7809C 86.0897,12.2019 90.9674,5.58942 96.8686,0L
62.7181,45.2261C 69.0098,36.4766 74.9882,27.5038 81.3167,18.7809C 86.0897,12.2019 90.9674,5.58942 96.8686,0L
97.2807,0.424133L 97.6927,0.848694L 97.6774,0.86261C 91.867,6.4364 87.0983,13.0296 82.3577,19.5376C
76.3192,27.8272 70.4709,36.2545 64.6375,44.6896C 61.4653,49.2765 58.2964,53.8705 54.9181,58.3079C
52.5132,61.4666 50.1979,65.0515 46.6992,66.9278C 40.4779,69.8781 32.753,68.4758 26.0432,66.9312C
17.0623,64.8636 8.31165,61.6313 0,57.6504L 0.1474,57.2906L 0.2948,56.931'/>

<Path Canvas.Left='338.758' Canvas.Top='207.091' Fill='#67FFFFFF' Data='F1 M


0.294861,56.8017C 8.60651,60.7826 17.3571,64.015 26.338,66.0825C 33.0479,67.6271 40.7728,69.0294
46.994,66.0791C 50.4927,64.2028 52.808,60.6179 55.213,57.4592C 58.5912,53.0219 61.7601,48.4278
64.9323,43.8409C 70.7657,35.4058 76.6141,26.9785 82.6525,18.6889C 87.3931,12.1809 92.1619,5.58771
97.9722,0.013916L 97.9875,0L 98.8119,0.849243L 98.7658,0.89093C 92.6783,6.80969 87.7601,13.8442
82.7697,20.7133C 77.0529,28.5822 71.3502,36.4675 65.95,44.557C 62.8376,49.2192 59.7719,53.9158 56.4994,58.467C
54.0273,61.9049 51.554,65.7357 47.8311,67.7533C 41.3,70.8959 33.1196,68.9803 26.0947,67.1962C 17.1035,64.9127
8.28662,61.6924 0,57.5223L 0.294861,56.8017'/>

<Path Canvas.Left='338.463' Canvas.Top='207.941' Fill='#34FFFFFF' Data='F1 M


0.294861,56.6731C 8.58148,60.8432 17.3983,64.0634 26.3896,66.347C 33.4144,68.1311 41.5948,70.0466
48.126,66.9041C 51.8489,64.8865 54.3222,61.0557 56.7943,57.6177C 60.0668,53.0666 63.1325,48.3699
66.2448,43.7078C 71.6451,35.6182 77.3477,27.733 83.0646,19.864C 88.055,12.9949 92.9732,5.96045
99.0607,0.041687L 99.1068,0L 99.931,0.849304L 99.8542,0.918762C 93.8694,6.82184 89.0602,13.8246
84.1057,20.6155C 78.376,28.4688 72.5269,36.2514 67.2624,44.4238C 64.2097,49.1628 61.2484,53.9626
58.0807,58.6255C 55.5524,62.3472 52.9133,66.4244 48.9631,68.5782C 42.1163,71.9107 33.4841,69.4955
26.1463,67.4607C 20.1036,65.785 13.9858,64.2005 8.24481,61.6778C 5.40955,60.4319 2.73871,58.841 0,57.3953L
0.294861,56.6731'/>

<Path Canvas.Left='387.498' Canvas.Top='202.385' Fill='#345C5C5C' Data='F1 M


0,72.1277C 1.89215,69.4163 2.92365,66.1876 4.63013,63.3557C 11.849,51.3762 19.7269,39.7951 27.7968,28.3716C
34.4945,18.9975 42.23,10.2262 47.5364,0L 48.9878,0.780273C 43.4214,10.9429 35.606,19.7009 28.879,29.1355C
20.8279,40.5582 13.1551,52.2502 5.72119,64.0839C 3.97296,66.8668 2.61469,69.8937 0.734314,72.5892L
0,72.1277'/>

<Path Canvas.Left='388.232' Canvas.Top='203.166' Fill='#675C5C5C' Data='F1 M


0,71.8089C 1.88037,69.1135 3.23865,66.0865 4.98688,63.3036C 12.4208,51.47 20.0936,39.7779 28.1447,28.3552C
34.8717,18.9206 42.6871,10.1627 48.2535,0L 49.7071,0.778809C 43.8956,10.8818 35.9844,19.6226 29.227,29.1191C
19.3155,43.2123 10.3409,57.9425 0.734253,72.2704L 0,71.8089'/>

<Path Canvas.Left='388.966' Canvas.Top='203.944' Fill='#B35C5C5C' Data='F1 M


0,71.4916C 9.60175,57.1772 18.5772,42.4392 28.4927,28.3403C 35.2501,18.8438 43.1613,10.103 48.9728,0L
49.7004,0.388916L 50.428,0.777466L 50.4178,0.795593C 44.3771,10.8365 36.3591,19.5498 29.5749,29.1042C
19.6871,43.1987 10.7889,57.9771 0.734436,71.9531L 0.367126,71.7223L 0,71.4916'/>

<Path Canvas.Left='389.701' Canvas.Top='204.722' Fill='#675C5C5C' Data='F1 M


0,71.1757C 10.0544,57.1996 18.9526,42.4212 28.8405,28.3268C 35.6246,18.7723 43.6426,10.0591 49.6833,0.0181274L
49.6936,0L 51.1488,0.7771L 51.118,0.831482C 44.8629,10.8074 36.7303,19.4832 29.9227,29.0907C 20.0602,43.1806
11.238,58.0181 0.736084,71.6381L 0,71.1757'/>

<Path Canvas.Left='390.437' Canvas.Top='205.499' Fill='#345C5C5C' Data='F1 M 0,70.861C


10.5019,57.241 19.3242,42.4035 29.1866,28.3136C 35.9942,18.7061 44.1268,10.0303 50.3819,0.0543823L 50.4127,0L
51.868,0.776978L 51.8166,0.867676C 45.3563,10.7811 37.0999,19.4158 30.2689,29.0775C 22.294,40.4973
15.402,52.6647 7.14624,63.8831C 5.20599,66.5197 2.82214,68.8004 0.737793,71.3245L 0,70.861'/>

<Path Canvas.Left='338.332' Canvas.Top='265.814' Fill='#345C5C5C' Data='F1 M


0.443237,0C 16.0347,10.1857 38.1003,12.5537 55.8748,6.9939L 56.2712,8.08447C 38.2225,13.7471 15.839,11.0826
0,0.74115L 0.443237,0'/>

<Path Canvas.Left='337.888' Canvas.Top='266.555' Fill='#675C5C5C' Data='F1 M


0.443237,0C 16.2822,10.3415 38.6658,13.0059 56.7145,7.34332L 57.1123,8.43347C 38.7932,14.1966 16.2807,10.9586
0,0.74115L 0.443237,0'/>

<Path Canvas.Left='337.445' Canvas.Top='267.296' Fill='#B35C5C5C' Data='F1 M


0.442993,0C 16.712,10.2136 39.2313,13.457 57.5553,7.69232L 57.7548,8.23724L 57.9542,8.78174L 57.938,8.78711C
51.4122,10.8456 44.4888,11.9378 37.6461,11.894C 24.5585,11.8104 11.0474,7.75848 0,0.741028L 0.221375,0.370605L
0.442993,0'/>

<Path Canvas.Left='337.003' Canvas.Top='268.037' Fill='#675C5C5C' Data='F1 M


0.442322,0C 11.4897,7.01746 25.0009,11.0693 38.0884,11.153C 44.9311,11.1968 51.8545,10.1046 58.3804,8.04608L
58.3965,8.04071L 58.7957,9.12988L 58.7471,9.14606C 50.8863,11.6315 42.4316,12.7407 34.2045,12.2089C
22.2043,11.4332 10.116,7.24335 0,0.741577L 0.442322,0'/>

<Path Canvas.Left='336.561' Canvas.Top='268.779' Fill='#345C5C5C' Data='F1 M


<Path Canvas.Left='336.561' Canvas.Top='268.779' Fill='#345C5C5C' Data='F1 M
0.44165,0C 10.5576,6.50177 22.646,10.6916 34.6462,11.4673C 42.8733,11.9991 51.3279,10.8899 59.1887,8.40448L
59.2373,8.38831L 59.6364,9.47742L 59.5554,9.50439C 50.9401,12.235 41.6022,13.3678 32.6073,12.4894C
21.1091,11.3666 9.68585,7.03949 0,0.74231L 0.44165,0'/>

<Path Canvas.Left='369.276' Canvas.Top='190.839' Fill='#345C5C5C' Data='F1 M


21.3538,38.6989C 17.6099,37.45 13.7386,36.2714 10.4442,34.0981C 7.44897,32.1222 4.83929,29.3355
3.17932,26.1542C 0,20.0612 0.651489,10.7297 5.27295,5.64288C 8.47241,2.62823 13.0266,0.792786 17.412,0.488647C
24.4575,0 31.473,2.07623 38.3699,3.59546L 38.1913,4.67511C 31.3861,3.21973 24.4564,1.2652 17.5162,1.7771C
13.4261,2.07874 9.16492,3.73792 6.1734,6.54333C 1.87195,11.2582 1.32092,19.9318 4.26471,25.5946C
7.53064,31.8771 14.8646,35.6577 21.5819,37.8969L 21.3538,38.6989'/>

<Path Canvas.Left='370.597' Canvas.Top='192.104' Fill='#675C5C5C' Data='F1 M


20.261,36.6317C 13.5436,34.3925 6.20972,30.6119 2.94379,24.3294C 0,18.6666 0.551025,9.99304 4.85248,5.27814C
7.84399,2.47272 12.1052,0.813538 16.1953,0.511902C 23.1355,0 30.0652,1.95453 36.8704,3.40991L 36.6921,4.4892C
30.302,3.16321 23.8279,1.46814 17.3073,1.74048C 13.1851,1.91266 8.77039,3.36481 5.75293,6.17859C
1.77032,10.5205 1.32068,18.5374 4.02917,23.7697C 7.15326,29.8049 14.0312,33.6544 20.4891,35.8297L
20.261,36.6317'/>

<Path Canvas.Left='371.918' Canvas.Top='193.573' Fill='#B35C5C5C' Data='F1 M


19.1684,34.3616C 12.7224,32.1907 5.83527,28.342 2.7085,22.3016C 0,17.0692 0.449646,9.05237 4.43225,4.71045C
7.44971,1.89667 11.8644,0.444519 15.9866,0.272339C 22.5072,0 28.9813,1.69507 35.3715,3.02106L 35.2825,3.56055L
35.1935,4.10004L 35.1753,4.09637C 29.1835,2.8905 23.1317,1.4295 17.0206,1.52698C 12.8942,1.59277 8.3606,2.8067
5.33264,5.61084C 1.88574,9.34418 1.3009,16.0535 3.31165,20.7199C 6.02649,27.0203 12.9313,31.2655
19.3968,33.5594L 19.2825,33.9606L 19.1684,34.3616'/>

<Path Canvas.Left='373.218' Canvas.Top='195.002' Fill='#675C5C5C' Data='F1 M


18.0959,32.1299C 11.6304,29.836 4.72559,25.5908 2.01074,19.2904C 0,14.624 0.584839,7.91467 4.03174,4.18134C
7.05969,1.3772 11.5933,0.163269 15.7197,0.0974731C 21.8307,0 27.8826,1.461 33.8744,2.66687L 33.8926,2.67053L
33.7148,3.74939L 33.6601,3.73846C 28.0531,2.64453 22.3994,1.39081 16.6867,1.36774C 12.5776,1.35114
7.9588,2.30249 4.93219,5.08179C 1.78607,8.45679 1.31488,14.5661 3.13397,18.8063C 5.72119,24.8369
12.1791,29.029 18.3257,31.327L 18.0959,32.1299'/>

<Path Canvas.Left='374.533' Canvas.Top='196.353' Fill='#345C5C5C' Data='F1 M


17.0108,29.9759C 10.8642,27.6779 4.40631,23.4858 1.81909,17.4552C 0,13.215 0.471191,7.10565 3.61731,3.73065C
6.64392,0.951355 11.2628,0 15.3718,0.0166016C 21.0845,0.0396729 26.7382,1.2934 32.3452,2.38733L
32.3999,2.39825L 32.222,3.47717L 32.1309,3.45892C 26.5883,2.41119 20.9892,1.25305 15.3486,1.28754C
11.5703,1.31061 7.31427,2.09027 4.51776,4.6311C 1.66943,7.64484 1.31476,13.1572 2.94232,16.9711C
5.40173,22.7343 11.4125,26.8753 17.2422,29.1724L 17.0108,29.9759'/>

<Path Canvas.Left='389.74' Canvas.Top='198.522' Fill='#26FFFFFF' Data='F1 M


0.0935059,25.8618C 4.16687,27.4902 8.88464,26.9769 13.2405,26.4565C 17.7853,25.6243 23.2078,22.6108
24.3192,18.126C 24.905,15.0692 24.7365,11.4733 23.0153,8.88013C 20.3696,4.89423 15.535,2.64172
11.0694,0.925537L 11.3862,0C 16.0485,1.79224 21.0927,4.19476 23.8002,8.39203C 25.6094,11.1965 25.7624,15.05
25.0955,18.3201C 23.8452,23.0637 18.1619,26.3218 13.3282,27.1584C 8.89954,27.6432 4.13654,27.8161 0,26.1615L
0.0935059,25.8618'/>

<Path Canvas.Left='389.647' Canvas.Top='197.596' Fill='#4CFFFFFF' Data='F1 M


0.0935059,27.0873C 4.23004,28.7419 8.99304,28.569 13.4218,28.0842C 18.2554,27.2476 23.9387,23.9895
25.189,19.2459C 25.8559,15.9758 25.7029,12.1223 23.8937,9.31781C 21.1862,5.12054 16.142,2.71802
11.4797,0.925781L 11.7957,0C 16.655,1.86841 21.9056,4.42358 24.6787,8.82971C 26.5764,11.8449 26.7154,15.9572
25.9652,19.4399C 24.5829,24.4433 18.6318,27.9459 13.5095,28.7861C 9.00861,29.2362 4.26068,28.9421 0,27.3871L
0.0935059,27.0873'/>

<Path Canvas.Left='389.553' Canvas.Top='196.67' Fill='#85FFFFFF' Data='F1 M


0.0933228,28.313C 4.34558,29.8668 9.09802,30.1625 13.6028,29.712C 18.7251,28.8718 24.6763,25.3692
26.0585,20.3658C 26.8087,16.8831 26.6697,12.7708 24.772,9.75562C 21.999,5.34949 16.7484,2.79431
11.889,0.925903L 12.0466,0.462891L 12.2041,0L 12.2156,0.00421143C 17.2689,1.94757 22.7175,4.65802
25.5571,9.26758C 27.5439,12.4929 27.6699,16.865 26.8348,20.5599C 25.3253,25.8237 19.1013,29.5712
13.6906,30.4138C 9.10669,30.831 4.28436,30.2952 0,28.6127L 0.0466309,28.4629L 0.0933228,28.313'/>

<Path Canvas.Left='389.46' Canvas.Top='195.745' Fill='#4CFFFFFF' Data='F1 M


0.0930786,29.5386C 4.37744,31.221 9.19977,31.7568 13.7836,31.3396C 19.1943,30.4971 25.4184,26.7495
26.9279,21.4858C 27.7629,17.7908 27.637,13.4187 25.6501,10.1934C 22.8105,5.58386 17.3619,2.87341
12.3087,0.930054L 12.2972,0.925842L 12.6121,0L 12.6467,0.0126953C 17.8902,2.02972 23.5289,4.89734
26.4351,9.70532C 28.5115,13.1404 28.6259,17.7733 27.7041,21.6798C 26.0712,27.2047 19.5701,31.1967
13.8713,32.0415C 9.20544,32.4261 4.31586,31.6534 0,29.8391L 0.0930786,29.5386'/>

<Path Canvas.Left='389.367' Canvas.Top='194.819' Fill='#26FFFFFF' Data='F1 M


0.0928955,30.765C 4.40875,32.5792 9.29834,33.352 13.9642,32.9673C 19.663,32.1225 26.1641,28.1305
27.797,22.6057C 28.7188,18.6991 28.6044,14.0662 26.528,10.6312C 23.6218,5.82318 17.9831,2.95557
12.7396,0.938538L 12.705,0.925842L 13.02,0L 13.0776,0.0211792C 18.5117,2.11182 24.3381,5.13812 27.313,10.1431C
29.4793,13.7876 29.5833,18.6821 28.5732,22.7997C 26.8197,28.5861 20.0386,32.8224 14.052,33.6692C
9.30139,34.0219 4.34711,33.0148 0,31.0667L 0.0928955,30.765'/>

<Path Canvas.Left='550.292' Canvas.Top='228.128' Fill='#34FFFFFF' Data='F1 M


7.68632,3.71375C 8.63746,7.19464 8.30715,11.0056 7.57337,14.5388L 4.88624,21.7733L -1.95956e-005,16.6653L
1.61224,12.3246C 2.6293,8.32977 2.36064,4.11371 2.80589,0C 4.25242,1.44446 5.98903,2.5744 7.68632,3.71375'/>

<Path Canvas.Left='545.405' Canvas.Top='223.663' Fill='#67FFFFFF' Data='F1 M


7.69218,4.46509C 7.24353,8.56805 7.51688,12.7899 6.49854,16.7897L 4.88627,21.1304L -2.08559e-005,16.0225L
0.537411,14.5756C 2.0552,9.7749 2.10747,4.43005 4.50019,0C 5.34092,1.62494 6.43269,3.13806 7.69218,4.46509'/>

<Path Canvas.Left='540.511' Canvas.Top='218.742' Fill='#B3FFFFFF' Data='F1 M


9.39484,4.92053C 7.00213,9.35059 6.94986,14.6954 5.43206,19.4961L 4.89463,20.9431L 2.45154,18.389L
0.386079,16.3171L -2.23393e-005,15.9489C 1.19072,12.8391 2.01289,9.58124 3.41409,6.56042C 4.49598,4.22803
6.01769,2.12115 7.47067,0C 8.06534,1.65765 8.62123,3.33838 9.39484,4.92053'/>

<Path Canvas.Left='535.812' Canvas.Top='213.781' Fill='#67FFFFFF' Data='F1 M


12.1697,4.96094C 10.7167,7.08209 9.19501,9.18896 8.11312,11.5214C 6.71193,14.5422 5.88976,17.8
4.69901,20.9098C 3.15332,19.4757 1.57863,18.073 2.37327e-005,16.6752C 1.34374,14.2011 2.43529,11.5875
3.90042,9.18335C 5.85097,5.98254 8.2718,3.09235 10.3902,0L 12.1697,4.96094'/>

<Path Canvas.Left='531.956' Canvas.Top='208.82' Fill='#34FFFFFF' Data='F1 M


14.2458,4.961C 12.1274,8.05334 9.70656,10.9435 7.75601,14.1443C 6.29088,16.5485 5.19933,19.1621
3.85561,21.6362C 2.4337,20.3827 1.13039,18.9778 -1.58906e-005,17.4561C 3.85171,11.4321 8.42536,5.89886
12.4662,0L 14.2458,4.961'/>

<Path Canvas.Left='289.416' Canvas.Top='188.274' Fill='#20FFFFFF' Data='F1 M


6.18872,0C 7.52512,2.03308 8.53534,4.31836 10.1808,6.11047C 11.1353,7.14996 12.9086,7.05029 13.9913,7.95551L
15.1559,10.2848L 7.56702,12.9147L 6.86823,11.5171C 5.82962,10.1469 4.43616,9.03851 3.56259,7.55762C
2.27042,5.36707 1.25912,3.02032 0,0.810608L 5.4299,0.0772095L 6.18872,0'/>

<Path Canvas.Left='283.596' Canvas.Top='189.084' Fill='#3FFFFFFF' Data='F1 M 5.8204,0C


7.07953,2.20972 8.09082,4.55646 9.383,6.74701C 10.2566,8.22791 11.65,9.3363 12.6886,10.7065L 13.3874,12.1041L
5.79855,14.7339L 5.56561,14.2681C 3.26312,10.0796 2.03406,5.37866 0,1.05347L 4.39648,0.228394L 5.8204,0'/>

<Path Canvas.Left='278.031' Canvas.Top='190.138' Fill='#6DFFFFFF' Data='F1 M


5.56537,0C 7.59943,4.3252 8.82849,9.02612 11.131,13.2146L 11.3639,13.6805L 7.56952,14.9954L 3.78119,16.2534C
1.76376,11.4948 2.03613,5.96631 0,1.21564L 2.7695,0.595337L 5.56537,0'/>

<Path Canvas.Left='272.491' Canvas.Top='191.354' Fill='#3FFFFFFF' Data='F1 M


5.53906,0C 7.5752,4.75067 7.30283,10.2791 9.32025,15.0377C 7.40805,15.6043 5.50073,16.1877 3.58362,16.7375C
2.98492,16.9092 2.37704,17.0471 1.77374,17.2019C 1.02271,14.4838 0.532135,11.6374 0.632751,8.81921C
0.723206,6.28577 0.998596,3.57056 0,1.24048L 5.53906,0'/>

<Path Canvas.Left='266.018' Canvas.Top='192.594' Fill='#20FFFFFF' Data='F1 M


6.47314,0C 7.47174,2.33008 7.19635,5.04529 7.1059,7.57874C 7.00528,10.3969 7.49585,13.2433 8.24689,15.9614C
6.06711,16.4348 3.89029,16.922 1.70755,17.3815C 1.40616,17.4449 1.09955,17.4805 0.795563,17.53C
0.355621,14.7278 0,11.8203 0.48764,9.02588C 0.756836,7.48322 1.94727,6.14423 2.00351,4.57928C 2.01483,4.26416
2.05612,3.93457 1.95993,3.63422C 1.69513,2.8075 1.27603,2.03845 0.934082,1.24054L 6.47314,0'/>

<Path Canvas.Left='234.106' Canvas.Top='338.189' Fill='#0AFFFFFF' Data='F1 M


27.5909,12.0546C 24.6353,20.0626 21.1081,27.8498 18.0741,35.8283C 17.1804,38.1786 16.5845,40.6334
15.7293,42.998C 15.4324,43.819 14.9161,44.5594 14.6935,45.4036C 14.8451,44.9415 14.6703,46.3774
14.7071,46.8623C 14.8021,48.113 15.0276,49.353 15.2879,50.58C 15.9435,53.6697 16.8542,56.7016 17.7637,59.7263C
21.2133,71.1992 24.7242,82.8665 25.5197,94.8204C 25.9702,107.281 24.5691,119.803 22.5647,132.11C
20.6823,143.667 18.2534,155.313 18.6216,167.017C 18.825,170.6 18.9395,174.197 19.3894,177.758C 20.0438,182.939
21.4561,187.996 22.4836,193.116C 24.184,201.589 25.8134,210.107 26.5833,218.714C 27.6976,235.229
26.3329,251.91 24.0795,268.308C 21.6726,285.823 18.2595,303.278 17.5499,320.944C 16.8673,352.688 17.1,384.53
19.7087,416.174C 22.0885,450.024 17.057,484.027 13.7573,517.799C 11.6779,539.903 12.4432,562.236
13.65,584.405C 14.2527,595.475 15.3395,606.526 15.5303,617.611L 15.5303,632.351L 7.24915,626.455L
7.24915,617.611C 6.82248,584.086 1.98068,550.461 4.85199,517.057C 7.95694,483.701 13.2959,450.177
11.0895,416.749C 8.63193,384.881 6.78552,352.904 7.12753,320.944C 7.67255,300.623 11.8397,280.56
14.3325,260.385C 16.0005,246.885 16.8115,233.177 15.881,219.606C 14.3214,202.237 9.02933,185.315
7.77057,167.921C 7.06381,153.974 9.84991,140.055 11.6716,126.21C 12.9899,116.192 13.7496,106.028
13.2428,95.9364C 12.4066,85.0143 8.93707,74.4086 5.59979,63.9752C 3.30157,56.7902 0,48.8708 2.08035,41.6197C
3.53629,36.9082 6.1489,32.6268 8.48535,28.2841C 13.4586,19.0405 18.9734,9.94629 22.3271,0C 24.2582,3.9364
25.95,7.98865 27.5909,12.0546'/>

<Path Canvas.Left='221.263' Canvas.Top='328.177' Fill='#13FFFFFF' Data='F1 M


35.17,10.0123C 31.8162,19.9586 26.3015,29.0528 21.3282,38.2963C 18.9918,42.639 16.3792,46.9205 14.9232,51.632C
12.8429,58.8831 16.1444,66.8025 18.4427,73.9875C 21.7799,84.4208 25.2495,95.0266 26.0856,105.949C
26.5925,116.041 25.8327,126.204 24.5145,136.222C 22.6928,150.067 19.9067,163.987 20.6134,177.933C
21.8722,195.327 27.1642,212.249 28.7238,229.618C 29.6543,243.189 28.8434,256.897 27.1754,270.397C
24.6826,290.573 20.5154,310.635 19.9704,330.956C 19.6284,362.917 21.4748,394.893 23.9324,426.761C
26.1388,460.189 20.7998,493.713 17.6949,527.069C 14.8235,560.473 19.6653,594.098 20.092,627.623L
20.092,636.467L 11.8109,630.571L 11.8109,627.623C 11.541,593.844 6.14261,560.004 8.78958,526.327C
11.7086,493.387 17.3381,460.342 15.3132,427.336C 13.0125,395.234 9.5303,363.14 9.5481,330.956C 10.0624,297.359
20.3629,264.029 18.0214,230.51C 16.4545,213.138 11.2397,196.218 9.76242,178.837C 8.20422,154.926
15.4315,130.972 13.8087,107.065C 12.7283,95.202 7.96161,83.9578 4.42102,72.5844C 1.9613,64.6829 0,55.7944
2.31012,47.848C 4.61981,40.4728 9.38358,34.0428 13.8711,27.7508C 20.0167,19.134 26.5721,10.2263 29.2999,0C
31.5305,3.16095 33.4369,6.55347 35.17,10.0123'/>

<Path Canvas.Left='208.499' Canvas.Top='320.441' Fill='#21FFFFFF' Data='F1 M


42.0644,7.73639C 39.3365,17.9626 32.7811,26.8704 26.6356,35.4872C 22.148,41.7792 17.3843,48.2092
15.0746,55.5844C 12.7645,63.5308 14.7258,72.4193 17.1855,80.3207C 20.7261,91.6942 25.4927,102.938
26.5732,114.801C 28.196,138.708 20.9687,162.662 22.5269,186.574C 24.0042,203.954 29.219,220.874
30.7859,238.247C 33.1273,271.766 22.8268,305.096 22.3126,338.693C 22.2948,370.876 25.7769,402.97
28.0777,435.072C 30.1026,468.079 24.4731,501.124 21.554,534.064C 18.9071,567.74 24.3055,601.58
24.5753,635.359L 24.5753,638.307L 20.4348,635.359L 16.2854,632.453C 16.2234,599.387 10.2773,566.302
12.649,533.322C 15.391,500.8 21.2924,468.232 19.4586,435.646C 17.3206,403.301 12.1828,371.108 11.8904,338.693C
12.0667,305.396 22.4532,272.351 20.0837,239.138C 18.5081,221.763 13.3327,204.846 11.6761,187.478C
9.85547,163.678 16.4519,139.689 14.2965,115.917C 12.8057,102.864 6.35785,90.8572 3.00317,78.1541C
0.759735,69.659 0,60.235 2.46173,51.8006C 4.31165,45.922 7.3862,40.3592 11.1566,35.4843C 17.1533,27.7308
24.7854,21.2451 30.1821,13.0624C 32.7593,9.15479 34.4197,4.59015 35.3377,0C 37.6636,2.5036 40.0584,4.96985
42.0644,7.73639'/>

<Path Canvas.Left='195.221' Canvas.Top='313.056' Fill='#13FFFFFF' Data='F1 M


48.6155,7.38507C 47.6974,11.9752 46.037,16.5399 43.4598,20.4475C 38.0631,28.6301 30.4311,35.1158
24.4343,42.8694C 20.6639,47.7443 17.5894,53.3071 15.7395,59.1857C 13.2777,67.6201 14.0375,77.0441
16.2809,85.5392C 19.6356,98.2422 26.0835,110.249 27.5742,123.302C 29.7296,147.074 23.1332,171.063
24.9539,194.863C 26.6104,212.231 31.7859,229.148 33.3615,246.523C 35.7309,279.736 25.3445,312.781
25.1682,346.078C 25.4606,378.493 30.5983,410.686 32.7364,443.032C 34.5701,475.617 28.6687,508.185
25.9267,540.707C 23.555,573.687 29.5011,606.772 29.5631,639.838C 26.8193,637.941 24.0407,636.094
21.2626,634.247C 20.972,602.789 14.9564,571.356 17.0214,539.964C 19.5948,507.861 25.7493,475.771
24.1172,443.606C 22.1487,411.006 15.3352,378.732 14.7459,346.078C 14.7143,337.08 15.0918,328.058
16.1385,319.121C 18.9305,295.284 24.4102,271.352 22.6591,247.415C 21.073,230.037 15.9099,213.124
14.1028,195.767C 13.2518,185.824 13.534,175.782 14.2464,165.828C 15.232,152.055 16.9593,138.126
15.2973,124.418C 13.3665,112.082 6.93631,100.861 3.65018,88.8143C 0.718781,78.0681 0,66.0929 3.12637,55.4017C
5.62567,47.4803 9.87854,39.8605 15.574,33.8142C 22.5793,26.3774 32.1041,21.2254 37.8922,12.8064C
40.4182,9.1322 40.8801,4.37213 41.7545,0L 48.6155,7.38507'/>

<Path Canvas.Left='182.198' Canvas.Top='305.671' Fill='#0AFFFFFF' Data='F1 M


54.7772,7.38513C 53.9028,11.7573 53.4409,16.5173 50.9149,20.1915C 45.1268,28.6105 35.602,33.7625
28.5967,41.1993C 22.9013,47.2457 18.6484,54.8654 16.1491,62.7869C 13.0227,73.478 13.7415,85.4532
16.6729,96.1995C 19.959,108.246 26.3892,119.467 28.32,131.804C 29.982,145.511 28.2547,159.44 27.2691,173.213C
26.5567,183.167 26.2746,193.209 27.1256,203.152C 28.9327,220.509 34.0958,237.422 35.6818,254.8C 37.433,278.737
31.9532,302.669 29.1612,326.507C 28.1146,335.443 27.737,344.465 27.7686,353.463C 28.3579,386.117
35.1714,418.391 37.1399,450.991C 38.7721,483.156 32.6175,515.246 30.0442,547.35C 27.9792,578.741
33.9947,610.174 34.2853,641.632C 31.5466,639.827 28.7923,638.046 26.0346,636.271C 25.8068,620.013
23.5452,603.846 22.0997,587.65C 20.8831,574.02 20.3171,560.267 21.1389,546.607C 23.5519,514.923 29.9387,483.31
28.5208,451.566C 26.7289,418.702 18.2211,386.364 17.3463,353.463C 17.2399,344.046 17.4568,334.59
18.5389,325.235C 21.2138,302.109 26.7289,278.907 24.9794,255.692C 23.3809,238.311 18.2092,221.404
16.2746,204.057C 15.1398,191.861 15.5704,179.54 16.2865,167.313C 16.9567,155.868 17.9027,144.232
16.0431,132.92C 12.8346,120.551 6.51221,109.131 3.32013,96.7585C 0.176178,84.5721 0,71.0814 3.53601,59.003C
5.4577,52.9216 7.93173,46.885 11.5317,41.6204C 15.1967,36.2607 20.2024,31.8085 25.473,28.0165C 29.5947,25.0511
34.0565,22.589 38.3824,19.9302C 39.9511,18.9659 41.5132,17.9665 42.9153,16.7728C 43.711,16.0953 44.811,15.4769
45.0255,14.4541C 46.0336,9.6452 46.9526,4.81805 47.9162,0L 54.7772,7.38513'/>

<Path Canvas.Left='513.741' Canvas.Top='311.611' Fill='#0AFFFFFF' Data='F1 M


5.42715,0C 7.77554,3.69031 10.0325,7.44049 12.4724,11.071C 13.9953,13.3369 16.123,15.1382 18.0924,17.029C
21.591,20.3879 25.2619,23.5629 28.8092,26.8704C 32.9838,31.2312 37.2027,35.688 40.2959,40.8723C
45.5836,49.5515 52.0998,57.5822 56.2198,66.8727C 60.3911,76.2794 62.3145,87.2267 60.7883,97.403C
59.9024,103.122 57.8417,108.821 54.633,113.637C 51.8015,117.887 48.1749,121.664 44.1574,124.817C
42.6232,126.021 41.0275,127.149 39.394,128.214C 38.9862,128.48 38.572,128.736 38.1566,128.99C 38.0058,129.082
37.8518,129.169 37.6959,129.252C 37.4735,129.37 37.1319,129.65 36.9686,129.458C 36.5523,128.969
37.8518,129.169 37.6959,129.252C 37.4735,129.37 37.1319,129.65 36.9686,129.458C 36.5523,128.969
37.3015,128.217 37.5022,127.606C 37.8722,126.481 38.1357,125.314 38.2641,124.136C 34.4757,131.829
36.638,141.481 38.4588,149.861C 40.8167,160.712 43.8694,171.488 44.9118,182.544C 46.5804,202.607
45.4733,222.907 43.2741,242.919C 41.0929,262.767 37.6662,282.558 37.2992,302.522C 37.3384,319.827
38.2722,337.118 38.9135,354.411C 39.6041,373.028 40.1324,391.652 40.7488,410.272C 41.9358,446.13
43.9765,481.96 46.3463,517.759C 47.4458,534.367 48.0078,551.026 49.835,567.57C 51.4013,580.341 50.5407,593.385
49.0273,606.163C 47.7607,616.857 46.1447,627.524 43.9649,638.07C 40.3237,639.227 36.6602,640.314
32.9924,641.384C 35.8654,630.37 37.5072,619.049 38.9216,607.754C 40.5321,594.893 41.5671,581.748
39.978,568.884C 38.3843,555.104 37.9978,541.21 37.1662,527.363C 35.8705,505.787 34.6104,484.209
33.5208,462.621C 31.914,430.785 30.9577,398.919 29.8446,367.062C 29.0931,345.551 27.9134,324.046
27.7898,302.522C 28.1103,280.845 31.9794,259.364 34.4966,237.832C 36.6123,219.734 37.7839,201.366
36.3574,183.202C 35.2773,171.338 31.6491,159.844 29.1104,148.205C 27.2594,139.718 25.8563,130.472
28.3687,122.157C 28.3727,122.458 28.1325,123.025 28.4317,123.058C 28.8129,123.099 29.0606,122.618
29.3605,122.379C 29.8566,121.984 30.3553,121.591 30.8604,121.207C 33.1513,119.466 35.4839,117.771
37.656,115.883C 43.4176,110.877 48.0855,103.666 49.2166,96.1172C 50.3264,88.1945 48.6606,79.7019
45.3107,72.4369C 41.2782,63.6915 34.8741,56.2487 29.5879,48.1989C 26.2597,42.9709 22.6302,37.9194
18.6958,33.131C 13.8141,27.5779 8.33633,22.4648 4.22708,16.3181C 2.76846,14.1362 1.40903,11.8896 -3.05176e-
005,9.67548L 5.42715,0'/>

<Path Canvas.Left='508.314' Canvas.Top='321.287' Fill='#13FFFFFF' Data='F1 M


5.42731,0C 6.83636,2.21417 8.1958,4.46075 9.65442,6.64258C 13.7637,12.7894 19.2414,17.9025 24.1232,23.4556C
28.0576,28.244 31.687,33.2954 35.0152,38.5234C 40.3015,46.5732 46.7055,54.016 50.738,62.7614C 54.0879,70.0264
55.7537,78.519 54.6439,86.4418C 53.5129,93.9904 48.845,101.202 43.0833,106.208C 41.3396,107.723
39.4891,109.112 37.646,110.505C 37.1931,110.847 36.7397,111.188 36.2878,111.532C 36.0953,111.678
35.9039,111.826 35.7129,111.974C 35.5452,112.104 35.3782,112.235 35.2117,112.366C 35.0699,112.478
34.929,112.591 34.7878,112.703C 34.48,112.949 34.1261,113.627 33.8195,113.38C 33.5862,113.192 33.8,112.781
33.7961,112.482C 31.2836,120.797 32.6867,130.043 34.5377,138.529C 37.0764,150.169 40.7046,161.662
41.7847,173.526C 43.2112,191.691 42.0396,210.059 39.924,228.156C 37.4067,249.689 33.5377,271.17
33.2172,292.846C 33.3408,314.37 34.5204,335.875 35.272,357.386C 36.385,389.243 37.3413,421.109
38.9482,452.946C 40.0378,474.533 41.2979,496.112 42.5936,517.688C 43.4251,531.535 43.8116,545.428
45.4053,559.208C 46.9944,572.072 45.9595,585.217 44.3489,598.078C 42.9346,609.373 41.2928,620.694
38.4197,631.709L 30.5485,633.953L 27.6094,634.76C 30.752,622.313 33.0142,609.625 34.5857,596.884C
36.0699,584.85 37.0491,572.554 35.5483,560.523C 33.8896,546.478 33.5692,532.306 32.8094,518.184C
31.5958,495.625 30.483,473.061 29.4592,450.493C 28.0187,418.742 26.8487,386.979 25.6879,355.217C
24.9283,334.43 23.8896,313.646 23.7078,292.846C 24.1653,253.168 36.1369,213.759 33.2303,174.184C
32.1237,161.468 27.8981,149.219 25.0453,136.778C 23.086,128.233 22.0533,119.073 23.9008,110.503C
25.1037,105.802 30.0197,102.902 33.6995,99.7398C 38.0822,95.9736 42.2833,90.8806 43.0723,85.1561C
43.7864,79.2531 42.2417,72.9573 39.5057,67.6782C 35.4262,59.8064 29.3246,53.1597 24.3071,45.85C
20.7829,40.5317 17.5952,34.9934 14.0098,29.7162C 9.31641,23.0524 4.37598,16.5519 0,9.67554L 5.42731,0'/>

<Path Canvas.Left='502.833' Canvas.Top='330.962' Fill='#21FFFFFF' Data='F1 M


5.48071,0C 9.85669,6.87634 14.7971,13.3769 19.4905,20.0407C 23.0759,25.3179 26.2636,30.8562 29.7878,36.1744C
34.8053,43.4842 40.9069,50.1309 44.9865,58.0026C 47.7224,63.2818 49.2672,69.5776 48.553,75.4805C
47.764,81.2051 43.5629,86.2981 39.1802,90.0643C 35.5004,93.2264 30.5844,96.1269 29.3815,100.827C
27.534,109.397 28.5667,118.557 30.5261,127.102C 33.3788,139.543 37.6044,151.793 38.711,164.509C
41.6176,204.083 29.646,243.492 29.1885,283.171C 29.3703,303.971 30.409,324.755 31.1686,345.541C
32.3294,377.304 33.4994,409.066 34.9399,440.817C 35.9637,463.385 37.0765,485.95 38.2902,508.508C
39.0499,522.63 39.3703,536.802 41.029,550.847C 42.5298,562.879 41.5506,575.175 40.0664,587.208C
38.4949,599.949 36.2327,612.637 33.0901,625.085L 27.7672,626.504L 22.4532,627.881L 23.0898,625.335C
26.3188,611.542 29.0282,597.584 30.5953,583.505C 31.7514,573.12 32.4815,562.529 31.1722,552.161C
29.4606,537.85 29.1914,523.401 28.5062,509.004C 27.3856,485.458 26.4435,461.903 25.4761,438.35C
23.3521,386.631 20.272,334.93 19.6793,283.171C 20.0207,243.683 32.8226,204.566 30.1568,165.167C
28.9752,150.754 23.2546,137.072 20.3687,122.902C 18.7675,115.04 18.1724,106.763 19.4863,98.8481C
20.6867,92.648 25.7191,87.627 30.332,83.3138C 33.0799,80.7444 36.712,77.9471 36.9814,74.1948C 37.3285,69.1515
34.634,64.1123 31.7513,59.9596C 27.8031,54.2719 23.0756,49.1555 19.08,43.5009C 15.375,38.06 12.4598,32.1174
9.37732,26.3012C 6.33655,20.7281 3.22052,15.1949 0,9.72375L 2.76721,4.83765L 5.48071,0'/>

<Path Canvas.Left='496.778' Canvas.Top='340.686' Fill='#13FFFFFF' Data='F1 M


6.05493,0C 9.27545,5.47113 12.3915,11.0044 15.4323,16.5775C 18.5147,22.3937 21.4299,28.3362 25.1349,33.7771C
29.1305,39.4317 33.858,44.5481 37.8063,50.2358C 40.689,54.3885 43.3834,59.4277 43.0364,64.471C 42.7669,68.2233
39.1348,71.0207 36.387,73.59C 31.774,77.9033 26.7416,82.9243 25.5413,89.1244C 24.2273,97.0395 24.8224,105.316
26.4236,113.178C 29.3096,127.349 35.0302,141.03 36.2117,155.443C 38.8775,194.842 26.0756,233.959
25.7342,273.447C 26.3269,325.206 29.407,376.907 31.5311,428.626C 32.4984,452.179 33.4406,475.734
34.5612,499.28C 35.2463,513.677 35.5156,528.126 37.2271,542.438C 38.5364,552.805 37.8063,563.396
36.6503,573.782C 35.0831,587.86 32.3738,601.818 29.1447,615.611L 28.5082,618.157L 17.8801,620.911L
19.7896,613.273C 22.6995,599.849 25.3878,586.334 26.8702,572.679C 27.9111,563.092 28.5996,553.317
27.3701,543.752C 25.6128,529.173 25.3844,514.448 24.777,499.776C 23.8009,476.198 23.074,452.61
22.1968,429.027C 20.2675,377.165 16.9409,325.341 16.2249,273.447C 16.333,255.395 18.6348,237.371
21.5135,219.55C 24.902,198.573 28.9565,177.31 27.6573,156.101C 26.6521,142.752 21.2617,130.102
17.9812,117.123C 15.5251,107.406 14.3154,97.0794 15.6459,87.1453C 16.8803,80.2391 21.0917,73.8602
17.9812,117.123C 15.5251,107.406 14.3154,97.0794 15.6459,87.1453C 16.8803,80.2391 21.0917,73.8602
25.9352,68.7849C 27.6279,67.0111 29.4062,65.316 31.022,63.472C 31.1804,63.2911 31.3367,63.1083
31.4894,62.9226C 31.6216,62.762 31.7493,62.5977 31.8765,62.433C 32.0253,62.2404 32.1638,62.0394
32.2908,61.8318C 32.3237,61.778 32.3559,61.7237 32.3862,61.6685C 32.4114,61.6226 32.4352,61.5759
32.4575,61.5285C 32.6783,61.0579 32.5764,61.1917 32.4965,61.1921C 31.7484,61.196 31.6421,62.4585
31.4647,63.1853C 26.5259,55.3088 19.8659,48.6435 14.4268,41.1037C 10.5457,35.5158 7.69604,29.2128
5.31885,22.8381C 3.61084,18.5771 1.88367,14.3213 0,10.135C 2.0528,6.77753 4.09497,3.41254 6.05493,0'/>

<Path Canvas.Left='489.698' Canvas.Top='350.821' Fill='#0AFFFFFF' Data='F1 M


7.08014,0C 8.96381,4.18628 10.691,8.44214 12.399,12.7031C 14.7762,19.0778 17.6259,25.3808 21.507,30.9687C
26.9394,38.4993 33.7736,45.0446 38.5449,53.0503C 38.6314,52.6955 38.7386,52.3432 38.8873,52.0096C
38.9493,51.8703 39.0167,51.7329 39.0939,51.6013C 39.1414,51.5204 39.1909,51.4404 39.2455,51.3641C
39.6271,50.8312 39.6008,51.0583 39.6099,51.0692C 39.8506,51.3569 39.3333,51.7747 39.1158,52.0804C
38.647,52.7395 38.1105,53.3501 37.5586,53.9414C 36.0704,55.5357 34.5211,57.072 33.0154,58.6498C
28.1719,63.7252 23.9604,70.1041 22.7261,77.0103C 21.3955,86.9444 22.6052,97.2707 25.0613,106.988C
28.3419,119.967 33.7322,132.617 34.7374,145.966C 36.0366,167.175 31.9822,188.438 28.5937,209.415C
25.7149,227.236 23.4131,245.26 23.305,263.312C 24.021,315.206 27.3477,367.03 29.2769,418.892C 30.1542,442.475
30.881,466.063 31.8572,489.641C 32.4645,504.313 32.6929,519.038 34.4502,533.617C 35.6797,543.182
34.9912,552.957 33.9504,562.544C 32.468,576.199 29.7796,589.714 26.8698,603.138L 24.9602,610.776L
14.332,613.53L 17.5146,600.799C 20.103,587.748 22.7733,574.674 24.1703,561.442C 25.0984,552.653
25.7483,543.694 24.5932,534.931C 22.7932,520.085 22.5998,505.083 22.0731,490.137C 21.241,466.527
20.7295,442.906 19.9426,419.294C 18.2096,367.289 14.6249,315.34 13.7956,263.312C 13.8668,243.555
16.4769,223.816 19.882,204.354C 23.2183,185.286 27.2252,165.954 26.183,146.624C 25.3768,134.435 20.3,122.903
16.847,111.186C 13.4195,99.5544 11.4881,87.0822 12.8307,75.0312C 14.2023,67.0663 18.3887,59.4881
23.5923,53.304C 25.3592,51.2042 27.2682,49.2278 29.0646,47.1532C 29.4457,46.7131 29.8156,46.2632
30.1802,45.8093C 30.3201,45.6351 30.4504,45.4532 30.5775,45.2693C 30.7945,44.9551 31.3085,44.4719
31.0259,44.2151C 30.7938,44.0043 30.4387,44.4736 30.2175,44.6957C 29.7043,45.211 29.2807,45.8163
28.9091,46.4413C 27.9441,48.0642 27.3339,49.9112 26.9731,51.7645C 26.7163,52.5325 26.5488,53.3328
26.446,54.1361C 26.3815,54.6401 26.5864,55.4043 26.1298,55.6272C 25.3471,56.0093 24.7463,54.5562
24.152,53.9194C 22.8713,52.5473 21.5995,51.1671 20.335,49.7802C 16.9823,46.1033 13.7394,42.3094
10.7989,38.2952C 8.97083,35.7023 7.11359,33.0917 5.75024,30.2271C 4.06226,26.6802 3.08368,22.8099
2.28564,18.9638C 1.54462,16.2018 0.807251,13.4382 0,10.6948C 2.41254,7.16516 4.80859,3.62195 7.08014,0'/>

<Path Canvas.Left='511.156' Canvas.Top='581.869' Fill='#0AFFFFFF' Data='F1 M 0,29.433C


1.53992,25.8398 3.0827,22.2478 4.61981,18.6534C 5.93616,15.5753 6.05042,12.0497 7.49896,9.03162C
8.83948,6.23859 11.092,3.70795 13.7958,2.1955C 16.6221,0.614502 20.1618,0 23.3617,0.49823C 28.9948,1.37537
34.299,6.91156 35.579,12.467C 38.3469,24.0312 38.3182,36.0997 39.1123,47.9639C 40.4646,67.3232 41.4939,86.7045
42.4843,106.086C 43.8276,134.42 43.6091,162.81 43.6004,191.176C 43.5928,215.97 43.6436,240.898 46.8074,265.49C
43.5341,267.382 40.2826,269.312 37.048,271.27C 33.2973,245.624 33.0103,219.525 33.2519,193.608C
33.5246,164.351 34.5131,135.091 34.0283,105.837C 33.6672,86.5427 33.3028,67.2451 32.5051,47.9639C
32.1021,36.505 32.4127,24.8498 29.8851,13.6658C 29.2684,10.9744 27.405,8.24609 24.9255,7.03101C
22.3309,5.75952 18.7189,5.94275 16.2687,7.47412C 12.685,9.71393 11.5593,14.6572 10.437,18.7316C
9.61719,21.7075 8.25372,24.5082 7.03778,27.3454L 0,29.433'/>

<Path Canvas.Left='518.193' Canvas.Top='587.702' Fill='#13FFFFFF' Data='F1 M 3.05176e-


005,21.5125C 0.923981,19.3566 1.85025,17.2017 2.77194,15.0447C 3.9205,12.3569 4.20663,9.36176 5.27072,6.63928C
6.6431,3.12805 10.882,0 14.6396,0.304321C 18.3401,0.604065 22.0182,4.21417 22.8474,7.83295C 25.3749,19.0169
25.0643,30.6721 25.4674,42.131C 26.265,61.4122 26.6294,80.7098 26.9906,100.004C 27.4754,129.258
26.4868,158.519 26.2141,187.776C 25.9726,213.692 26.2596,239.792 30.0103,265.437C 26.7724,267.427
23.5445,269.435 20.3498,271.494C 16.2752,246.518 15.4957,221.021 15.7483,195.717C 16.0678,163.718
18.0616,131.752 18.5346,99.7554C 18.796,80.5488 19.0993,61.338 18.8602,42.131C 18.8035,31.0834 19.425,19.8434
17.1535,9.03168C 16.9034,7.92334 16.1582,6.73273 15.1045,6.30774C 14.0446,5.88031 12.5663,6.20715
11.7477,7.00458C 10.7239,8.00195 10.3198,9.51013 9.91385,10.8806C 9.06033,13.7619 8.22159,16.6627
7.03781,19.4249L 3.05176e-005,21.5125'/>

<Path Canvas.Left='519.248' Canvas.Top='593.565' Fill='#21FFFFFF' Data='F1 M


5.98325,13.5626C 7.16702,10.8005 8.00577,7.89966 8.85928,5.01831C 9.17056,3.96747 9.49728,2.89777
10.0609,1.95782C 10.7307,0.840576 12.3335,0 13.6007,0.301941C 14.8339,0.595825 15.8199,1.93286 16.099,3.16943C
18.3704,13.9812 17.7489,25.2212 17.8056,36.2688C 18.0447,55.4757 17.7414,74.6865 17.48,93.8932C 17.007,125.89
15.0132,157.855 14.6938,189.854C 14.4411,215.159 15.2207,240.656 19.2953,265.631L 14.5021,268.769L
9.72287,271.943L 9.33725,269.63C 3.05176e-005,211.716 6.2872,152.242 9.0242,93.6444C 9.90182,74.5256
10.8743,55.405 11.1986,36.2688C 11.447,25.6349 12.3982,14.8167 10.4052,4.36816C 10.8716,5.47693
12.5099,6.25031 13.6652,5.91541C 13.9947,5.81989 14.3119,5.65717 14.5785,5.44135C 14.7023,5.34113
14.8178,5.22876 14.9168,5.10406C 14.9532,5.05823 15.0415,4.90692 15.0178,4.96039C 14.1369,6.94366
13.6325,9.07397 12.9858,11.1455C 10.716,12.1179 8.35062,12.8604 5.98325,13.5626'/>

<Path Canvas.Left='512.514' Canvas.Top='597.933' Fill='#13FFFFFF' Data='F1 M


19.7195,6.77734C 19.8074,6.49567 19.8962,6.21429 19.9832,5.93237C 20.3483,4.75012 20.7062,3.56561
21.0757,2.38477C 21.2146,1.94073 21.3682,1.50092 21.5392,1.06824C 21.6033,0.905884 21.8583,0.451538
21.7517,0.589722C 21.1888,1.31964 20.0965,1.76196 19.1857,1.62042C 18.321,1.48602 17.4153,0.809082 17.1389,0C
21.7517,0.589722C 21.1888,1.31964 20.0965,1.76196 19.1857,1.62042C 18.321,1.48602 17.4153,0.809082 17.1389,0C
19.1318,10.4485 18.1806,21.2667 17.9322,31.9006C 17.6079,51.0369 16.6355,70.1575 15.7578,89.2762C
13.0208,147.874 6.73367,207.348 16.0709,265.261L 16.4565,267.575L 6.89786,273.924L 5.741,266.983C
1.44327,240.013 -3.05176e-005,212.517 0.604462,185.213C 1.31583,153.081 4.76511,121.067 7.30185,89.0276C
8.78928,69.9962 10.4322,50.9692 11.325,31.9006C 11.8402,21.6796 13.1288,11.2933 11.445,1.19873C
11.8316,2.79156 12.7904,4.31171 14.0344,5.37897C 15.5455,6.67542 17.6418,7.46106 19.6328,7.46124C
21.4182,7.46143 23.2868,6.84399 24.7164,5.7746C 25.4158,5.2514 26.0371,4.60382 26.5277,3.88123C 27.1548,2.9577
26.9082,3.15735 26.5789,4.06342C 24.1927,4.65698 21.9753,5.79883 19.7195,6.77734'/>

<Path Canvas.Left='501.825' Canvas.Top='599.131' Fill='#0AFFFFFF' Data='F1 M


37.268,2.86469C 37.3909,2.52667 37.4291,2.13422 37.6622,1.86041C 37.8643,1.62311 37.3919,2.42468
37.2169,2.6825C 36.8389,3.23914 36.3875,3.7536 35.8782,4.19336C 34.694,5.21588 33.1653,5.93274
31.6179,6.16315C 27.8889,6.71838 23.0232,3.66382 22.1342,0C 23.8179,10.0946 22.5293,20.4808 22.0142,30.7019C
21.1213,49.7705 19.4784,68.7974 17.991,87.8289C 15.4542,119.868 12.0049,151.883 11.2936,184.014C
10.6891,211.318 12.1324,238.814 16.4301,265.784L 17.587,272.725L 8.02826,279.074L 6.10022,267.506C
1.60596,238.987 0,209.901 0.969299,181.047C 2.01971,149.778 6.0451,118.671 9.53497,87.5802C 11.6263,68.6351
13.9398,49.7056 15.407,30.7019C 16.1377,21.1011 17.8232,11.379 16.5275,1.83795L 17.5007,0.975525C
19.2956,3.14087 20.4688,5.93213 22.7429,7.58691C 25.7523,9.77667 30.1932,10.5807 33.7471,9.47583C
36.267,8.69244 38.8621,6.92627 39.9067,4.50305C 40.1278,3.99017 40.2916,3.21289 39.8872,2.8277C 39.255,2.22546
38.1189,2.66876 37.268,2.86469'/>

<Path Canvas.Left='537.592' Canvas.Top='676.453' Fill='#0AFFFFFF' Data='F1 M


8.39474,0C 9.02695,25.2888 10.1512,50.563 10.9824,75.8461C 12.3493,117.423 13.4348,159.012 14.1191,200.606C
10.576,202.306 7.03104,204.002 3.48611,205.698C 2.90854,138.909 1.6691,72.1233 -3.05176e-005,5.35199L
8.39474,0'/>

<Path Canvas.Left='529.197' Canvas.Top='681.805' Fill='#13FFFFFF' Data='F1 M


8.39474,0C 10.0639,66.7714 11.3033,133.557 11.8809,200.346C 8.31326,202.052 4.74515,203.757 1.17703,205.461C
0.993317,138.757 1.66635,72.0354 -3.05176e-005,5.35199L 8.39474,0'/>

<Path Canvas.Left='519.619' Canvas.Top='687.157' Fill='#21FFFFFF' Data='F1 M


9.57822,0C 11.2446,66.6833 10.5716,133.405 10.7553,200.109L 5.38089,202.676L 3.05176e-005,205.246L 3.05176e-
005,202.676C 0.216888,136.899 2.57358,71.1094 1.17392,5.34668L 5.38089,2.67596L 9.57822,0'/>

<Path Canvas.Left='508.857' Canvas.Top='692.504' Fill='#13FFFFFF' Data='F1 M


11.9359,0C 13.3355,65.7627 10.9788,131.552 10.762,197.329L 10.762,199.899L 0,205.04L 0,197.329C
0.582825,133.316 4.14764,69.324 3.46252,5.31122C 6.29211,3.54907 9.11792,1.78076 11.9359,0'/>

<Path Canvas.Left='498.095' Canvas.Top='697.815' Fill='#0AFFFFFF' Data='F1 M


14.2245,0C 14.9096,64.0128 11.3448,128.004 10.762,192.018L 10.762,199.729L 0,204.869L 0,192.018C
0.927979,129.748 5.57776,67.5497 5.66217,5.27271C 8.52319,3.52637 11.3752,1.76538 14.2245,0'/>

<Path Canvas.Left='522.398' Canvas.Top='705.885' Fill='#0AFFFFFF' Data='F1 M


7.43179,0C 9.72385,57.2985 15.081,114.479 16.0931,171.828L 10.8887,174.567L 7.72702,176.217C 7.16727,118.949
2.28903,61.8041 -3.05176e-005,4.57947L 7.43179,0'/>

<Path Canvas.Left='514.966' Canvas.Top='710.464' Fill='#13FFFFFF' Data='F1 M


7.43185,0C 9.72092,57.2246 14.5992,114.37 15.1589,171.637C 12.3605,173.09 9.55881,174.537 6.75174,175.973C
6.60959,118.797 2.28531,61.7092 -3.05176e-005,4.57947L 7.43185,0'/>

<Path Canvas.Left='507.533' Canvas.Top='715.044' Fill='#21FFFFFF' Data='F1 M


7.43335,0C 9.71869,57.1297 14.043,114.218 14.1851,171.393L 9.96747,173.54L 5.74481,175.679L 5.74481,173.54C
5.75513,117.188 2.20819,60.8906 0,4.58221L 3.71747,2.28973L 7.43335,0'/>

<Path Canvas.Left='500.084' Canvas.Top='719.626' Fill='#13FFFFFF' Data='F1 M


7.44836,0C 9.65656,56.3085 13.2035,112.606 13.1932,168.958L 13.1932,171.097L 4.74768,175.376L 4.74768,168.958C
4.90039,114.149 2.06049,59.3706 0,4.60095C 2.4823,3.06653 4.96484,1.53247 7.44836,0'/>

<Path Canvas.Left='492.614' Canvas.Top='724.227' Fill='#0AFFFFFF' Data='F1 M


7.46985,0C 9.53033,54.7696 12.3702,109.548 12.2175,164.357L 12.2175,170.775L 3.77203,175.053L 3.77203,164.357C
4.05975,111.102 1.87347,57.8567 0,4.62006L 4.65326,1.74146L 7.46985,0'/>

<Path Canvas.Left='535.14' Canvas.Top='666.73' Fill='#0AFFFFFF' Data='F1 M 7.59323,0C


10.3136,70.7286 12.3347,141.497 16.4458,212.158L 14.217,213.408L 7.8237,217.004C 3.87088,146.312
2.72098,75.4912 3.05176e-005,4.74127L 7.59323,0'/>

<Path Canvas.Left='527.547' Canvas.Top='671.471' Fill='#13FFFFFF' Data='F1 M


7.59329,0C 10.3142,70.7499 11.4641,141.571 15.417,212.263C 12.5341,213.886 9.65598,215.518 6.77859,217.151C
2.81387,146.423 2.72305,75.5282 3.05176e-005,4.74133L 7.59329,0'/>
<Path Canvas.Left='519.949' Canvas.Top='676.213' Fill='#21FFFFFF' Data='F1 M
7.59781,0C 10.3208,70.7869 10.4117,141.681 14.3764,212.41L 10.0513,214.871L 5.72556,217.337L 5.60226,215.118C
1.87619,145.065 2.54471,74.8432 3.05176e-005,4.73785L 3.8013,2.37061L 7.59781,0'/>

<Path Canvas.Left='512.321' Canvas.Top='680.951' Fill='#13FFFFFF' Data='F1 M


7.62796,0C 10.1726,70.1053 9.50412,140.327 13.2302,210.38L 13.3535,212.599L 4.70187,217.533L 4.33194,210.874C
0.871246,142.227 2.07346,73.4187 3.05176e-005,4.71509C 2.54678,3.15009 5.0881,1.57617 7.62796,0'/>

<Path Canvas.Left='504.551' Canvas.Top='685.666' Fill='#0AFFFFFF' Data='F1 M


7.76947,0C 9.8429,68.7036 8.64069,137.511 12.1014,206.159L 12.4713,212.818L 3.81964,217.751L 3.20306,206.654C
0,139.401 1.78412,71.9987 0.101685,4.69092L 2.08868,3.4801L 7.76947,0'/>

<Path Canvas.Left='529.653' Canvas.Top='775.667' Fill='#0AFFFFFF' Data='F1 M


3.93533,0C 5.905,11.818 8.35489,23.5586 10.0511,35.4189C 12.6742,53.7596 14.2744,72.2343 16.0516,90.6762C
17.5284,106.266 19.0768,121.92 18.7467,137.576C 18.382,154.877 15.6387,172.083 12.728,189.141L
5.70724,191.716L 4.17825,192.268C 6.80228,175.196 8.94351,157.991 9.54538,140.728C 10.1281,124.014
9.13193,107.274 8.26974,90.5724C 7.32645,72.2671 6.65793,53.9241 4.69485,35.7C 3.57437,25.298 1.71988,14.9865
-3.05176e-005,4.66675L 3.93533,0'/>

<Path Canvas.Left='525.419' Canvas.Top='780.333' Fill='#13FFFFFF' Data='F1 M


4.23447,0C 5.95438,10.3198 7.80887,20.6312 8.92935,31.0332C 10.8924,49.2573 11.5609,67.6003 12.5042,85.9057C
13.3664,102.607 14.3626,119.348 13.7799,136.062C 13.178,153.324 11.0368,170.529 8.41275,187.601L
2.85239,189.582L 3.05176e-005,190.575C 4.98697,155.973 5.02957,120.76 4.72232,85.8019C 4.52432,58.7174
4.7518,31.3834 0.299103,4.66675L 4.23447,0'/>

<Path Canvas.Left='517.085' Canvas.Top='785' Fill='#21FFFFFF' Data='F1 M 8.63297,0C


13.0857,26.7167 12.8582,54.0507 13.0562,81.1352C 13.3634,116.094 13.3208,151.306 8.33389,185.908L
4.16531,187.333L -3.05176e-005,188.736L 0.279694,186.778C 4.91116,151.795 4.08224,116.299 5.27444,81.0314C
6.19827,55.5858 8.40756,29.832 4.66098,4.64673L 6.66531,2.33331L 8.63297,0'/>

<Path Canvas.Left='508.754' Canvas.Top='789.647' Fill='#13FFFFFF' Data='F1 M


12.9919,0C 16.7385,25.1853 14.5292,50.9391 13.6053,76.3847C 12.4131,111.653 13.2421,147.149 8.6106,182.131L
8.33087,184.09L 0,186.896L 0.839233,181.021C 3.04376,162.793 2.76776,144.343 3.15253,125.985C 3.50024,109.397
4.56396,92.8251 5.82343,76.2809C 7.71704,52.4114 11.0048,28.348 8.77136,4.50781C 10.2088,3.03442
11.6233,1.5376 12.9919,0'/>

<Path Canvas.Left='500.423' Canvas.Top='794.155' Fill='#0AFFFFFF' Data='F1 M


17.1022,0C 19.3356,23.8402 16.0479,47.9036 14.1543,71.7731C 12.8948,88.3173 11.8311,104.889 11.4834,121.477C
11.0986,139.835 11.3746,158.285 9.1701,176.513L 8.33087,182.388L 0,185.195L 1.39874,175.403C 3.35522,157.447
2.09454,139.284 2.38593,121.223C 2.65326,104.654 4.427,88.1261 6.37244,71.6694C 9.09625,49.3019
13.3054,26.8771 12.5736,4.3562C 14.1226,2.94629 15.6181,1.47803 17.1022,0'/>

<Path Canvas.Left='537.286' Canvas.Top='682.521' Fill='#0AFFFFFF' Data='F1 M


8.08218,0C 10.5631,76.9047 13.8234,154.097 8.17368,230.834L 1.73312,233.709L -3.05176e-005,234.475C
5.9263,158.021 2.9075,81.0684 0.434967,4.4248L 8.08218,0'/>

<Path Canvas.Left='529.098' Canvas.Top='686.946' Fill='#13FFFFFF' Data='F1 M 8.6232,0C


11.0957,76.6436 14.1145,153.596 8.1882,230.05L 2.91745,232.36L 3.05176e-005,233.625C 6.19998,157.476
3.43948,80.7858 0.976044,4.42468L 8.6232,0'/>

<Path Canvas.Left='520.899' Canvas.Top='691.371' Fill='#21FFFFFF' Data='F1 M


9.17453,0C 11.638,76.3611 14.3985,153.051 8.19852,229.2L 4.10098,230.962L 3.05176e-005,232.716L
0.173431,230.635C 6.30557,155.48 3.95132,79.7905 1.52731,4.42474L 5.35098,2.21234L 9.17453,0'/>

<Path Canvas.Left='512.697' Canvas.Top='695.796' Fill='#13FFFFFF' Data='F1 M


9.72934,0C 12.1534,75.3658 14.5076,151.055 8.37546,226.21L 8.20206,228.291L 3.05176e-005,231.798L
0.520233,225.556C 6.53036,152.089 4.42703,78.0997 2.08035,4.42505L 7.00656,1.57532L 9.72934,0'/>

<Path Canvas.Left='504.495' Canvas.Top='700.221' Fill='#0AFFFFFF' Data='F1 M


10.2823,0C 12.629,73.6747 14.7324,147.664 8.72223,221.131L 8.20203,227.373L 0,230.88L 0.866943,220.476C
6.7572,148.697 4.9129,76.4071 2.63086,4.42322L 8.65961,0.938599L 10.2823,0'/>

<Path Canvas.Left='432.2' Canvas.Top='842.018' Fill='#0AFFFFFF' Data='F1 M 6.4668,0C


6.4668,41.4382 11.553,82.7584 16.2656,123.928L 7.96429,127.905L 6.01868,128.844C 3.85571,104.209
2.4707,79.5048 1.44073,54.7965C 0.743958,38.0807 0,21.3564 0,4.6261L 6.4668,0'/>

<Path Canvas.Left='424.92' Canvas.Top='846.644' Fill='#13FFFFFF' Data='F1 M 7.27997,0C


7.27997,16.7303 8.02393,33.4546 8.7207,50.1704C 9.75067,74.8787 11.1357,99.5833 13.2986,124.218L
6.46875,127.54L 2.85889,129.316C 0,87.8456 0.81311,46.1949 0.81311,4.62604L 7.27997,0'/>

<Path Canvas.Left='415.056' Canvas.Top='851.27' Fill='#21FFFFFF' Data='F1 M 10.6772,0C


10.6772,41.569 9.86414,83.2195 12.723,124.69L 7.44391,127.313L 2.15356,129.961L 2.00928,127.653C 0,86.6842
3.69135,45.6335 4.18457,4.61884L 7.44391,2.31299L 10.6772,0'/>

<Path Canvas.Left='404.983' Canvas.Top='855.889' Fill='#13FFFFFF' Data='F1 M


14.2574,0C 13.7642,41.0147 10.0729,82.0654 12.0822,123.034L 12.2264,125.342L 1.64557,130.639L 1.21271,123.713C
0,83.9608 5.94513,44.3077 7.57935,4.57043L 11.9847,1.5802L 14.2574,0'/>

<Path Canvas.Left='394.835' Canvas.Top='860.46' Fill='#0AFFFFFF' Data='F1 M 17.728,0C


16.0938,39.7373 10.1487,79.3903 11.3614,119.143L 11.7943,126.068L 1.21344,131.365L 0.492004,119.822C 0,81.2388
7.87634,42.998 10.7938,4.52197L 16.4392,0.85791L 17.728,0'/>

<Path Canvas.Left='427.281' Canvas.Top='853.191' Fill='#0AFFFFFF' Data='F1 M 4.8537,0C


7.0705,8.86707 9.64984,17.6635 11.2673,26.6592C 13.4749,38.937 14.5175,51.401 16.5663,63.7064C 18.277,73.9329
20.6514,84.2365 20.2245,94.5963C 19.9147,102.117 18.0505,109.534 16.0304,116.785C 12.9653,118.087
9.89197,119.37 6.8067,120.624C 8.76093,112.118 10.4553,103.449 10.6357,94.7234C 10.8489,84.408 9.14087,74.138
8.02753,63.8806C 6.79401,51.664 6.46783,39.3471 4.72339,27.1929C 3.67926,19.9182 1.78247,12.7867 0,5.65686L
4.8537,0'/>

<Path Canvas.Left='422.427' Canvas.Top='858.848' Fill='#13FFFFFF' Data='F1 M


4.85376,0C 6.63623,7.12988 8.53302,14.2613 9.57715,21.536C 11.3216,33.6902 11.6478,46.0071 12.8813,58.2238C
13.9946,68.4811 15.7027,78.7512 15.4894,89.0666C 15.309,97.7921 13.6147,106.462 11.6605,114.967C
8.79163,116.117 5.90271,117.217 3.00427,118.289C 4.86536,108.722 5.91254,98.9402 5.90057,89.1937C
5.888,78.9154 4.88293,68.6622 4.34253,58.398C 3.62128,40.7729 4.2785,22.77 0,5.6568L 4.85376,0'/>

<Path Canvas.Left='417.097' Canvas.Top='864.505' Fill='#21FFFFFF' Data='F1 M


5.33002,0C 9.60852,17.1132 8.95129,35.1161 9.67255,52.7412C 10.213,63.0054 11.218,73.2585 11.2306,83.5369C
11.2426,93.2834 10.1954,103.065 8.33429,112.633L 7.86279,112.803L 4.1532,114.078L 0,115.446L 0.422668,113.332C
2.09387,103.577 1.88562,93.5588 1.64197,83.6641C 1.38965,73.4163 1.12836,63.1664 1.13385,52.9155C
1.36096,37.1375 3.49573,21.0541 0.393616,5.58228C 2.10748,3.78436 3.71252,1.88513 5.33002,0'/>

<Path Canvas.Left='408.642' Canvas.Top='870.087' Fill='#13FFFFFF' Data='F1 M


8.84833,0C 11.9504,15.4717 9.81567,31.5552 9.58856,47.3332C 9.58307,57.5841 9.84436,67.8339 10.0967,78.0817C
10.3403,87.9764 10.5486,97.9943 8.87738,107.75L 8.45471,109.863L 0.14801,112.598L 1.41614,106.258C
2.6189,96.9808 0.971924,87.5519 0.507813,78.2089C 0,67.9861 0.525757,57.7294 1.0498,47.5074C 1.97443,33.3734
4.70142,19.1791 3.36713,5.07782C 5.28046,3.48334 7.09772,1.77155 8.84833,0'/>

<Path Canvas.Left='398.78' Canvas.Top='875.165' Fill='#0AFFFFFF' Data='F1 M 13.2292,0C


14.5635,14.1013 11.8365,28.2955 10.9119,42.4296C 10.3879,52.6516 9.86212,62.9083 10.3699,73.131C 10.834,82.474
12.481,91.903 11.2783,101.18L 10.0101,107.52L 1.70355,110.255L 3.81708,99.6876C 4.5318,90.8488 1.45801,82.1001
0.781067,73.2582C 0,63.0562 1.35846,52.7853 2.37311,42.6039C 3.80396,29.9093 7.11176,17.3496 7.125,4.57465C
9.20746,3.1156 11.2475,1.5932 13.2292,0'/>

<Path Canvas.Left='405.254' Canvas.Top='855.789' Fill='#0AFFFFFF' Data='F1 M


0,26.4583C 0.870667,22.9757 1.74579,19.4942 2.61206,16.0105L 2.57996,16.083C 2.2536,15.0787 2.68835,13.973
2.79114,12.922C 3.10388,9.7243 4.5318,6.37354 6.90088,4.20313C 10.1198,1.25403 15.4432,0 19.645,1.18457C
24.3359,2.50708 28.2311,7.60608 29.0038,12.4182C 30.101,17.9135 30.2953,23.5698 31.4927,29.0441C
33.0136,36.973 34.7012,44.8691 36.2417,52.7941C 38.1308,62.8497 39.6484,73.036 39.9581,83.2629C 40.299,94.5175
39.398,105.777 38.8745,117.025C 35.7857,118.453 32.6996,119.887 29.6188,121.333C 29.8853,108.643
30.6038,95.9531 30.3732,83.2629C 30.1881,73.0812 29.2839,62.9135 28.1434,52.7941C 27.2197,44.8744
26.2056,36.9653 25.294,29.0441C 24.6937,23.7296 24.7004,18.3408 23.8007,13.0686C 23.4195,10.6582
21.9581,8.1109 19.8289,6.9187C 17.3397,5.5249 13.6339,5.73279 11.2811,7.34613C 8.47266,9.27185 7.90997,13.4574
7.50543,16.8385C 7.38666,17.8314 6.13959,22.5221 5.89838,23.4926L 0,26.4583'/>

<Path Canvas.Left='411.152' Canvas.Top='861.314' Fill='#13FFFFFF' Data='F1 M


0,17.9677C 0.5224,15.8782 1.05145,13.7903 1.56726,11.6991C 2.01343,9.89038 1.86768,7.96326 2.36285,6.16736C
2.83179,4.46674 3.9278,2.81885 5.38269,1.82123C 7.73553,0.207886 11.4413,0 13.9305,1.3938C 16.0598,2.586
17.5211,5.1333 17.9023,7.5437C 18.8021,12.8159 18.7953,18.2047 19.3956,23.5192C 20.3073,31.4404
21.3213,39.3495 22.245,47.2692C 23.3856,57.3885 24.2897,67.5563 24.4748,77.738C 24.7054,90.4282
23.9869,103.118 23.7205,115.808C 20.6833,117.239 17.6473,118.673 14.6155,120.115C 14.7014,95.833
15.0585,71.5347 14.1466,47.2692C 13.8388,39.3522 13.5005,31.4364 13.1968,23.5192C 13.069,18.4097
13.3732,13.2605 12.6991,8.19409C 12.5665,7.31445 12.0861,6.35022 11.31,5.91553C 10.3889,5.39954
8.94244,5.57129 8.16431,6.28485C 7.37561,7.00812 7.19049,8.22736 7.0177,9.28345C 6.70404,11.2003
6.36951,13.1177 5.89838,15.0021L 0,17.9677'/>

<Path Canvas.Left='416.262' Canvas.Top='866.714' Fill='#21FFFFFF' Data='F1 M


0.788696,9.60254C 1.25983,7.71814 1.59436,5.80078 1.90802,3.88391C 2.08081,2.82782 2.26593,1.60858
3.05463,0.885315C 3.83276,0.171753 5.27917,0 6.20032,0.515991C 6.97644,0.950684 7.45685,1.91492
7.58942,2.79456C 8.26355,7.86096 7.95935,13.0102 8.08716,18.1197C 8.39087,26.0369 8.72913,33.9527
9.03693,41.8697C 9.94879,66.1351 9.59167,90.4335 9.50586,114.716L 4.98785,116.87L 0.475647,119.024L
0.475647,116.87C 0.406616,91.8693 0,66.8525 0.938782,41.8697C 1.24658,33.9527 1.58484,26.0369 1.88855,18.1197C
2.12872,13.2311 2.78784,8.32275 2.38629,3.44482C 2.5932,4.0752 3.00085,4.71362 3.57983,5.0376C 4.1322,5.34662
4.83881,5.4505 5.45782,5.3183C 5.97278,5.20831 6.46289,4.89893 6.81171,4.50452C 6.98218,4.31177
7.28503,3.59729 7.21002,3.84338C 6.95074,4.69415 6.82135,5.57935 6.64856,6.45178C 4.71991,7.54663
2.77008,8.60632 0.788696,9.60254'/>

<Path Canvas.Left='406.709' Canvas.Top='870.158' Fill='#13FFFFFF' Data='F1 M


16.2016,3.00696C 16.3089,2.46539 16.4115,1.92285 16.5234,1.3822C 16.5752,1.13232 16.6349,0.884155
16.6927,0.63562C 16.7134,0.546204 16.6603,0.0198975 16.7687,0.374451C 16.9938,1.11084 15.7639,1.71265
15.0109,1.87347C 13.8411,2.12329 12.2174,1.17371 11.9393,0C 12.3409,4.87793 11.6818,9.78632 11.4416,14.6749C
11.1379,22.592 10.7996,30.5079 10.4918,38.4249C 9.55304,63.4077 9.95966,88.4245 10.0287,113.425L
10.0287,115.579L 1.00409,119.886L 1.00409,113.425C 0.887634,99.3599 0,85.3022 0.131836,71.2374C
0.234619,60.2744 1.16553,49.3193 2.39343,38.4249C 3.31714,30.5051 4.33118,22.596 5.2428,14.6749C
5.75232,10.1502 6.77863,5.65063 6.74115,1.09747L 7.45117,0.561035C 8.3728,1.34119 8.52313,2.75879
9.32611,3.66064C 10.5359,5.01941 12.4445,5.93909 14.2631,5.9873C 16.7341,6.05286 20.4626,4.16425
20.3116,1.69702C 20.2745,1.09155 19.0372,1.48169 18.4927,1.74902C 17.7106,2.13306 16.9653,2.58765
16.2016,3.00696'/>

<Path Canvas.Left='397.015' Canvas.Top='871.256' Fill='#0AFFFFFF' Data='F1 M


16.4351,0C 16.4725,4.5531 15.4462,9.05273 14.9367,13.5774C 14.0251,21.4985 13.011,29.4077 12.0873,37.3274C
10.8594,48.2219 9.92853,59.1769 9.82574,70.1399C 9.69391,84.2048 10.5815,98.2624 10.698,112.327L
10.698,118.789L 1.6734,123.097L 1.6734,112.327C 1.47955,98.2579 0,84.209 0.219666,70.1399C 0.391541,59.1318
1.9563,48.1475 3.98901,37.3274C 5.52954,29.4023 7.2171,21.5062 8.73798,13.5774C 9.30402,10.1974
10.0753,6.85498 10.7356,3.49207C 12.6863,2.41547 14.6225,1.29578 16.4351,0'/>

<Path Canvas.Left='444.56' Canvas.Top='820.859' Fill='#0AFFFFFF' Data='F1 M 7.20685,0C


7.20685,27.9612 9.44635,55.8844 11.3217,83.7826C 12.1189,95.6415 13.1082,107.497 13.399,119.379C
13.7604,134.148 11.8053,148.886 11.3597,163.653C 8.63245,165.313 5.92157,167.001 3.23346,168.723C
2.78845,152.342 3.99408,135.946 3.63055,119.563C 2.78003,81.2289 0,42.9333 0,4.58984L 7.20685,0'/>

<Path Canvas.Left='437.353' Canvas.Top='825.449' Fill='#13FFFFFF' Data='F1 M


7.20679,0C 7.20679,38.3434 9.98682,76.639 10.8373,114.973C 11.2009,131.356 9.99524,147.752 10.4402,164.133C
7.83838,165.828 5.24304,167.533 2.67621,169.28C 1.34149,150.422 1.42834,131.49 1.01422,112.589C
0.225647,76.5962 0,40.5911 0,4.58972L 7.20679,0'/>

<Path Canvas.Left='428.027' Canvas.Top='830.038' Fill='#21FFFFFF' Data='F1 M


9.32684,0C 9.32684,36.0013 9.55249,72.0065 10.3411,107.999C 10.7552,126.9 10.6683,145.832 12.0031,164.69L
8.22351,167.295L 4.47052,169.91L 4.27997,167.623C 2.56,148.705 0.964233,129.745 0.627441,110.751C 0,75.3649
1.84497,39.9768 2.10425,4.58606L 5.72351,2.29486L 9.32684,0'/>

<Path Canvas.Left='418.357' Canvas.Top='834.625' Fill='#13FFFFFF' Data='F1 M


11.7734,0C 11.5141,35.3907 9.66913,70.7788 10.2966,106.165C 10.6334,125.159 12.2291,144.119 13.9491,163.037L
14.1396,165.324L 6.63348,170.556L 6.06177,163.695C 3.9718,144.605 0.826843,125.551 0.528137,106.349C 0,72.3992
3.48767,38.5031 4.42554,4.56232C 6.88062,3.0509 9.33295,1.53491 11.7734,0'/>

<Path Canvas.Left='408.681' Canvas.Top='839.187' Fill='#0AFFFFFF' Data='F1 M


14.1024,0C 13.1645,33.9407 9.67682,67.8369 10.205,101.786C 10.5037,120.988 13.6486,140.042 15.7386,159.132L
16.3103,165.993L 8.8042,171.224L 7.85132,159.79C 5.38983,140.515 0.697205,121.4 0.436523,101.97C 0,69.4316
4.86108,37.035 6.57898,4.5387C 9.09424,3.03827 11.6029,1.52661 14.1024,0'/>

<Path Canvas.Left='511.346' Canvas.Top='372.845' Fill='#0AFFFFFF' Data='F1 M


0.897339,0C 1.74622,1.13184 2.50983,2.33295 3.44397,3.39557C 5.02045,5.1889 7.49384,5.92902 9.45972,7.28418C
10.0416,7.76801 10.6465,8.22528 11.2052,8.7356C 11.546,9.04688 11.8373,9.40833 12.1534,9.74469C
11.8716,10.1653 11.6083,10.599 11.308,11.0066C 10.7234,11.8 10.1027,12.5662 9.5,13.3461C 9.05908,11.7158
7.81244,10.3788 6.63745,9.16571C 4.33655,7.13837 1.83997,5.24847 0,2.79517L 0.897339,0'/>

<Path Canvas.Left='510.449' Canvas.Top='375.641' Fill='#13FFFFFF' Data='F1 M


0.897278,0C 2.73724,2.45331 5.23383,4.3432 7.53473,6.37054C 8.70972,7.58362 9.95636,8.92065 10.3973,10.5509L
9.26855,12.0498L 7.9704,13.9141C 7.11633,11.9111 6.01343,9.99811 4.71246,8.25201C 3.1651,6.41309
1.44208,4.71783 0,2.79523L 0.897278,0'/>

<Path Canvas.Left='509.533' Canvas.Top='378.436' Fill='#21FFFFFF' Data='F1 M


0.915405,0C 2.35748,1.92261 4.08051,3.61786 5.62787,5.45679C 6.92883,7.20288 8.03174,9.11584 8.8858,11.1188L
7.9668,12.6475L 7.11871,14.1464L 6.68195,13.4185C 5.25513,11.4842 3.93341,9.46088 2.80573,7.33826C
1.93073,5.79749 0.987976,4.29419 0,2.82324L 0.466797,1.39752L 0.915405,0'/>
<Path Canvas.Left='508.332' Canvas.Top='381.259' Fill='#13FFFFFF' Data='F1 M 1.2016,0C
2.18958,1.47095 3.13232,2.97424 4.00732,4.51501C 5.13501,6.63763 6.45673,8.66095 7.88354,10.5952L
8.32031,11.3231L 6.62402,14.3208L 5.31378,12.137C 4.82782,11.6909 4.34399,11.2424 3.85596,10.7986C
3.38788,10.3729 2.8299,10.0309 2.44556,9.52832C 2.09863,9.07465 1.91693,8.51373 1.70367,7.98395C
1.49585,7.46753 1.35791,6.92566 1.18506,6.39648C 0.835754,5.27765 0.463196,4.16266 0,3.086L 0.754089,1.26501L
1.2016,0'/>

<Path Canvas.Left='506.526' Canvas.Top='384.345' Fill='#0AFFFFFF' Data='F1 M


1.80609,0C 2.26929,1.07666 2.64185,2.19165 2.99115,3.31049C 3.164,3.83966 3.30194,4.38153 3.50977,4.89795C
3.72302,5.42773 3.90472,5.98865 4.25165,6.44232C 4.63599,6.94495 5.19397,7.28687 5.66205,7.71259C
6.15009,8.15643 6.63391,8.60486 7.11987,9.05103L 8.43011,11.2348L 6.73395,14.2325L 4.55017,10.5929C
3.9455,10.1984 3.34631,9.79553 2.73621,9.40955C 2.16119,9.04578 1.45251,8.84778 0.9953,8.34387C
0.625916,7.93677 0.520203,7.34521 0.380798,6.81348C 0.242554,6.28619 0.239502,5.73248 0.168884,5.19202L
0.0679321,3.80371L 0,3.36664L 1.27899,1.13275L 1.80609,0'/>

<Path Canvas.Left='509.542' Canvas.Top='345.609' Fill='#0AFFFFFF' Data='F1 M


3.02783,0C 5.20624,3.04974 7.32452,6.14331 9.56299,9.14923C 11.6459,11.9462 14.2863,14.2856 16.7824,16.7209C
21.6539,21.4737 26.7247,26.0266 31.447,30.9277C 29.8969,33.8508 28.2827,36.7409 26.6032,39.5916C
18.126,28.6437 8.04797,18.9568 0,7.68964L 3.02783,0'/>

<Path Canvas.Left='506.514' Canvas.Top='353.299' Fill='#13FFFFFF' Data='F1 M


3.02783,0C 11.0758,11.2672 21.1539,20.9541 29.631,31.902C 27.8084,34.8963 25.959,37.8758 24.0252,40.7995C
16.6827,29.3091 7.92572,18.7858 0,7.68958L 3.02783,0'/>

<Path Canvas.Left='503.441' Canvas.Top='360.989' Fill='#21FFFFFF' Data='F1 M


3.07324,0C 10.999,11.0962 19.7559,21.6195 27.0984,33.1099L 24.0594,37.5948L 20.954,42.0804L 19.7971,40.1522C
13.4797,29.1722 7.09149,18.2098 0,7.7132L 1.55939,3.84479L 3.07324,0'/>

<Path Canvas.Left='499.955' Canvas.Top='368.702' Fill='#13FFFFFF' Data='F1 M


3.48535,0C 10.5768,10.4966 16.965,21.459 23.2824,32.439L 24.4393,34.3672L 18.2285,43.3386L 14.7576,37.5539C
9.70526,27.7474 5.37183,17.5671 0,7.93188C 1.19995,5.30499 2.3797,2.66791 3.48535,0'/>

<Path Canvas.Left='495.811' Canvas.Top='376.634' Fill='#0AFFFFFF' Data='F1 M


4.14453,0C 9.51636,9.63525 13.8498,19.8155 18.9022,29.622L 22.373,35.4067L 16.1622,44.3781L 10.3774,34.7369C
6.4563,26.1122 3.65417,17.0177 0,8.27661C 1.43732,5.54639 2.82483,2.78894 4.14453,0'/>

<Path Canvas.Left='513.546' Canvas.Top='360.061' Fill='#0AFFFFFF' Data='F1 M


0.697296,0C 4.11087,3.90118 8.13437,7.23865 12.1218,10.5511C 15.6359,13.4703 19.4104,16.7527 20.9096,21.0682L
19.9584,22.722L 18.8535,24.7473C 17.9281,22.8326 17.0605,20.8524 15.7694,19.1626C 11.1865,13.1642
4.97092,8.5899 3.05176e-005,2.90881L 0.697296,0'/>

<Path Canvas.Left='512.849' Canvas.Top='362.97' Fill='#13FFFFFF' Data='F1 M


0.697418,0C 5.6683,5.68109 11.8839,10.2554 16.4668,16.2538C 17.7578,17.9436 18.6255,19.9238 19.5509,21.8385L
18.7196,23.4695L 17.8772,25.2399C 12.5288,17.346 6.27902,10.0848 3.05176e-005,2.90887L 0.697418,0'/>

<Path Canvas.Left='512.129' Canvas.Top='365.879' Fill='#21FFFFFF' Data='F1 M


0.719269,0C 6.99826,7.1759 13.2481,14.4371 18.5965,22.3311L 17.8706,23.9544L 17.1682,25.5624L 16.6492,24.8705C
10.8655,17.7366 5.82803,10.0162 3.05176e-005,2.91858L 0.370636,1.45441L 0.719269,0'/>

<Path Canvas.Left='511.247' Canvas.Top='368.797' Fill='#13FFFFFF' Data='F1 M


0.882141,0C 6.71014,7.09766 11.7476,14.8181 17.5313,21.9519L 18.0503,22.6439L 16.6454,25.8599L 15.0885,23.784C
13.0245,21.6053 10.5558,19.7775 8.78772,17.3525C 5.48175,12.8184 3.17249,7.6225 0,2.99402L 0.443237,1.57031L
0.882141,0'/>

<Path Canvas.Left='510.126' Canvas.Top='371.792' Fill='#0AFFFFFF' Data='F1 M


1.12122,0C 4.2937,4.62848 6.60297,9.82434 9.90894,14.3585C 11.6771,16.7835 14.1457,18.6113 16.2097,20.79L
17.7667,22.8659L 16.3618,26.082L 13.7668,22.6221C 11.5082,20.5708 8.59418,19.1461 6.81543,16.6672C
3.86932,12.5613 2.38953,7.57788 0,3.12506L 0.527832,1.72736L 1.12122,0'/>

<Path Canvas.Left='521.077' Canvas.Top='349.845' Fill='#0AFFFFFF' Data='F1 M


0.718048,0C 4.40427,4.21277 8.63284,7.91827 12.5745,11.8931C 16.0202,15.3677 19.6208,19.3456 20.7022,24.1181L
19.6316,25.5667L 18.1821,27.6235C 17.4313,25.5131 16.7575,23.3384 15.6065,21.4169C 11.4711,14.5128
5.29959,9.052 -3.05176e-005,2.99536L 0.718048,0'/>

<Path Canvas.Left='520.359' Canvas.Top='352.84' Fill='#13FFFFFF' Data='F1 M


0.717987,0C 6.01761,6.05664 12.1891,11.5174 16.3246,18.4215C 17.4756,20.3431 18.1493,22.5178 18.9001,24.6281L
17.9024,26.1411L 16.8099,27.9095C 12.0912,19.0722 6.59695,10.535 -3.05176e-005,2.99542L 0.717987,0'/>

<Path Canvas.Left='519.605' Canvas.Top='355.836' Fill='#21FFFFFF' Data='F1 M


<Path Canvas.Left='519.605' Canvas.Top='355.836' Fill='#21FFFFFF' Data='F1 M
0.753632,0C 7.35062,7.53961 12.8448,16.0768 17.5636,24.9141L 16.6446,26.4976L 15.7547,28.0703L
15.2964,27.3065C 10.0935,19.2715 6.00772,10.4545 -3.05176e-005,3.00208L 0.394562,1.49762L 0.753632,0'/>

<Path Canvas.Left='518.621' Canvas.Top='358.838' Fill='#13FFFFFF' Data='F1 M


0.984344,0C 6.9921,7.45245 11.0779,16.2694 16.2808,24.3044L 16.739,25.0682L 14.9593,28.2134L 13.5845,25.9222C
11.6726,23.4028 9.32449,21.1805 7.76218,18.4306C 4.92264,13.4326 3.11496,7.86249 -3.05176e-005,3.03137L
0.488434,1.64124L 0.984344,0'/>

<Path Canvas.Left='517.319' Canvas.Top='361.869' Fill='#0AFFFFFF' Data='F1 M


1.30173,0C 4.41672,4.83112 6.2244,10.4012 9.06393,15.3992C 10.6263,18.1491 12.9744,20.3714 14.8863,22.8908L
16.261,25.1821L 14.4814,28.3275L 12.19,24.5086C 10.0628,22.0862 7.20078,20.217 5.6304,17.4014C 3.13602,12.9291
2.19156,7.73584 -3.05176e-005,3.10754L 0.578339,1.81671L 1.30173,0'/>

<Path Canvas.Left='500.405' Canvas.Top='361.561' Fill='#0AFFFFFF' Data='F1 M


2.76984,0C 5.45221,3.75531 8.07111,7.58704 11.1805,10.9972C 16.7211,17.0735 22.8942,22.5746 28.1854,28.8693C
27.3867,31.0504 26.5469,33.2184 25.6191,35.3479C 20.6055,28.4407 14.1976,22.6614 8.40088,16.3969C 5.341,13.09
2.61865,9.47504 0,5.8089L 2.76984,0'/>

<Path Canvas.Left='497.635' Canvas.Top='367.37' Fill='#13FFFFFF' Data='F1 M 2.7699,0C


5.38855,3.66614 8.1109,7.28113 11.1708,10.588C 16.9675,16.8525 23.3754,22.6318 28.389,29.539C 27.4351,31.6412
26.425,33.7197 25.3402,35.7574C 18.1945,24.8056 7.60089,16.4499 0,5.8089L 2.7699,0'/>

<Path Canvas.Left='494.916' Canvas.Top='373.179' Fill='#21FFFFFF' Data='F1 M


2.71899,0C 10.3199,10.641 20.9135,18.9967 28.0592,29.9485L 27.6974,30.6003L 26.334,32.9044L 24.5357,35.8008L
23.7339,34.4644C 17.2686,23.8931 7.43591,15.7645 0,5.85181C 0.856506,3.87885 1.79321,1.94147 2.71899,0'/>

<Path Canvas.Left='492.501' Canvas.Top='379.031' Fill='#13FFFFFF' Data='F1 M


2.41498,0C 9.85089,9.91266 19.6836,18.0413 26.1489,28.6126L 26.9507,29.949L 23.3539,35.7419L 20.9485,31.7328C
15.2678,22.2799 6.74939,14.8461 0,6.12402L 1.6983,1.70691L 2.41498,0'/>

<Path Canvas.Left='490.331' Canvas.Top='385.155' Fill='#0AFFFFFF' Data='F1 M


2.16956,0C 8.91895,8.72205 17.4373,16.1559 23.118,25.6088L 25.5235,29.6179L 21.9266,35.4108L 17.9176,28.7291C
13.0791,20.4859 6.11426,13.6882 0,6.34137C 0.699524,4.2196 1.40979,2.10089 2.16956,0'/>

<Path Canvas.Left='519.588' Canvas.Top='360.076' Fill='#0AFFFFFF' Data='F1 M


1.39157,0C 3.6857,4.12946 6.55484,7.96204 9.73355,11.4565C 13.3214,15.4008 17.5403,19.5002 18.6967,24.7053L
17.3957,26.4726L 16.0534,28.3992C 15.3123,26.3082 14.6488,24.1541 13.5168,22.246C 9.50333,15.481
3.81998,9.77905 -3.05176e-005,2.90289L 1.39157,0'/>

<Path Canvas.Left='518.196' Canvas.Top='362.979' Fill='#13FFFFFF' Data='F1 M


1.39169,0C 5.2117,6.87616 10.8951,12.5781 14.9085,19.3431C 16.0405,21.2512 16.7041,23.4053 17.4452,25.4963L
16.3322,27.1991L 15.2626,28.9473C 10.5182,20.0737 4.88687,11.6989 3.05176e-005,2.90295L 1.39169,0'/>

<Path Canvas.Left='516.787' Canvas.Top='365.882' Fill='#21FFFFFF' Data='F1 M


1.40836,0C 6.2952,8.79596 11.9265,17.1707 16.6709,26.0444L 15.7126,27.7014L 14.7826,29.345L 14.3036,28.5468C
8.957,20.3517 4.53342,11.5839 3.05176e-005,2.91248L 0.712555,1.45142L 1.40836,0'/>

<Path Canvas.Left='515.229' Canvas.Top='368.794' Fill='#13FFFFFF' Data='F1 M


1.55826,0C 6.09164,8.67145 10.5152,17.4393 15.8618,25.6343L 16.3408,26.4326L 14.4807,29.7197L 13.0439,27.3251C
11.0868,24.7819 8.65976,22.5599 7.08493,19.7639C 4.10757,14.4778 2.40762,8.56757 3.05176e-005,2.99884L
0.781158,1.52972L 1.55826,0'/>

<Path Canvas.Left='513.435' Canvas.Top='371.793' Fill='#0AFFFFFF' Data='F1 M 1.7941,0C


4.20169,5.56873 5.90164,11.479 8.879,16.7651C 10.4538,19.5611 12.8808,21.7831 14.8379,24.3262L
16.2747,26.7209L 14.4147,30.0082L 12.02,26.017C 9.82901,23.5755 6.87106,21.7138 5.2822,18.8438C
2.60654,14.0109 1.7106,8.38831 3.05176e-005,3.13568L 0.876129,1.6424L 1.7941,0'/>

<Path Canvas.Left='506.996' Canvas.Top='366.061' Fill='#0AFFFFFF' Data='F1 M


2.99725,0C 4.8938,3.79309 6.76868,7.62164 9.10828,11.1587C 13.3355,17.5494 18.3422,23.4095 22.4506,29.8773L
19.9826,34.061L 19.3724,35.0446C 13.3369,24.6103 5.39075,15.2905 0,4.50891L 2.99725,0'/>

<Path Canvas.Left='503.999' Canvas.Top='370.57' Fill='#13FFFFFF' Data='F1 M 2.99731,0C


8.38806,10.7816 16.3342,20.1014 22.3698,30.5356L 20.2171,33.848L 19.0237,35.574C 13.3796,24.8231
5.43024,15.3694 0,4.50885L 2.99731,0'/>

<Path Canvas.Left='501.029' Canvas.Top='375.079' Fill='#21FFFFFF' Data='F1 M


2.96985,0C 8.40009,10.8605 16.3495,20.3142 21.9936,31.0652L 20.2213,33.5045L 18.4061,35.9172L 17.8041,34.7131C
12.4988,24.3087 5.30359,14.9423 0,4.53711L 1.47125,2.25446L 2.96985,0'/>
<Path Canvas.Left='498.175' Canvas.Top='379.616' Fill='#13FFFFFF' Data='F1 M
2.85419,0C 8.15778,10.4052 15.353,19.7715 20.6583,30.176L 21.2603,31.3801L 17.6299,36.2055L 15.8238,32.5932C
11.0995,23.0212 4.93359,14.2186 0,4.75275L 1.84882,1.6214L 2.85419,0'/>

<Path Canvas.Left='495.41' Canvas.Top='384.369' Fill='#0AFFFFFF' Data='F1 M 2.76495,0C


7.69855,9.46588 13.8644,18.2684 18.5887,27.8405L 20.3949,31.4528L 16.7645,36.2782L 13.7543,30.2577C
9.63574,21.5869 4.45612,13.4592 0,4.95703L 2.22925,0.936035L 2.76495,0'/>

<Path Canvas.Left='486.96' Canvas.Top='360.386' Fill='#0AFFFFFF' Data='F1 M


0.473389,0C 5.44806,4.97467 11.1729,9.13812 16.4714,13.7664C 19.2441,16.1884 22.1142,18.6244 24.1946,21.6619C
25.4818,23.5413 26.3314,25.6936 27.2013,27.799L 26.5368,28.9991L 25.3981,31.1077C 23.9229,28.2963
22.5483,25.3817 20.5753,22.8942C 14.6146,15.3798 6.78217,9.5611 0,2.77893L 0.473389,0'/>

<Path Canvas.Left='486.487' Canvas.Top='363.165' Fill='#13FFFFFF' Data='F1 M


0.473328,0C 7.25549,6.78217 15.0879,12.6009 21.0486,20.1153C 23.0217,22.6027 24.3962,25.5174 25.8715,28.3288C
25.3276,29.3574 24.7947,30.3918 24.2661,31.4283C 17.5682,20.8565 8.84949,11.6284 0,2.77887L 0.473328,0'/>

<Path Canvas.Left='486' Canvas.Top='365.944' Fill='#21FFFFFF' Data='F1 M 0.486389,0C


9.33588,8.84949 18.0546,18.0776 24.7524,28.6495L 23.9997,30.1394L 23.2547,31.6157L 22.8026,30.9375C
15.8441,21.0677 8.37683,11.4839 0,2.78558L 0.249695,1.3894L 0.486389,0'/>

<Path Canvas.Left='485.414' Canvas.Top='368.729' Fill='#13FFFFFF' Data='F1 M


0.586426,0C 8.96326,8.69836 16.4305,18.2822 23.389,28.1519L 23.8411,28.8301L 22.3511,31.7828L 20.9946,29.7481C
18.664,26.7487 15.7255,24.2474 13.4642,21.1954C 8.94672,15.0983 4.92749,8.60999 0,2.83929C 0.213318,1.89673
0.40564,0.949341 0.586426,0'/>

<Path Canvas.Left='484.684' Canvas.Top='371.569' Fill='#0AFFFFFF' Data='F1 M


0.730164,0C 5.65765,5.77069 9.67688,12.259 14.1943,18.3561C 16.4557,21.4081 19.3942,23.9094 21.7248,26.9088L
23.0812,28.9435L 21.5912,31.8962L 19.3305,28.5051C 16.8835,25.649 13.5114,23.6192 11.3085,20.5709C
7.21661,14.9086 4.17743,8.5249 0,2.92535L 0.277588,1.87708L 0.730164,0'/>

<Path Canvas.Left='195.392' Canvas.Top='307' Fill='#0BFFFFFF' Data='F1 M


9.16724,28.4007C 15.1577,33.8283 22.7307,37.4866 30.3297,40.2433C 42.3451,44.6022 55.0782,46.869
66.9612,51.5768C 83.3445,58.0677 99.3385,65.5357 115.839,71.7235C 125.403,75.3104 135.146,78.7107
145.208,80.4741C 165.18,83.4549 185.562,83.8677 205.736,82.9918C 230.7,81.9081 255.878,78.5641
279.776,71.2646C 290.016,68.1369 300.043,64.093 309.471,59.0191C 312.547,57.3643 315.56,55.5853
318.478,53.6677C 319.894,52.7375 321.214,51.6227 322.762,50.935C 326.711,49.1807 331.073,48.5516
335.287,47.5955C 342.207,46.0251 349.161,44.4485 355.84,42.051C 368.592,37.4736 381.032,29.0035
388.271,17.5515L 393.913,0L 393.691,7.67468L 390.306,18.2055C 384.651,29.4542 375.527,39.2471 365.155,46.3835C
354.92,53.4261 343.065,57.7786 332.277,63.9413C 327.735,66.5355 323.557,69.7377 318.993,72.2916C
310.609,76.9833 301.739,80.8506 292.69,84.0781C 269.229,92.4453 244.177,96.5443 219.33,98.2936C
193.927,100.082 168.171,99.6116 142.968,95.9592C 131.957,94.1539 121.23,90.7247 110.724,86.9653C
92.1394,80.315 74.2321,71.8701 56.3553,63.5018C 43.9037,57.6731 30.9771,52.5536 19.503,44.9797C
11.8763,39.9453 4.70587,33.546 0,25.7123C 2.90372,27.0197 6.02472,27.8857 9.16724,28.4007'/>

<Path Canvas.Left='188.035' Canvas.Top='314.675' Fill='#15FFFFFF' Data='F1 M


7.3566,18.0377C 12.0625,25.8713 19.2329,32.2706 26.8596,37.305C 38.3336,44.879 51.2603,49.9984
63.7119,55.8271C 81.5887,64.1954 99.496,72.6403 118.08,79.2906C 128.586,83.05 139.313,86.4792 150.324,88.2845C
175.527,91.9369 201.284,92.4073 226.687,90.6189C 251.533,88.8696 276.586,84.7706 300.046,76.4034C
309.096,73.176 317.965,69.3087 326.35,64.6169C 330.914,62.063 335.092,58.8608 339.633,56.2666C 350.421,50.1039
362.276,45.7514 372.512,38.7089C 382.884,31.5724 392.008,21.7795 397.663,10.5308L 401.048,0L 400.826,7.67456L
399.697,11.1848C 395.641,21.6917 389.864,31.7017 382.676,40.3724C 373.259,51.7317 361.34,60.9622
349.148,69.2728C 341.23,74.6703 333.037,79.7544 324.392,83.8893C 301.458,94.8588 276.139,101.073
250.935,104.401C 216.946,108.89 182.033,108.556 148.085,103.769C 134.228,101.604 120.701,97.3915
107.516,92.6107C 89.6569,86.1353 72.2766,78.14 55.7549,68.7643C 41.3441,60.5865 26.9979,51.4404
15.7173,39.304C 8.81592,31.879 2.99496,22.9538 0,13.2693C 2.22131,15.1681 4.72168,16.774 7.3566,18.0377'/>

<Path Canvas.Left='182.169' Canvas.Top='321.751' Fill='#24FFFFFF' Data='F1 M


5.86661,6.19275C 8.86157,15.8773 14.6825,24.8024 21.5839,32.2274C 32.8645,44.3639 47.2108,53.5099
61.6215,61.6877C 78.1432,71.0635 95.5235,79.0587 113.382,85.5342C 126.568,90.315 140.094,94.527
153.951,96.6929C 187.9,101.48 222.813,101.813 256.802,97.3246C 282.005,93.9961 307.325,87.7822
330.259,76.8127C 338.904,72.6779 347.096,67.5938 355.015,62.1963C 367.206,53.8857 379.126,44.6552
388.543,33.2958C 395.731,24.6251 401.508,14.6152 405.564,4.10828L 406.692,0.598022L 406.581,4.4353L
406.557,7.14771L 406.577,8.34235C 401.398,26.1171 393.369,43.6141 381.744,58.0235C 373.124,68.7085
362.118,77.6587 350.259,84.5754C 328.304,97.3807 303.414,105.423 278.456,110.233C 236.967,118.229
193.571,117.931 151.711,112.178C 131.566,109.139 111.874,102.823 93.0394,95.0553C 70.988,85.9613
49.3723,73.9714 32.1415,57.4769C 22.0566,47.823 13.1161,36.4785 7.19189,23.837C 3.6701,16.3218 1.65955,8.13184
0,0C 1.88907,2.12524 3.74274,4.30212 5.86661,6.19275'/>
<Path Canvas.Left='176.506' Canvas.Top='315.381' Fill='#15FFFFFF' Data='F1 M
5.66287,6.37067C 7.32242,14.5025 9.33298,22.6925 12.8548,30.2076C 18.7789,42.8491 27.7195,54.1937
37.8044,63.8476C 55.0351,80.342 76.6509,92.332 98.7023,101.426C 117.537,109.193 137.229,115.51
157.374,118.548C 199.234,124.302 242.629,124.6 284.119,116.604C 309.077,111.794 333.967,103.751
355.922,90.9461C 367.781,84.0294 378.787,75.0792 387.407,64.3942C 399.032,49.9848 407.06,32.4877
412.24,14.713C 412.385,17.5458 412.696,20.376 413.187,23.1697C 409.798,41.3376 404.78,59.8322 395.118,75.587C
390.397,83.2855 384.844,90.8654 377.59,96.2452C 355.66,112.511 329.096,122.632 302.585,129.166C
254.837,140.934 203.875,140.574 155.135,134.033C 133.68,130.886 112.559,124.688 92.5061,116.435C
73.5291,108.626 54.7781,98.5003 40.0512,84.2094C 26.3458,70.9098 15.2178,54.2681 8.48596,36.3964C
4.09467,24.7385 2.491,12.2059 0,0L 5.66287,6.37067'/>

<Path Canvas.Left='170.843' Canvas.Top='309.01' Fill='#0BFFFFFF' Data='F1 M


5.66284,6.37073C 8.15384,18.5767 9.75751,31.1093 14.1488,42.7672C 20.8807,60.6389 32.0087,77.2805
45.714,90.5801C 60.441,104.871 79.1919,114.997 98.1689,122.806C 118.222,131.058 139.342,137.257
160.797,140.404C 209.538,146.945 260.5,147.304 308.248,135.537C 334.759,129.003 361.323,118.882
383.253,102.616C 390.507,97.2361 396.06,89.6562 400.781,81.9578C 410.443,66.2029 415.46,47.7084
418.85,29.5404C 419.549,32.8535 420.436,36.1308 421.478,39.3528C 420.262,57.0321 417.463,75.1791
410.041,91.2712C 405.836,100.388 400.602,109.758 392.608,115.833C 385.66,121.112 378.026,125.468
370.325,129.572C 352.056,139.307 332.248,146.351 312.146,151.293C 282.887,158.486 252.405,161.341
222.277,160.995C 200.97,160.75 179.684,158.661 158.558,155.889C 134.603,152.452 110.854,145.964
88.6201,136.408C 70.9781,128.825 53.4948,118.957 40.3623,104.947C 25.9446,89.5665 15.5068,69.9648
9.44882,49.7724C 7.35947,42.8082 5.78204,35.6675 4.77164,28.4672C 4.28711,25.0143 4.34622,21.4872
3.68643,18.0635C 2.52356,12.0293 1.22882,6.02118 0,0L 5.66284,6.37073'/>

<Path Canvas.Left='196.983' Canvas.Top='381.943' Fill='#2EFFFFFF' Data='F1 M


3.52792,396.634L 7.57332,400.448L 12.292,404.292L 17.6377,408.133L 23.5641,411.94L 30.0251,415.684L
36.9751,419.337L 44.3686,422.872L 52.1605,426.263L 60.3058,429.484L 68.7595,432.508L 77.4768,435.31L
86.413,437.863L 95.5233,440.143L 104.763,442.123L 114.087,443.78L 123.451,445.086L 121.269,447.016L
121.274,445.128L 121.279,442.775L 121.285,439.973L 121.292,436.74L 121.298,433.09L 121.305,429.04L
121.312,424.604L 121.32,419.8L 121.328,414.642L 121.336,409.147L 121.344,403.331L 121.352,397.208L
121.361,390.796L 121.37,384.109L 121.379,377.164L 121.388,369.976L 121.398,362.562L 121.407,354.936L
121.417,347.115L 121.427,339.114L 121.437,330.95L 121.446,322.638L 121.456,314.194L 121.467,305.633L
121.477,296.972L 121.487,288.227L 121.497,279.412L 121.507,270.544L 121.517,261.639L 121.527,252.712L
121.537,243.78L 121.547,234.857L 121.557,225.961L 121.567,217.106L 121.577,208.308L 121.586,199.584L
121.596,190.948L 121.605,182.418L 121.614,174.008L 121.623,165.734L 121.632,157.612L 121.64,149.659L
121.649,141.889L 121.657,134.319L 121.665,126.964L 121.672,119.84L 121.679,112.963L 121.686,106.349L
121.693,100.013L 121.699,93.9718L 121.705,88.2406L 121.711,82.8352L 121.716,77.7715L 121.721,73.0652L
121.726,68.7322L 121.73,64.7883L 121.734,61.2493L 121.737,58.1308L 121.74,55.4488L 121.742,53.219L
121.744,51.4572L 121.745,50.1793L 121.746,49.4009L 121.746,49.1378L 123.409,51.0686L 114.529,49.6424L
105.668,48.0035L 96.8576,46.1534L 88.1272,44.0935L 79.5075,41.8252L 71.0287,39.3498L 62.7212,36.6685L
54.6152,33.7824L 46.7411,30.6926L 39.1289,27.4L 31.809,23.9054L 24.8114,20.2091L 18.1666,16.3114L
11.9048,12.2123L 6.05664,7.91119L 0.65303,3.40747L 3.89999,1.95038L 4.08195,397.995L 3.52792,396.634L
0.735992,399.357L 0.611008,399.216L 0.500351,399.064L 0.404999,398.902L 0.325943,398.731L 0.263184,398.553L
0.218048,398.371L 0.190857,398.184L 0.181961,397.996L 0,1.95221L 0.0186005,1.67273L 0.078064,1.39899L
0.176697,1.13684L 0.312775,0.892029L 0.480316,0.667542L 0.679016,0.470154L 0.904312,0.303711L 1.15163,0.17218L
1.41428,0.0748901L 1.68837,0.0172119L 1.96794,0L 2.24701,0.0240479L 2.52037,0.085144L 2.78178,0.18573L
3.0258,0.323242L 3.24696,0.495117L 8.45868,4.83868L 14.1264,9.00684L 20.2195,12.9955L 26.7072,16.8009L
33.5584,20.4198L 40.7419,23.8492L 48.2263,27.0865L 55.9806,30.1292L 63.9733,32.975L 72.1734,35.6215L
80.5496,38.067L 89.0708,40.3093L 97.7058,42.3467L 106.423,44.1773L 115.193,45.7993L 123.983,47.2109L
124.321,47.2891L 124.639,47.4282L 124.927,47.6227L 125.173,47.867L 125.378,48.1472L 125.528,48.4604L
125.619,48.7957L 125.646,49.1418L 125.646,49.4049L 125.645,50.1833L 125.644,51.4612L 125.642,53.223L
125.64,55.4528L 125.637,58.1348L 125.634,61.2533L 125.63,64.7924L 125.626,68.7363L 125.621,73.0693L
125.616,77.7755L 125.611,82.8392L 125.605,88.2446L 125.599,93.976L 125.593,100.017L 125.586,106.353L
125.579,112.967L 125.572,119.844L 125.565,126.968L 125.557,134.323L 125.549,141.893L 125.54,149.663L
125.532,157.617L 125.523,165.738L 125.514,174.012L 125.505,182.422L 125.496,190.952L 125.486,199.588L
125.477,208.312L 125.467,217.11L 125.457,225.965L 125.447,234.862L 125.437,243.784L 125.427,252.717L
125.417,261.643L 125.407,270.549L 125.397,279.416L 125.387,288.231L 125.377,296.977L 125.367,305.638L
125.357,314.199L 125.346,322.643L 125.337,330.955L 125.327,339.119L 125.317,347.12L 125.307,354.941L
125.298,362.567L 125.288,369.981L 125.279,377.169L 125.27,384.114L 125.261,390.801L 125.252,397.214L
125.244,403.336L 125.236,409.153L 125.228,414.648L 125.22,419.806L 125.212,424.61L 125.205,429.046L
125.198,433.097L 125.192,436.747L 125.185,439.981L 125.179,442.783L 125.174,445.137L 125.169,447.028L
125.158,447.233L 125.125,447.436L 125.07,447.635L 124.995,447.826L 124.901,448.009L 124.788,448.18L
124.657,448.339L 124.511,448.483L 124.35,448.611L 124.177,448.721L 123.992,448.813L 123.799,448.884L
123.6,448.935L 123.397,448.965L 123.192,448.973L 122.987,448.958L 113.475,447.631L 104.012,445.95L
94.6403,443.942L 85.4032,441.63L 76.3439,439.041L 67.5058,436.201L 58.932,433.134L 50.6656,429.866L
42.7497,426.42L 35.2274,422.823L 28.1414,419.098L 21.5342,415.27L 15.4483,411.36L 9.92546,407.392L
5.00749,403.385L 0.735992,399.357L 3.52792,396.634'/>

<Path Canvas.Left='205.043' Canvas.Top='403.893' Fill='#1FFFFFFF' Data='F1 M


<Path Canvas.Left='205.043' Canvas.Top='403.893' Fill='#1FFFFFFF' Data='F1 M
97.6511,42.6417L 94.6949,42.1309L 95.4297,37.1852L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1094L 89.5173,36.1638L 92.4735,36.6745L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5456L 85.7349,40.451M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1884L
74.55,32.8367L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3864L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0875L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0955,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0955,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4134L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7298L 33.8514,24.4134M
28.252,21.8278L 25.5711,20.4814L 27.639,15.929L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.1349L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.1349M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1523L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='205.043' Canvas.Top='418.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.1309L 95.4297,37.1852L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1094L 89.5173,36.1638L 92.4735,36.6745L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5456L 85.7349,40.451M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1884L
74.55,32.8367L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3864L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0875L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0955,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0955,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4134L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7298L 33.8514,24.4134M
28.252,21.8278L 25.5711,20.4814L 27.639,15.929L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.1349L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.1349M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1523L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='203.295' Canvas.Top='432.9' Fill='#1FFFFFFF' Data='F1 M


93.4866,42.6132L 90.1151,42.0308L 87.4827,41.444L 88.4508,36.5386L 91.0832,37.1254L 94.2214,37.6675L
93.4866,42.6132M 81.6264,40.1387L 75.7702,38.8333L 76.7383,33.9279L 82.5945,35.2333L 81.6264,40.1387M
69.8606,37.2309L 64.079,35.627L 65.2887,30.7755L 71.0703,32.3795L 69.8606,37.2309M 58.2075,33.8603L
52.5255,31.933L 53.993,27.1532L 59.6751,29.0805L 58.2075,33.8603M 46.8434,30.0057L 46.3664,29.8438L
41.1466,27.6926L 42.8971,23.009L 48.1168,25.1602L 48.311,25.2259L 46.8434,30.0057M 35.5992,25.4064L
33.0824,24.369L 29.9998,22.8209L 32.0677,18.2685L 35.1503,19.8167L 37.3497,20.7228L 35.5992,25.4064M
24.6381,20.128L 20.7895,18.1948L 19.1776,17.1961L 21.6081,12.8266L 23.22,13.8253L 26.706,15.5756L
24.6381,20.128M 14.0772,14.0361L 9.69283,11.3192L 8.83592,10.6487L 11.6841,6.53918L 12.541,7.20966L
16.5076,9.66663L 14.0772,14.0361M 4.11055,6.95123L 0,3.73376L 3.32556,0L 6.95869,2.84174L 4.11055,6.95123M
105.311,44.6561L 99.399,43.6347L 100.134,38.689L 106.046,39.7104L 105.311,44.6561'/>

<Path Canvas.Left='205.043' Canvas.Top='448.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.1309L 95.4297,37.1852L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1094L 89.5173,36.1638L 92.4735,36.6745L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5456L 85.7349,40.451M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1884L
74.55,32.8367L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3864L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0875L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0955,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0955,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4134L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7298L 33.8514,24.4134M
28.252,21.8278L 25.5711,20.4814L 27.639,15.929L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.1349L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.1349M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1523L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>
<Path Canvas.Left='205.043' Canvas.Top='463.893' Fill='#1FFFFFFF' Data='F1 M
97.6511,42.6417L 94.6949,42.1309L 95.4297,37.1852L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1094L 89.5173,36.1638L 92.4735,36.6745L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5456L 85.7349,40.451M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1884L
74.55,32.8367L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3864L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0875L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0955,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0955,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4134L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7298L 33.8514,24.4134M
28.252,21.8278L 25.5711,20.4814L 27.639,15.929L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.1349L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.1349M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1523L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='203.295' Canvas.Top='477.9' Fill='#1FFFFFFF' Data='F1 M


97.4282,43.2942L 93.4866,42.6132L 94.2214,37.6675L 98.163,38.3484L 97.4282,43.2942M 89.4348,41.879L
85.5307,41.0088L 86.4987,36.1034L 90.4029,36.9736L 89.4348,41.879M 81.6264,40.1385L 77.7223,39.2683L
78.6904,34.3629L 82.5945,35.2332L 81.6264,40.1385M 73.715,38.3002L 69.8606,37.2308L 71.0703,32.3794L
74.9247,33.4487L 73.715,38.3002M 66.0062,36.1616L 62.1518,35.0922L 63.3614,30.2408L 67.2159,31.3101L
66.0062,36.1616M 58.2075,33.8602L 54.4194,32.5753L 55.887,27.7955L 59.6751,29.0804L 58.2075,33.8602M
50.6314,31.2905L 46.8434,30.0056L 48.311,25.2258L 52.099,26.5107L 50.6314,31.2905M 42.9958,28.4546L
39.2975,26.9305L 41.0479,22.2469L 44.7462,23.771L 42.9958,28.4546M 35.5993,25.4064L 33.0824,24.369L
31.7871,23.7184L 33.855,19.1661L 35.1503,19.8166L 37.3497,20.7228L 35.5993,25.4064M 28.2126,21.9232L
24.6381,20.128L 26.706,15.5756L 30.2805,17.3708L 28.2126,21.9232M 21.0636,18.3327L 20.7895,18.1947L
17.4775,16.1427L 19.9079,11.7732L 23.22,13.8252L 23.1315,13.7803L 21.0636,18.3327M 14.0772,14.0361L
10.6769,11.9294L 13.1074,7.55988L 16.5077,9.66656L 14.0772,14.0361M 7.2608,9.41614L 4.11055,6.95117L
6.95869,2.84167L 10.1089,5.30664L 7.2608,9.41614M 0.960312,4.48627L 0,3.73376L 3.32556,0L 3.80846,0.37677L
0.960312,4.48627M 105.311,44.6561L 101.37,43.9752L 102.105,39.0294L 106.046,39.7104L 105.311,44.6561'/>

<Path Canvas.Left='205.043' Canvas.Top='493.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1852L 98.3859,37.6959L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1095L 89.5173,36.1638L 92.4735,36.6744L 91.7387,41.6202M 85.7349,40.4509L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5455L 85.7349,40.4509M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8402L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1885L
74.55,32.8367L 74.9904,32.9348L 74.0223,37.8402M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8318L 60.65,28.9804L 63.5408,29.7824L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0956,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0956,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8278L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.7791,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1524L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='205.043' Canvas.Top='508.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1853L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1096L 89.5173,36.1638L 92.4735,36.6746L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.7029,35.5457L 85.7349,40.451M 79.8786,39.1456L 76.9504,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0035,37.0399L 72.2132,32.1885L
74.55,32.8368L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2451,26.1602L 50.7776,30.9399M 45.0955,29.0127L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2329L 45.0955,29.0127M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8279L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8279M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.6231L
17.31,10.2536L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09363L
14.7598,8.67358L 12.3293,13.0431M 7.08804,9.65564L 4.72537,7.80695L 7.57352,3.69745L 9.93619,5.54614L
14.7598,8.67358L 12.3293,13.0431M 7.08804,9.65564L 4.72537,7.80695L 7.57352,3.69745L 9.93619,5.54614L
7.08804,9.65564M 2.36269,5.95825L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95825M 103.564,43.6632L
100.607,43.1525L 101.342,38.2067L 104.298,38.7175L 103.564,43.6632'/>

<Path Canvas.Left='205.043' Canvas.Top='523.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1853L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1096L 89.5173,36.1638L 92.4735,36.6746L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.7029,35.5457L 85.7349,40.451M 79.8786,39.1456L 76.9504,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0035,37.0399L 72.2132,32.1885L
74.55,32.8368L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2451,26.1602L 50.7776,30.9399M 45.0955,29.0127L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2329L 45.0955,29.0127M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8279L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8279M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.6231L
17.31,10.2536L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09363L
14.7598,8.67358L 12.3293,13.0431M 7.08804,9.65564L 4.72536,7.80695L 7.5735,3.69745L 9.93619,5.54614L
7.08804,9.65564M 2.36267,5.95825L 0,4.1095L 2.84814,0L 5.21082,1.84875L 2.36267,5.95825M 103.564,43.6632L
100.607,43.1525L 101.342,38.2067L 104.298,38.7175L 103.564,43.6632'/>

<Path Canvas.Left='205.043' Canvas.Top='538.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1852L 98.3859,37.6959L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1095L 89.5173,36.1638L 92.4735,36.6744L 91.7387,41.6202M 85.7349,40.4509L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5455L 85.7349,40.4509M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8402L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1885L
74.55,32.8367L 74.9904,32.9348L 74.0223,37.8402M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8318L 60.65,28.9804L 63.5408,29.7824L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0956,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0956,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8278L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.7791,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1524L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='205.043' Canvas.Top='553.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1852L 98.3859,37.6959L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1095L 89.5173,36.1638L 92.4735,36.6744L 91.7387,41.6202M 85.7349,40.4509L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5455L 85.7349,40.4509M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8402L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1885L
74.55,32.8367L 74.9904,32.9348L 74.0223,37.8402M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8318L 60.65,28.9804L 63.5408,29.7824L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0956,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0956,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8278L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.7791,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1524L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='205.043' Canvas.Top='583.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1852L 98.3859,37.6959L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1095L 89.5173,36.1638L 92.4735,36.6744L 91.7387,41.6202M 85.7349,40.4509L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5455L 85.7349,40.4509M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8402L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1885L
74.55,32.8367L 74.9904,32.9348L 74.0223,37.8402M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8318L 60.65,28.9804L 63.5408,29.7824L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0956,29.0126L
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0956,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0956,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8278L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.7791,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1524L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='203.295' Canvas.Top='597.9' Fill='#1FFFFFFF' Data='F1 M


95.4574,42.9537L 90.5303,42.1025L 91.2652,37.1567L 96.1922,38.0079L 95.4574,42.9537M 85.5307,41.0088L
80.6504,39.921L 81.6185,35.0156L 86.4987,36.1034L 85.5307,41.0088M 75.7702,38.8333L 75.0882,38.6812L
70.8242,37.4982L 72.0339,32.6467L 76.2978,33.8297L 76.7383,33.9279L 75.7702,38.8333M 66.0062,36.1615L
61.1882,34.8248L 62.3978,29.9734L 67.2159,31.3101L 66.0062,36.1615M 56.3135,33.2178L 51.5784,31.6117L
53.046,26.8319L 57.7811,28.438L 56.3135,33.2178M 46.8434,30.0056L 46.3664,29.8437L 42.0712,28.0736L
43.8216,23.39L 48.1168,25.1601L 48.311,25.2258L 46.8434,30.0056M 37.4484,26.1685L 33.0824,24.369L
32.6807,24.1672L 34.7486,19.6149L 35.1503,19.8166L 39.1988,21.4849L 37.4484,26.1685M 28.2126,21.9232L
23.7444,19.6791L 25.8123,15.1268L 30.2805,17.3708L 28.2126,21.9232M 19.1776,17.196L 14.9272,14.5627L
17.3577,10.1932L 21.6081,12.8265L 19.1776,17.196M 10.6769,11.9294L 9.69283,11.3191L 6.47324,8.79993L
9.32138,4.69043L 12.541,7.20959L 13.1074,7.55988L 10.6769,11.9294M 2.53543,5.71875L 0,3.73376L 3.32556,0L
5.38358,1.60925L 2.53543,5.71875M 105.311,44.6561L 100.384,43.8049L 101.119,38.8591L 106.046,39.7104L
105.311,44.6561'/>

<Path Canvas.Left='205.043' Canvas.Top='613.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1852L 98.3859,37.6959L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1095L 89.5173,36.1638L 92.4735,36.6744L 91.7387,41.6202M 85.7349,40.4509L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5455L 85.7349,40.4509M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8402L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1885L
74.55,32.8367L 74.9904,32.9348L 74.0223,37.8402M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8318L 60.65,28.9804L 63.5408,29.7824L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0956,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0956,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8278L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.7791,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1524L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='205.043' Canvas.Top='628.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1852L 98.3859,37.6959L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1095L 89.5173,36.1638L 92.4735,36.6744L 91.7387,41.6202M 85.7349,40.4509L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5455L 85.7349,40.4509M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8402L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1885L
74.55,32.8367L 74.9904,32.9348L 74.0223,37.8402M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8318L 60.65,28.9804L 63.5408,29.7824L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0956,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0956,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8278L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.7791,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1524L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='203.295' Canvas.Top='642.9' Fill='#1FFFFFFF' Data='F1 M


93.4866,42.6132L 90.1151,42.0307L 87.4827,41.444L 88.4508,36.5386L 91.0832,37.1253L 94.2214,37.6675L
93.4866,42.6132M 81.6265,40.1385L 75.7702,38.8332L 76.7383,33.9278L 82.5946,35.2332L 81.6265,40.1385M
69.8606,37.2308L 64.079,35.6268L 65.2887,30.7754L 71.0703,32.3794L 69.8606,37.2308M 58.2075,33.8601L
52.5255,31.9329L 53.993,27.1531L 59.6751,29.0803L 58.2075,33.8601M 46.8434,30.0056L 46.3664,29.8436L
41.1466,27.6925L 42.8971,23.0089L 48.1168,25.16L 48.311,25.2258L 46.8434,30.0056M 35.5993,25.4064L
33.0824,24.3689L 29.9998,22.8208L 32.0677,18.2684L 35.1503,19.8165L 37.3497,20.7228L 35.5993,25.4064M
33.0824,24.3689L 29.9998,22.8208L 32.0677,18.2684L 35.1503,19.8165L 37.3497,20.7228L 35.5993,25.4064M
24.6381,20.1279L 20.7895,18.1947L 19.1776,17.196L 21.6081,12.8265L 23.22,13.8252L 26.706,15.5756L
24.6381,20.1279M 14.0772,14.036L 9.69283,11.3191L 8.83592,10.6486L 11.6841,6.53906L 12.541,7.20959L
16.5077,9.6665L 14.0772,14.036M 4.11055,6.95117L 0,3.73376L 3.32556,0L 6.95869,2.84167L 4.11055,6.95117M
105.311,44.6561L 99.399,43.6346L 100.134,38.689L 106.046,39.7104L 105.311,44.6561'/>

<Path Canvas.Left='205.043' Canvas.Top='658.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1853L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1096L 89.5173,36.1638L 92.4735,36.6746L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.7029,35.5457L 85.7349,40.451M 79.8786,39.1456L 76.9504,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0035,37.0399L 72.2132,32.1885L
74.55,32.8368L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2451,26.1602L 50.7776,30.9399M 45.0955,29.0127L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2329L 45.0955,29.0127M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8279L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8279M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.6231L
17.31,10.2536L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09363L
14.7598,8.67358L 12.3293,13.0431M 7.08804,9.65564L 4.72536,7.80695L 7.5735,3.69745L 9.93619,5.54614L
7.08804,9.65564M 2.36267,5.95825L 0,4.1095L 2.84814,0L 5.21082,1.84875L 2.36267,5.95825M 103.564,43.6632L
100.607,43.1525L 101.342,38.2067L 104.298,38.7175L 103.564,43.6632'/>

<Path Canvas.Left='205.043' Canvas.Top='673.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1853L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1096L 89.5173,36.1638L 92.4735,36.6746L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.7029,35.5457L 85.7349,40.451M 79.8786,39.1456L 76.9504,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0035,37.0399L 72.2132,32.1885L
74.55,32.8368L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2451,26.1602L 50.7776,30.9399M 45.0955,29.0127L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2329L 45.0955,29.0127M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8279L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8279M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.6231L
17.31,10.2536L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09363L
14.7598,8.67358L 12.3293,13.0431M 7.08804,9.65564L 4.72536,7.80695L 7.5735,3.69745L 9.93619,5.54614L
7.08804,9.65564M 2.36267,5.95825L 0,4.1095L 2.84814,0L 5.21082,1.84875L 2.36267,5.95825M 103.564,43.6632L
100.607,43.1525L 101.342,38.2067L 104.298,38.7175L 103.564,43.6632'/>

<Path Canvas.Left='205.043' Canvas.Top='703.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1853L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1096L 89.5173,36.1638L 92.4735,36.6746L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.7029,35.5457L 85.7349,40.451M 79.8786,39.1456L 76.9504,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0035,37.0399L 72.2132,32.1885L
74.55,32.8368L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2451,26.1602L 50.7776,30.9399M 45.0955,29.0127L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2329L 45.0955,29.0127M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8279L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8279M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.6231L
17.31,10.2536L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09363L
14.7598,8.67358L 12.3293,13.0431M 7.08804,9.65564L 4.72536,7.80695L 7.5735,3.69745L 9.93619,5.54614L
7.08804,9.65564M 2.36267,5.95825L 0,4.1095L 2.84814,0L 5.21082,1.84875L 2.36267,5.95825M 103.564,43.6632L
100.607,43.1525L 101.342,38.2067L 104.298,38.7175L 103.564,43.6632'/>

<Path Canvas.Left='205.043' Canvas.Top='718.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.131L 95.4297,37.1853L 98.3859,37.696L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1096L 89.5173,36.1638L 92.4735,36.6746L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.7029,35.5457L 85.7349,40.451M 79.8786,39.1456L 76.9504,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8403L 73.3403,37.6882L 71.0035,37.0399L 72.2132,32.1885L
74.55,32.8368L 74.9904,32.9349L 74.0223,37.8403M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5845L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
69.3224,31.3865L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8319L 60.65,28.9805L 63.5408,29.7825L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2451,26.1602L 50.7776,30.9399M 45.0955,29.0127L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2329L 45.0955,29.0127M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8279L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8279M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.6231L
17.31,10.2536L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.77908,11.4631L 12.2096,7.09363L
14.7598,8.67358L 12.3293,13.0431M 7.08804,9.65564L 4.72536,7.80695L 7.5735,3.69745L 9.93619,5.54614L
7.08804,9.65564M 2.36267,5.95825L 0,4.1095L 2.84814,0L 5.21082,1.84875L 2.36267,5.95825M 103.564,43.6632L
100.607,43.1525L 101.342,38.2067L 104.298,38.7175L 103.564,43.6632'/>

<Path Canvas.Left='205.043' Canvas.Top='733.893' Fill='#1FFFFFFF' Data='F1 M


97.6511,42.6417L 94.6949,42.1309L 95.4297,37.1852L 98.3859,37.6959L 97.6511,42.6417M 91.7387,41.6202L
88.7825,41.1095L 89.5173,36.1638L 92.4735,36.6745L 91.7387,41.6202M 85.7349,40.451L 82.8067,39.7983L
83.7748,34.8929L 86.703,35.5456L 85.7349,40.451M 79.8786,39.1456L 76.9505,38.4929L 77.9185,33.5875L
80.8467,34.2402L 79.8786,39.1456M 74.0223,37.8402L 73.3403,37.6882L 71.0036,37.0399L 72.2132,32.1884L
74.55,32.8367L 74.9904,32.9348L 74.0223,37.8402M 68.1127,36.2379L 65.2219,35.4359L 66.4316,30.5844L
69.3224,31.3864L 68.1127,36.2379M 62.3311,34.6339L 59.4403,33.8318L 60.65,28.9804L 63.5408,29.7824L
62.3311,34.6339M 56.4596,32.8672L 53.6186,31.9036L 55.0862,27.1238L 57.9272,28.0874L 56.4596,32.8672M
50.7776,30.9399L 47.9366,29.9763L 49.4041,25.1965L 52.2452,26.1602L 50.7776,30.9399M 45.0955,29.0126L
44.6185,28.8507L 42.1725,27.8427L 43.9229,23.1591L 46.3689,24.1671L 46.5631,24.2328L 45.0955,29.0126M
39.3988,26.6996L 36.6251,25.5565L 38.3755,20.8729L 41.1492,22.016L 39.3988,26.6996M 33.8514,24.4135L
31.3345,23.376L 30.9329,23.1743L 33.0008,18.6219L 33.4024,18.8236L 35.6018,19.7299L 33.8514,24.4135M
28.252,21.8278L 25.5711,20.4814L 27.639,15.9291L 30.3199,17.2755L 28.252,21.8278M 22.8902,19.135L
20.2093,17.7886L 22.2772,13.2362L 24.9581,14.5826L 22.8902,19.135M 17.4297,16.2031L 14.8795,14.623L
17.31,10.2535L 19.8602,11.8336L 17.4297,16.2031M 12.3293,13.0431L 9.7791,11.4631L 12.2096,7.09357L
14.7598,8.67358L 12.3293,13.0431M 7.08806,9.65564L 4.72537,7.80688L 7.57352,3.69739L 9.9362,5.54614L
7.08806,9.65564M 2.36269,5.95819L 0,4.1095L 2.84814,0L 5.21083,1.84869L 2.36269,5.95819M 103.564,43.6631L
100.607,43.1524L 101.342,38.2067L 104.298,38.7174L 103.564,43.6631'/>

<Path Canvas.Left='205.831' Canvas.Top='749.509' Fill='#1FFFFFFF' Data='F1 M


82.9952,39.3995L 73.2348,37.2239L 74.2028,32.3185L 83.9633,34.4941L 82.9952,39.3995M 63.4708,34.5522L
57.9013,33.0071L 53.778,31.6085L 55.2456,26.8287L 59.3689,28.2273L 64.6804,29.7008L 63.4708,34.5522M
44.308,28.3964L 43.8309,28.2344L 34.9129,24.5592L 36.6634,19.8756L 45.5814,23.5508L 45.7755,23.6166L
44.308,28.3964M 25.6772,20.3139L 18.2541,16.5854L 16.6422,15.5868L 19.0727,11.2173L 20.6846,12.2159L
27.7451,15.7616L 25.6772,20.3139M 8.14145,10.3201L 7.15739,9.70984L 0,4.1095L 2.84814,0L 10.0055,5.60034L
10.5719,5.95062L 8.14145,10.3201M 102.776,43.0469L 92.922,41.3444L 93.6568,36.3987L 103.511,38.1011L
102.776,43.0469'/>

<Path Canvas.Left='525.131' Canvas.Top='356.247' Fill='#14FFFFFF' Data='F1 M


2.75418,0.246277C 3.07999,0.572083 3.2717,1.19574 3.7316,1.22369C 4.91678,1.29565 6.15451,0 7.22311,0.5177C
7.97495,0.881958 7.5488,2.18848 7.42984,3.01538C 7.25272,4.24615 6.58536,5.36499 6.34995,6.58594C
6.18716,7.43024 5.97238,8.34753 6.24429,9.16327C 6.44193,9.7561 7.16757,10.0056 7.62991,10.426C
9.02481,11.6945 10.3407,13.0496 11.6277,14.4274C 12.9196,15.8104 14.2537,17.2031 15.1927,18.8463C
15.5079,19.3978 15.519,20.1581 16.0008,20.572C 16.608,21.0935 17.5049,21.1246 18.2329,21.4573C 18.9304,21.7759
19.697,22.0154 20.2715,22.5233C 20.7599,22.955 20.9699,23.6241 21.3117,24.1791C 21.3758,24.2831 21.43,24.393
21.4892,24.4999L 16.1678,27.9468C 16.5197,27.4101 17.2021,26.9782 17.2235,26.3368C 17.2877,24.418
14.331,23.8015 13.0244,22.3949C 12.6107,21.9496 12.4883,21.3023 12.1766,20.7805C 11.2444,19.2194
10.0575,17.8198 8.87766,16.4363C 7.70175,15.0573 6.49258,13.7041 5.21957,12.4143C 4.79697,11.9861
4.21536,11.6723 3.94797,11.1334C 3.63736,10.5073 3.59085,9.77094 3.56149,9.07269C 3.52438,8.18878
3.82681,7.3067 3.75021,6.42529C 3.69016,5.7345 3.73947,4.80902 3.15811,4.43109C 2.43918,3.96381
1.42636,4.54138 0.586456,4.36884C 0.315643,4.31323 0.195526,3.97791 3.05176e-005,3.78241L 2.75418,0.246277'/>

<Path Canvas.Left='522.377' Canvas.Top='360.029' Fill='#27FFFFFF' Data='F1 M


2.75418,0C 2.94968,0.195496 3.06979,0.530823 3.34061,0.586426C 4.18051,0.758972 5.19333,0.181396
5.91226,0.648682C 6.49362,1.02661 6.44431,1.95209 6.50436,2.64288C 6.58096,3.52429 6.27853,4.40637
6.31564,5.29028C 6.345,5.98853 6.39151,6.72491 6.70212,7.35095C 6.96951,7.88989 7.55112,8.20367
7.97372,8.6319C 9.24673,9.92169 10.4559,11.2749 11.6318,12.6539C 12.8116,14.0374 13.9985,15.437
14.9308,16.998C 15.2424,17.5199 15.3648,18.1672 15.7785,18.6125C 16.2381,19.1072 16.9209,19.3341
17.4682,19.7296C 18.0054,20.1179 18.5888,20.4662 19.0291,20.9618C 19.4395,21.4237 19.9983,21.9368
19.9777,22.5544C 19.9563,23.1958 19.2739,23.6277 18.922,24.1644L 14.894,26.8577C 15.2258,26.1425
15.8598,25.4999 15.8896,24.712C 15.9116,24.1281 15.3553,23.6699 15.0325,23.1827C 14.7068,22.6912
14.321,22.2421 13.9494,21.7843C 12.8466,20.4259 11.9428,18.9174 10.9505,17.4763C 8.97372,14.6056
6.43539,12.1548 4.40585,9.32104C 3.35715,7.85675 3.19742,5.75403 1.8472,4.56201C 1.38522,4.15417
0.734222,4.03076 0.195465,3.73157C 0.114899,3.68683 0.065155,3.60126 -3.05176e-005,3.53607L 2.75418,0'/>

<Path Canvas.Left='519.57' Canvas.Top='363.565' Fill='#44FFFFFF' Data='F1 M 2.80722,0C


2.87241,0.0651855 2.92215,0.150757 3.00272,0.195496C 3.54147,0.49469 4.19247,0.618103 4.65445,1.02594C
2.87241,0.0651855 2.92215,0.150757 3.00272,0.195496C 3.54147,0.49469 4.19247,0.618103 4.65445,1.02594C
6.00467,2.21796 6.1644,4.32068 7.2131,5.78497C 9.24265,8.61871 11.781,11.0695 13.7578,13.9402C 14.7501,15.3813
15.6538,16.8898 16.7566,18.2482C 17.1283,18.706 17.5141,19.1552 17.8398,19.6467C 18.1626,20.1338
18.7188,20.592 18.6968,21.176C 18.6671,21.9639 18.0331,22.6064 17.7012,23.3217L 17.4302,23.768L
17.5539,24.0153L 17.4302,23.768C 16.4897,23.6232 15.4496,23.7792 14.6087,23.3337C 14.1216,23.0756
14.0703,22.3699 13.8432,21.8676C 13.6127,21.3581 13.4386,20.8248 13.2378,20.3029C 13.0352,19.7763
12.8914,19.2236 12.6329,18.722C 11.6103,16.7375 10.2063,14.9733 8.939,13.1354C 7.66782,11.2921 6.52322,9.31506
4.91684,7.75507C 3.37424,6.25702 0.855133,5.55206 -3.05176e-005,3.57916L 1.43021,1.76801L 2.80722,0'/>

<Path Canvas.Left='515.809' Canvas.Top='367.144' Fill='#27FFFFFF' Data='F1 M


3.76035,0C 4.61551,1.9729 7.13461,2.67786 8.67722,4.1759C 10.2836,5.7359 11.4282,7.71289 12.6994,9.55627C
13.9667,11.3941 15.3706,13.1584 16.3933,15.1428C 16.6518,15.6444 16.7956,16.1971 16.9982,16.7238C
17.199,17.2457 17.3731,17.7789 17.6035,18.2885C 17.8307,18.7908 17.8819,19.4964 18.369,19.7545C 19.2099,20.2
20.2501,20.0441 21.1906,20.1888L 21.3142,20.4361L 21.5615,20.9307L 21.1906,20.1888C 18.8874,20.7633
16.6526,21.812 14.2809,21.9122C 13.7626,21.9341 13.7355,21.012 13.607,20.5094C 13.4636,19.9489 13.5104,19.3561
13.4794,18.7784C 13.447,18.1747 13.6078,17.5394 13.4168,16.9656C 13.248,16.4582 12.755,16.1246
12.4502,15.6852C 12.1462,15.2469 11.8709,14.7894 11.5921,14.3347C 10.184,12.0385 8.81058,9.71869
7.31052,7.48138C 7.00851,7.03088 6.8334,6.44507 6.38095,6.146C 5.84378,5.79089 5.15927,5.69263
4.51791,5.63525C 3.69199,5.5614 2.85947,5.82788 2.03329,5.75726C 1.43076,5.70575 0.694794,5.71796
0.284821,5.27344C -3.05176e-005,4.9646 0.383331,4.4389 0.432587,4.02167L 3.76035,0'/>

<Path Canvas.Left='511.844' Canvas.Top='371.166' Fill='#14FFFFFF' Data='F1 M


4.39819,0C 4.34894,0.417236 3.96558,0.942932 4.25043,1.25177C 4.6604,1.69629 5.39636,1.68408 5.9989,1.7356C
6.82507,1.80621 7.65759,1.53973 8.48352,1.61359C 9.12488,1.67096 9.80939,1.76923 10.3466,2.12433C
10.799,2.4234 10.9741,3.00922 11.2761,3.45972C 12.7762,5.69702 14.1496,8.01678 15.5577,10.313C 15.8365,10.7677
16.1118,11.2253 16.4158,11.6635C 16.7206,12.103 17.2136,12.4365 17.3824,12.944C 17.5734,13.5177 17.4126,14.153
17.445,14.7568C 17.476,15.3345 17.4292,15.9272 17.5726,16.4877C 17.7011,16.9903 17.7282,17.9124
18.2465,17.8905C 20.6182,17.7903 22.853,16.7416 25.1562,16.1672L 25.5271,16.909L 25.7744,17.4036L
25.1562,16.1672C 21.4902,17.4609 17.9555,19.2148 14.1583,20.0482C 13.6827,20.1526 13.6108,19.1943
13.576,18.7087C 13.53,18.0673 13.7936,17.4408 13.9261,16.8115C 14.0704,16.1265 14.5192,15.4577 14.406,14.7668C
14.3229,14.2594 13.704,14.0122 13.3997,13.5977C 12.4879,12.356 11.882,10.9158 11.1649,9.55237C 10.4349,8.16449
9.64392,6.80945 8.86578,5.448C 8.60437,4.99066 8.53503,4.30048 8.05023,4.09442C 7.3277,3.78735 6.46722,3.95874
5.69507,4.10034C 4.53644,4.31287 3.47583,4.922 2.31927,5.14551C 1.62091,5.28046 0.872131,5.35065
0.185425,5.16516C 0,5.11511 0.304443,4.79999 0.363953,4.61737L 4.39819,0'/>

<Path Canvas.Left='419.08' Canvas.Top='217.705' Fill='#14FFFFFF' Data='F1 M


0.590515,83.7698C 5.83813,82.1203 9.93555,77.8469 15.043,75.8042C 20.1963,73.7432 25.7425,72.8456
31.0615,71.2604C 39.698,68.6866 48.1964,65.6683 56.8027,62.9958C 65.4462,60.2567 74.0467,56.5234
81.1791,50.9252C 83.4284,49.1597 85.5476,47.2085 87.4597,45.0825C 88.729,43.6711 90.618,41.6075
89.804,39.8926C 89.698,40.4022 88.8833,39.3639 88.5464,38.9671C 87.6729,37.9382 87.3365,36.554
86.7395,35.3434C 85.065,31.9487 83.0493,28.6537 80.5009,25.8547C 78.505,23.6625 76.0999,21.8612
74.1509,19.6272C 68.2269,12.8372 62.4396,5.59387 54.9203,0.628052L 53.0362,0L 53.7899,0.251221L
54.9203,0.628052C 63.2656,5.01111 70.3335,11.4962 77.7734,17.2844C 83.0977,21.4266 88.3099,25.941
92.2818,31.3936C 94.0416,33.8094 96.3903,36.0718 97.0505,38.9868C 97.4528,41.3328 96.8824,43.9338
95.6978,45.9984C 93.5321,49.773 90.2233,52.8626 86.8071,55.5585C 78.6151,62.0235 68.7968,66.4924
58.8498,69.6487C 50.2921,72.3124 41.8533,75.3484 33.296,78.0131C 27.7748,79.7324 22.1152,80.9908
16.6106,82.7628C 11.0216,84.5619 5.78857,87.6407 0,88.6235L 0.590515,83.7698'/>

<Path Canvas.Left='418.385' Canvas.Top='217.956' Fill='#27FFFFFF' Data='F1 M


0.694763,88.3723C 6.48334,87.3895 11.7164,84.3107 17.3054,82.5115C 22.8099,80.7396 28.4695,79.4812
33.9908,77.7619C 42.5481,75.0972 50.9869,72.0612 59.5446,69.3975C 69.4915,66.2411 79.3099,61.7723
87.5019,55.3073C 90.918,52.6114 94.2269,49.5218 96.3926,45.7472C 97.5772,43.6826 98.1475,41.0816
97.7453,38.7355C 97.085,35.8206 94.7363,33.5582 92.9766,31.1424C 89.0046,25.6898 83.7925,21.1754
78.4681,17.0331C 71.0283,11.245 63.9604,4.75989 55.6151,0.376831L 54.4846,0L 55.2383,0.251221L
55.6151,0.376831C 67.0864,4.96521 78.236,10.67 88.3404,17.7795C 92.5117,20.7144 96.4564,24.0779
99.7584,27.965C 102.168,30.8019 104.437,34.1489 104.992,37.8297C 105.373,40.8909 104.949,44.1631
103.733,46.9982C 101.72,51.6913 98.1045,55.6844 94.2395,59.0219C 84.9497,67.0438 73.2895,72.3342
61.5916,76.0504C 47.3436,80.4966 33.3356,85.7814 18.873,89.4701C 12.6671,91.0529 6.39362,92.6982 0,93.0734L
0.694763,88.3723'/>

<Path Canvas.Left='417.603' Canvas.Top='218.208' Fill='#44FFFFFF' Data='F1 M


0.782104,92.8221C 7.17572,92.447 13.4492,90.8017 19.6551,89.2189C 34.1177,85.5302 48.1257,80.2454
62.3737,75.7992C 74.0716,72.0829 85.7318,66.7925 95.0216,58.7707C 98.8866,55.4332 102.502,51.4401
104.515,46.747C 105.731,43.9119 106.155,40.6397 105.774,37.5785C 105.219,33.8977 102.95,30.5507
100.541,27.7137C 97.2385,23.8267 93.2938,20.4631 89.1225,17.5283C 79.0181,10.4188 67.8685,4.71399
56.3972,0.12561L 56.0204,0L 56.3972,0.12561L 56.7786,0.237427C 70.2795,4.05139 84.1151,7.9101 96.1429,15.1316C
100.315,17.6367 104.414,20.5566 107.468,24.3451C 110.297,27.8535 112.435,32.2042 113.02,36.6727C
113.945,45.4348 109.253,54.9016 103.038,61.1472C 92.6685,71.5685 78.4308,77.9966 64.4207,82.452C
50.0014,86.9637 36.0461,93.2554 21.2227,96.1774C 14.2703,97.5478 7.08618,97.4095 0,97.4095L 0.397217,95.1256L
0.782104,92.8221'/>

<Path Canvas.Left='416.808' Canvas.Top='218.445' Fill='#27FFFFFF' Data='F1 M


0.794434,97.1721C 7.88062,97.1721 15.0648,97.3104 22.0172,95.9399C 36.8406,93.0179 50.7958,86.7263
65.2151,82.2146C 79.2252,77.7592 93.463,71.3311 103.833,60.9097C 110.047,54.6642 114.739,45.1973
113.815,36.4353C 113.23,31.9667 111.092,27.616 108.263,24.1077C 105.208,20.3192 101.11,17.3992
96.9374,14.8942C 84.9095,7.67267 71.074,3.81396 57.5731,0L 58.3711,0.1203C 66.7984,1.51056 75.4247,1.73279
83.7544,3.6217C 87.0415,4.36713 90.1757,5.68744 93.3145,6.91571C 97.2969,8.47412 101.3,10.0565 105.02,12.1658C
108.011,13.8617 110.912,15.8672 113.238,18.3997C 117.484,23.0233 120.302,29.2983 121.061,35.5295C
122.022,45.6175 117.496,56.5814 110.723,64.1184C 105.325,70.1237 98.4201,74.7673 91.3349,78.6393C
83.6843,82.8204 75.57,86.2231 67.2622,88.8675C 58.8499,91.5072 50.5952,94.6255 42.2709,97.5312C
36.1524,99.6669 29.9969,101.959 23.5848,102.898C 15.7968,104.039 7.87109,101.74 0,101.74L 0.794434,97.1721'/>

<Path Canvas.Left='416.014' Canvas.Top='217.438' Fill='#14FFFFFF' Data='F1 M


0.794434,102.747C 8.66553,102.747 16.5912,105.046 24.3792,103.906C 30.7914,102.967 36.9468,100.674
43.0654,98.5386C 51.3896,95.633 59.6443,92.5146 68.0566,89.8749C 76.3644,87.2306 84.4788,83.8278
92.1293,79.6468C 99.2145,75.7747 106.12,71.1312 111.517,65.1259C 118.291,57.5888 122.816,46.6249
121.856,36.5369C 121.096,30.3058 118.278,24.0308 114.032,19.4071C 111.707,16.8746 108.806,14.8691
105.815,13.1733C 102.095,11.064 98.0913,9.48157 94.1089,7.92316C 90.9702,6.69489 87.8359,5.37457
84.5488,4.62915C 76.2191,2.74023 67.5928,2.51801 59.1655,1.12775L 60.0179,1.09174C 68.7964,1.51111 77.631,0
86.3819,0.812744C 89.9247,1.14178 93.3309,2.36981 96.7445,3.37335C 101.683,4.82507 106.706,6.21393
111.293,8.54993C 114.358,10.111 117.341,12.0295 119.703,14.5303C 124.989,20.1284 128.21,27.9831
129.102,35.631C 130.136,47.2798 125.383,59.9273 117.828,68.8541C 111.811,75.9635 103.777,81.3415
95.5699,85.7447C 87.4468,90.1028 78.8872,93.7299 70.1037,96.5279C 61.7393,99.1602 53.5481,102.315
45.2999,105.291C 38.9852,107.57 32.6255,110.185 25.9468,110.865C 17.2621,111.748 8.72949,107.315 0,107.315L
0.794434,102.747'/>

<Path Canvas.Left='288.296' Canvas.Top='389.044' Fill='#1FFFFFFF' Data='F1 M


20.482,3.28394L 15.7751,1.64856L 12.4789,0.441711L 10.6573,0.590027L 8.08368,0L 5.41522,0.490295L
2.14392,1.11761L 1.95215,1.32953L 0.401306,3.08466L 0.397247,3.1156L 0.130981,5.50372L 0,7.08893L
1.05463,8.38318L 4.22186,12.0475L 4.37653,12.1388L 13.1867,17.1502L 21.4745,19.4272L 23.8445,19.5905L
28.8646,20.0002L 29.6535,19.9354L 30.5813,19.8581L 31.9124,18.952L 33.6298,17.7507L 33.6525,17.7346L
32.768,15.3674L 32.0575,13.1859L 31.7297,12.8204L 27.9907,8.39771L 23.0075,4.87152L 20.8281,3.70361L
20.482,3.28394'/>

<Path Canvas.Left='280.359' Canvas.Top='385.08' Fill='#1CFFFFFF' Data='F1 M


34.7863,7.36987L 21.7361,1.20502L 18.4429,1.0481L 16.6539,0.251465L 14.3235,0.124817L 11.5295,0L
6.10013,1.05707L 3.61429,1.56409C 2.32739,3.89185 1.13611,6.27313 0,8.6781L 0.0345154,8.72986L 2.24872,11.926L
2.37991,12.3015L 2.8631,13.6218C 3.79727,14.4518 4.72095,15.2939 5.66565,16.1121C 6.58997,16.9125
7.535,17.6888 8.4697,18.4772L 13.9882,21.4464L 14.6512,21.7931L 24.535,25.5446L 26.4161,25.6072L
26.95,25.6285L 31.4178,26.9878L 34.9437,27.144L 37.1637,27.7176C 39.2407,27.7209 41.3177,27.7469
43.3944,27.783L 45.2794,27.0061L 47.1747,26.1877C 47.5336,25.113 47.9153,24.0461 48.2921,22.9775L
48.0681,22.6865L 47.3178,21.668L 46.9842,20.2141L 46.8846,19.6923L 42.5043,13.8801L 42.2446,13.5021L
36.3703,8.5567L 35.1288,7.78833L 34.7863,7.36987'/>

<Path Canvas.Left='272.112' Canvas.Top='380.339' Fill='#19FFFFFF' Data='F1 M


44.497,8.82086L 30.9772,2.37115L 28.8696,2.25391L 26.3027,1.05243L 24.1494,0.944336L 19.6842,0.743835L
17.8785,0L 14.9364,0.601746L 13.7792,0.573975L 10.3028,0.547485L 8.15384,2.03601L 7.02151,2.36481L
4.04068,3.29175C 2.60236,5.49921 1.28119,7.78271 0,10.0849L 0.0298767,10.137L 0.957031,11.7346L
0.564972,13.1904L 0.502228,13.4486C 1.12769,14.5336 1.72705,15.6342 2.3786,16.7037C 3.11435,17.9116
3.90155,19.0873 4.66302,20.2791C 7.68164,22.5568 10.7885,24.7184 13.9342,26.8171L 16.5965,27.9986L
22.7225,30.6177L 40.1012,35.1307L 40.8949,35.148L 42.5136,35.1941L 45.9579,36.0711C 49.9547,36.1818
53.9461,36.4534 57.9341,36.7407L 58.0069,36.7124L 59.1246,36.2596L 60.2945,36.0527L 61.23,35.8745C
62.0005,35.2549 62.7637,34.625 63.4992,33.9642C 63.1211,31.8492 62.8243,29.7117 62.7231,27.5657L
60.6422,25.2402L 59.8235,23.268L 59.3877,22.8358L 58.4974,21.9156L 57.6932,20.3221L 52.6613,15.1617L
52.2264,14.6946L 44.8397,9.19708L 44.497,8.82086'/>

<Path Canvas.Left='563.395' Canvas.Top='313.725' Fill='#1FFFFFFF' Data='F1 M


4.98599,0.439941L 4.00967,0.195374L 3.33646,0L 2.93869,0.171631L 2.89481,0.191162L 2.34604,0.170532L
1.52286,0.659668L 0.900177,1.04865L 0.635712,1.46857L 0.365936,1.92419L 0.208221,2.53552L -3.05176e-
005,3.47229L 0.0932312,3.7533C 0.228058,4.21851 0.384308,4.67877 0.572235,5.12518L 1.45847,5.80334L
2.17722,6.29712L 3.57706,6.39044L 3.76053,6.40698C 4.25986,6.26532 4.75839,6.10913 5.27151,6.03082L
5.53476,5.92999L 5.65378,5.87274L 6.23154,5.21271L 6.59567,4.81439C 6.62619,4.28564 6.66751,3.7569
6.73563,3.23163L 6.33829,1.96051L 6.28165,1.76147L 5.43973,0.833923L 5.02805,0.568787L 4.98599,0.439941'/>

<Path Canvas.Left='561.862' Canvas.Top='312.445' Fill='#1CFFFFFF' Data='F1 M


8.07236,1.26935L 5.46756,0L 4.6951,0.192688L 4.33835,0.0353394L 4.15622,0.0793457L 3.16135,0.329712C
2.51736,0.713013 1.879,1.10614 1.25192,1.51648C 0.815094,2.46301 0.416656,3.42749 0.0387878,4.39905L 3.05176e-
005,4.50861C 0.0672913,4.9137 0.149139,5.31763 0.263153,5.71216L 0.313019,6.36206L 0.955231,7.29755L
1.2988,7.73053L 2.16757,8.28754L 2.42557,8.44275L 4.24124,9.02264L 4.71133,8.81854L 5.54599,8.9364L
6.24863,8.64026L 6.60446,8.64691L 6.67349,8.64948L 7.42734,8.31335L 7.9642,8.13525C 8.11765,7.99878
8.28592,7.87903 8.45786,7.76672L 8.93082,7.35217C 9.14047,6.91119 9.36319,6.47626 9.59604,6.04706L
9.52292,5.63208L 9.59299,5.26202L 9.66678,4.92603L 9.47568,4.08539L 9.2634,2.97107L 9.09048,2.71674L
8.34244,1.58698L 8.11392,1.39832L 8.07236,1.26935'/>

<Path Canvas.Left='560.228' Canvas.Top='310.937' Fill='#19FFFFFF' Data='F1 M


10.4037,1.42645L 7.64175,0.119995L 7.51309,0.151367L 7.14108,0.241394L 6.61868,0L 5.53769,0.26709L
5.07791,0.381775L 4.71066,0.245544L 4.04037,0.651672L 3.98856,0.68396L 2.93839,1.00623L 2.77213,1.20581L
2.35666,1.72052L 1.93265,2.047L 1.36899,2.50769C 0.927887,3.42169 0.531525,4.35718 0.148163,5.29688L
0.103424,5.41809L 0.146515,5.85535L 0.180756,6.08765L 0.10965,6.37L 3.05176e-005,6.9093C 0.146454,7.68365
0.347931,8.45947 0.683075,9.17279L 2.37479,10.7227L 2.76511,10.9156L 3.94339,11.48L 7.10526,11.947L
7.30246,11.8492L 7.58273,11.7212L 8.22025,11.7708C 9.01749,11.3641 9.80411,10.9117 10.6597,10.649L
10.9443,10.3544L 11.4138,10.1055L 11.4139,10.1053L 11.5391,9.99219L 11.6596,9.90161L 12.1151,9.36572C
12.291,8.56781 12.5459,7.78833 12.8103,7.0152L 12.6122,6.38367L 12.5919,6.31036L 12.6553,5.62286L
12.4875,5.22327L 12.486,5.16595L 12.4834,4.68677L 12.0699,3.74786L 11.752,2.99878L 10.6945,1.80969L
10.4535,1.53998L 10.4037,1.42645'/>

<Path Canvas.Left='194.924' Canvas.Top='339.107' Fill='#1FFFFFFF' Data='F1 M


8.39566,1.72736L 6.91541,0.900452L 5.89505,0.288696L 5.1748,0.322998L 4.31577,0L 2.33716,0.279968L
1.88766,0.339844L 0.885468,1.14111L 0.459137,1.94946L 0,2.86084L 0.376251,4.51782L 0.561249,5.25012L
2.70844,8.04956L 5.21777,9.52313L 7.02765,9.86163L 7.8815,10.02L 8.5827,9.97632L 9.55032,9.3877L
10.3248,8.9057L 10.6518,7.18469L 10.7777,6.5979L 10.2388,4.23303L 9.33731,2.92834L 9.04611,2.50323L
8.4437,1.92847L 8.39566,1.72736'/>

<Path Canvas.Left='192.529' Canvas.Top='337.212' Fill='#1CFFFFFF' Data='F1 M


13.2284,3.73199L 9.41827,0.720947L 8.18793,0.606445L 7.65851,0.213318L 6.00558,0.0278931L 5.76645,0L
2.65298,0.447205L 2.54126,0.461914L 0.915283,2.25696L 0,3.30695L 0.140137,4.29779L 0.221741,4.79089L
0.137726,5.52777L 1.02222,7.60443L 1.17819,7.95526L 2.65088,9.84644L 5.2775,12.25L 6.13321,12.4282L
7.41464,13.3389L 8.44855,13.512L 8.69727,13.5538L 9.37952,13.9315L 11.7926,14.072L 12.1255,13.9269L
13.7537,13.2018L 13.9587,12.9288L 15.0574,11.476L 14.993,10.7971L 15.0168,10.7144L 15.2989,9.78479L
14.9612,7.52521L 14.8613,6.70801L 13.6014,4.30597L 13.2762,3.93298L 13.2284,3.73199'/>

<Path Canvas.Left='189.842' Canvas.Top='335.032' Fill='#19FFFFFF' Data='F1 M


17.1443,4.36316L 13.1845,1.245L 12.3938,1.17456L 11.6383,0.592468L 10.4468,0.489746L 9.16522,0.367676L
8.61816,0L 7.39142,0.221924L 6.2012,0.122559L 5.67166,0.0772705L 4.61438,0.66449L 3.31998,0.950073L
2.90146,1.04242L 1.34363,2.58929L 0.360016,3.60657L 0.425262,4.32501L 0.32666,4.46924L 0,4.96289L
0.18335,6.98004L 0.305847,7.93701L 2.00272,10.9889L 2.22183,11.3727L 4.36935,13.8062L 9.25677,17.3614L
10.1271,17.5273L 10.7354,17.9264L 11.1298,18.1855L 14.91,18.6949L 15.6292,18.7859L 16.2874,18.4738L
17.2931,18.201L 17.3582,18.1526L 18.8359,17.0332L 18.8742,16.9325L 19.7963,14.6324L 20.261,13.5443L
19.9836,12.3638L 20.0672,11.7307L 20.1216,11.3644L 19.8983,10.6956L 19.9259,9.91541L 19.1819,7.81036L
18.9702,7.18237L 17.2023,4.54266L 17.1443,4.36316'/>

<Path Canvas.Left='353.214' Canvas.Top='240.881' Fill='#1FFFFFFF' Data='F1 M


9.88702,1.92657L 8.02679,0.995728L 6.74042,0.303467L 6.12439,0.346741L 5.88269,0.361572L 4.82227,0L
1.97034,0.426575L 1.5481,0.78479L 0.869812,1.34534L 0,3.30597L 0.0541992,3.48602L 0.873169,6.05719L
1.99689,7.44727L 3.57764,9.42346L 6.65033,11.2527L 6.83795,11.2917L 9.91339,11.85L 10.7791,11.776L
10.8079,11.758L 12.8471,10.4233L 12.9825,9.40131L 13.2236,7.63007L 12.4178,5.03687L 12.3558,4.83173L
10.7479,2.82306L 9.9657,2.16272L 9.88702,1.92657'/>

<Path Canvas.Left='350.267' Canvas.Top='238.683' Fill='#1CFFFFFF' Data='F1 M


15.767,4.17688L 10.8831,0.741638L 9.39746,0.644287L 8.72174,0.196594L 6.43506,0L 5.80865,0.112671L
2.6568,0.573792L 2.13153,1.20123L 0.187195,3.51892L 0,3.74011L 0.421509,5.40436L 0.398865,6.03534L
0.388306,6.23029L 1.75885,9.09589L 2.91595,10.5474L 3.58618,11.3938L 6.80359,14.3601L 7.83636,14.6105L
8.93311,15.408L 9.39984,15.7468L 10.9556,16.0428L 11.79,16.5131L 13.7683,16.6526L 14.752,16.6863L
16.3315,15.9376L 17.18,15.5165L 18.5408,13.5665L 18.6909,13.3456L 18.5646,12.526L 18.8519,11.2949L
18.4462,9.53076L 18.0358,7.64301L 16.2744,4.84314L 15.8453,4.41278L 15.767,4.17688'/>

<Path Canvas.Left='347.125' Canvas.Top='236.109' Fill='#19FFFFFF' Data='F1 M


20.2175,4.89111L 15.1544,1.31818L 14.1965,1.26166L 13.2305,0.59668L 11.218,0.486206L 10.2346,0.417114L
9.54034,0L 8.0965,0.297607L 6.02637,0.172058L 5.77716,0.321777L 4.84265,0.860535L 2.86713,1.29315L
2.49799,1.68378L 0.427979,3.86127L 0.231812,4.06427L 0.406799,4.84418L 0,5.49762C 0.206543,6.62775
0.39325,7.76141 0.577271,8.89545L 2.97412,13.0428L 3.44067,13.5707L 5.61237,16.0313L 11.5766,20.4623L
12.1048,20.5872L 12.6205,20.7043L 13.8408,21.5312L 17.1804,22.1061L 19.3038,22.3877L 20.1201,21.9976L
20.3289,21.9415L 21.3867,21.6105L 22.4238,20.7811L 23.3349,20.0213L 24.0768,17.9446L 24.8845,15.6688L
24.4517,14.2581L 24.521,13.0631L 24.1843,12.2783L 24.1369,11.3533L 23.2797,9.46075L 22.7018,8.15961L
20.3058,5.10107L 20.2175,4.89111'/>

<Path Canvas.Left='335.843' Canvas.Top='184.741' Fill='#345C5C5C' Data='F1 M


<Path Canvas.Left='335.843' Canvas.Top='184.741' Fill='#345C5C5C' Data='F1 M
36.3301,0C 36.3301,4.67841 35.9146,9.49182 34.322,13.8908C 31.8164,20.8117 27.2537,26.8353 24.4293,33.6324C
23.6634,35.444 22.6701,37.1517 21.7282,38.8784C 20.8773,40.5361 20.035,42.1984 19.1981,43.8633C
15.1631,51.5378 9.39685,58.1849 4.99097,65.6527C 3.23291,68.6326 1.38904,71.8659 1.21606,75.3214C
1.12836,77.0736 2.073,79.0042 3.45538,80.0844L 2.73102,81.0836C 1.1582,79.842 0,77.7265 0.0112305,75.7227C
0.0324707,71.928 2.05933,68.3226 3.99323,65.0576C 8.39789,57.6212 14.1614,51.0062 18.1815,43.355C
19.017,41.6895 19.8557,40.0254 20.6996,38.3641C 21.6102,36.6676 22.5811,34.9944 23.3203,33.2165C
26.0826,26.3806 30.4603,20.2617 33.1037,13.3788C 34.7228,9.16296 35.4608,4.55316 35.4608,0.0370483L
36.3301,0'/>

<Path Canvas.Left='334.507' Canvas.Top='184.778' Fill='#675C5C5C' Data='F1 M


36.7971,0C 36.7971,4.51611 36.0592,9.12592 34.4401,13.3418C 31.7966,20.2246 27.419,26.3435 24.6566,33.1794C
23.9175,34.9573 22.9466,36.6306 22.036,38.327C 21.1921,39.9883 20.3534,41.6524 19.5179,43.318C 15.4978,50.9692
9.73425,57.5842 5.32959,65.0206C 3.39569,68.2855 1.36884,71.891 1.3476,75.6857C 1.33636,77.6895 2.49457,79.805
4.06738,81.0466L 3.34955,82.0513C 1.61133,80.6686 0.258484,78.4196 0.160706,76.2007C 0,72.5526 1.76416,68.9691
3.54712,65.7823C 8.00842,57.8085 14.2542,50.8997 18.5013,42.8097C 19.3354,41.1434 20.1706,39.4777
21.0074,37.8127C 21.8879,36.1471 22.8362,34.5081 23.5476,32.7635C 27.8134,21.9146 35.7859,11.7123
35.9278,0.0370483L 36.7971,0'/>

<Path Canvas.Left='333.161' Canvas.Top='184.815' Fill='#B35C5C5C' Data='F1 M


37.2734,0C 37.1338,11.6625 29.1611,21.8721 24.8932,32.7265C 24.1818,34.4711 23.2335,36.11 22.353,37.7757C
21.5162,39.4406 20.681,41.1064 19.8469,42.7726C 15.5998,50.8626 9.354,57.7714 4.8927,65.7453C 3.10974,68.9321
1.34558,72.5156 1.50629,76.1636C 1.60406,78.3826 2.95691,80.6315 4.69513,82.0142L 4.33875,82.5185L
3.9834,83.0231L 3.96857,83.012C 2.09851,81.5163 0.585144,79.1895 0.349182,76.8065C 0,73.2796 1.49854,69.6895
3.13446,66.5455C 7.58307,57.9962 14.3526,50.7985 18.8304,42.2645C 19.663,40.5974 20.4946,38.9298
21.3244,37.2614C 22.1758,35.6271 23.102,34.0224 23.7842,32.3106C 27.9154,21.5236 36.0213,11.5815
36.4034,0.0367432L 36.8387,0.0185547L 37.2734,0'/>

<Path Canvas.Left='331.851' Canvas.Top='184.852' Fill='#675C5C5C' Data='F1 M


37.7137,0C 37.3315,11.5447 29.2256,21.4868 25.0944,32.2739C 24.4122,33.9857 23.486,35.5904 22.6346,37.2247C
21.8048,38.8931 20.9732,40.5607 20.1407,42.2277C 15.6628,50.7618 8.89328,57.9594 4.44467,66.5088C
2.80875,69.6527 1.31021,73.2429 1.65939,76.7697C 1.89536,79.1527 3.40872,81.4796 5.27878,82.9753L
5.29361,82.9864L 4.58298,83.9957L 4.53848,83.9623C 2.57681,82.3857 0.944183,80.0385 0.547394,77.5532C
0,74.1245 1.22537,70.5016 2.71335,67.3644C 7.06253,58.1948 14.4121,50.708 19.1241,41.7194C 19.9553,40.0517
20.7833,38.3823 21.606,36.7104C 22.4292,35.108 23.3343,33.5377 23.9854,31.858C 26.4535,25.245 30.0456,19.1074
32.9965,12.6953C 34.8405,8.68854 36.5965,4.43823 36.8422,0.0343628L 37.7137,0'/>

<Path Canvas.Left='330.638' Canvas.Top='184.886' Fill='#345C5C5C' Data='F1 M


38.0555,0C 37.8098,4.40387 36.0538,8.65417 34.2098,12.6609C 31.2589,19.073 27.6668,25.2106 25.1987,31.8236C
24.5476,33.5033 23.6425,35.0737 22.8193,36.676C 21.9966,38.348 21.1686,40.0173 20.3374,41.6851C
15.6255,50.6736 8.27585,58.1605 3.92667,67.3301C 2.43869,70.4672 1.21332,74.0901 1.76071,77.5188C
2.1575,80.0041 3.79013,82.3513 5.7518,83.928L 5.7963,83.9613L 5.08566,84.9706L 5.01157,84.915C 2.81754,83.1448
1.00705,80.5019 0.572144,77.7166C 0,74.0522 1.27798,70.1797 2.87051,66.8303C 7.23251,57.6562 14.6076,50.1754
19.3209,41.1768C 20.1506,39.5083 20.9751,37.8372 21.7907,36.1617C 22.5866,34.5917 23.4722,33.0561
24.0896,31.4077C 26.5118,24.7548 29.9539,18.5183 32.9846,12.1197C 34.8105,8.26483 36.8404,4.28339
37.1826,0.0317383L 38.0555,0'/>

<Path Canvas.Left='341.799' Canvas.Top='188.438' Fill='#34FFFFFF' Data='F1 M


31.7649,0.291748C 29.8024,4.76001 28.8149,9.59595 27.3909,14.2639C 24.7472,22.9302 21.8438,31.5225
18.6597,40.0052C 14.3988,50.8522 6.42328,59.8771 1.19812,70.294L 0,69.7336C 5.24512,59.3618 13.2403,50.3847
17.4763,39.5614C 20.6468,31.0824 23.4448,22.4672 26.2375,13.8564C 27.7445,9.21002 29.0421,4.47247 31.006,0L
31.7649,0.291748'/>

<Path Canvas.Left='340.6' Canvas.Top='188.146' Fill='#67FFFFFF' Data='F1 M


32.205,0.291748C 30.2411,4.76422 28.9435,9.50177 27.4366,14.1481C 24.6439,22.7589 21.8458,31.3741
18.6753,39.8531C 14.4393,50.6765 6.44415,59.6535 1.19904,70.0254L 0,69.4664C 5.26367,59.1383 13.2811,50.2097
17.4918,39.4094C 22.3539,26.3561 26.0031,12.8425 31.4462,0L 32.205,0.291748'/>

<Path Canvas.Left='339.4' Canvas.Top='187.854' Fill='#B3FFFFFF' Data='F1 M


32.6458,0.291626C 27.2057,13.1216 23.5558,26.6418 18.6915,39.701C 14.4807,50.5013 6.46332,59.4299
1.19965,69.7581L 0.599792,69.4791L 0,69.2004L 0.00848389,69.1835C 5.28534,58.903 13.3243,50.029
17.5081,39.2573C 22.3554,26.1915 26.2303,12.7362 31.8869,0L 32.2664,0.145813L 32.6458,0.291626'/>

<Path Canvas.Left='338.201' Canvas.Top='187.562' Fill='#67FFFFFF' Data='F1 M


33.0865,0.291809C 27.4299,13.028 23.5551,26.4833 18.7078,39.5491C 14.5239,50.3208 6.48499,59.1948
1.20813,69.4753L 1.19965,69.4922L 0,68.9348L 0.0254517,68.8839C 5.31201,58.6563 13.3715,49.8434
17.5243,39.1053C 20.6534,30.6371 23.1492,21.9407 26.3758,13.5093C 28.1345,8.91364 30.2532,4.4624 32.3267,0L
33.0865,0.291809'/>

<Path Canvas.Left='337.001' Canvas.Top='187.271' Fill='#34FFFFFF' Data='F1 M


<Path Canvas.Left='337.001' Canvas.Top='187.271' Fill='#34FFFFFF' Data='F1 M
33.5264,0.291809C 31.4528,4.75421 29.3341,9.20544 27.5754,13.8011C 24.3489,22.2325 21.8531,30.929
18.7239,39.3971C 14.5711,50.1352 6.51166,58.9481 1.2251,69.1757L 1.19965,69.2266L 0,68.6693L
0.0424194,68.5844C 5.33655,58.4085 13.4198,49.6583 17.5405,38.9533C 20.6558,30.4888 23.0561,21.7616
26.4221,13.3936C 28.2656,8.81055 30.6078,4.44385 32.7654,0L 33.5264,0.291809'/>

<Path Canvas.Left='370.356' Canvas.Top='178.582' Fill='#34FFFFFF' Data='F1 M 0,9.6391C


0.267395,7.76575 1.04425,5.82452 2.38171,4.48578C 4.21912,2.64667 6.90961,1.67657 9.4718,1.23688C 16.6791,0
24.1788,1.92059 31.2706,3.70441C 40.3289,6.05267 49.4479,8.88708 57.5599,13.552C 62.5287,16.4094
67.0493,20.1542 70.9077,24.3931L 70.8019,24.5373C 60.5973,13.7844 45.3606,8.41278 31.0201,4.65668C
24.0387,2.88074 16.6896,1.00183 9.56476,2.06525C 7.1394,2.42725 4.56854,3.25757 2.79999,4.95624C
1.53857,6.16785 0.772339,7.95282 0.524292,9.6842L 0,9.6391'/>

<Path Canvas.Left='370.88' Canvas.Top='179.583' Fill='#67FFFFFF' Data='F1 M 0,8.68237C


0.248047,6.95099 1.01428,5.16602 2.2757,3.95441C 4.04425,2.25574 6.61511,1.42542 9.04047,1.06342C 16.1653,0
23.5144,1.87891 30.4958,3.65485C 44.8363,7.41095 60.073,12.7826 70.2776,23.5355L 70.1723,23.6787C
59.7968,13.1957 44.5036,8.38098 30.2452,4.60712C 23.6927,2.9212 16.8886,1.25104 10.1442,1.78906C
7.64014,1.98883 4.93683,2.57526 2.99298,4.16632C 1.65881,5.25836 0.803406,7.01105 0.524353,8.72742L
0,8.68237'/>

<Path Canvas.Left='371.405' Canvas.Top='180.834' Fill='#B3FFFFFF' Data='F1 M


0,7.47638C 0.276611,5.7699 1.13086,4.01025 2.46863,2.91528C 4.41248,1.32422 7.11578,0.737793 9.61981,0.538025C
16.3643,0 23.1684,1.67017 29.7208,3.35608C 43.9792,7.12994 59.2725,11.9446 69.6479,22.4277L 69.5955,22.4989L
69.5429,22.5703L 69.5327,22.5596C 65.1606,18.3251 59.6335,15.3326 54.0963,12.8058C 46.1963,9.20081
37.8592,6.55121 29.4702,4.30835C 23.3381,2.71222 17.0269,1.22119 10.692,1.35455C 8.10791,1.40894
5.29071,1.73743 3.1615,3.2027C 1.77191,4.159 0.818665,5.86096 0.524658,7.52197L 0.262146,7.4989L 0,7.47638'/>

<Path Canvas.Left='371.929' Canvas.Top='182.056' Fill='#67FFFFFF' Data='F1 M


0,6.30078C 0.294006,4.63977 1.24725,2.93781 2.63684,1.98151C 4.76605,0.516235 7.58325,0.187744
10.1673,0.133362C 16.5023,0 22.8135,1.49103 28.9456,3.08716C 37.3345,5.33002 45.6716,7.97961 53.5716,11.5846C
59.1089,14.1115 64.6359,17.1039 69.008,21.3384L 69.0182,21.3491L 68.9131,21.4918L 68.8823,21.4598C
64.4532,17.3507 58.7593,14.7503 53.2205,12.3373C 45.3083,8.89026 37.0266,6.29047 28.6949,4.03943C
22.6517,2.4483 16.4427,0.999207 10.1935,1.01123C 7.74884,1.01593 5.07794,1.20123 3.01489,2.51276C
1.72821,3.33075 0.81488,4.85291 0.525269,6.34979L 0,6.30078'/>

<Path Canvas.Left='372.454' Canvas.Top='183.055' Fill='#34FFFFFF' Data='F1 M


0,5.35059C 0.289612,3.8537 1.20294,2.33154 2.48962,1.51355C 4.55267,0.202026 7.22357,0.0167236
9.66821,0.0120239C 15.9174,0 22.1264,1.4491 28.1697,3.04022C 36.5013,5.29126 44.783,7.89105 52.6952,11.3381C
58.234,13.7511 63.9279,16.3515 68.357,20.4606L 68.3878,20.4926L 68.2825,20.6352L 68.2312,20.582C
63.7419,16.5942 57.8903,14.392 52.3441,12.0907C 44.4215,8.80334 36.1938,6.25134 27.9191,3.99249C
22.2793,2.49054 16.5143,1.13214 10.6818,0.919495C 8.14642,0.827087 5.39563,0.75061 3.13428,1.9007C
1.83667,2.56067 0.828247,3.97937 0.525391,5.40332L 0,5.35059'/>

<Canvas Canvas.Left='888.255' Canvas.Top='952.934' Width='139.344' Height='18.5254'>


<Path Canvas.Left='0' Canvas.Top='0' Fill='#FF000000' Data='F1 M 5.54688,14.3164L
0,0L 2.05078,0L 5.77148,10.4004C 6.07098,11.2337 6.32166,12.015 6.52344,12.7441C 6.74481,11.9629
7.00195,11.1816 7.29492,10.4004L 11.1621,0L 13.0957,0L 7.49023,14.3164L 5.54688,14.3164'/>

<Path Canvas.Left='12.881' Canvas.Top='3.71094' Fill='#FF000000' Data='F1 M


7.68561,7.26563L 9.50201,7.49023C 9.21552,8.55145 8.68494,9.375 7.91022,9.96094C 7.1355,10.5469
6.14587,10.8398 4.94147,10.8398C 3.4245,10.8398 2.22174,10.3727 1.33301,9.43848C 0.444336,8.50427 0,7.19403
0,5.50781C 0,3.763 0.449219,2.40881 1.34766,1.44531C 2.24609,0.48175 3.4115,0 4.84375,0C 6.23053,0
7.36334,0.471985 8.24225,1.41602C 9.12115,2.36005 9.56061,3.68817 9.56061,5.40039C 9.56061,5.50452
9.55737,5.66077 9.55084,5.86914L 1.81647,5.86914C 1.88153,7.00842 2.2038,7.88086 2.78326,8.48633C
3.36267,9.0918 4.08533,9.39453 4.95123,9.39453C 5.59576,9.39453 6.14587,9.22528 6.60162,8.88672C
7.05731,8.54816 7.41864,8.00781 7.68561,7.26563M 1.91406,4.42383L 7.70514,4.42383C 7.62701,3.55145
7.40564,2.89716 7.04108,2.46094C 6.48114,1.78381 5.75525,1.44531 4.86334,1.44531C 4.05603,1.44531
3.37732,1.71545 2.82721,2.25586C 2.27704,2.7962 1.97272,3.51886 1.91406,4.42383'/>

<Path Canvas.Left='24.0527' Canvas.Top='3.71094' Fill='#FF000000' Data='F1 M


7.30469,6.80664L 9.03326,7.03125C 8.84442,8.22266 8.36102,9.15527 7.58307,9.8291C 6.80505,10.5029
5.84967,10.8398 4.7168,10.8398C 3.29755,10.8398 2.15662,10.376 1.29401,9.44824C 0.431335,8.52051 0,7.19073
0,5.45898C 0,4.33923 0.185608,3.35938 0.556702,2.51953C 0.927795,1.67969 1.49255,1.0498 2.25104,0.629883C
3.00946,0.209961 3.83466,0 4.72656,0C 5.85291,0 6.77411,0.28479 7.4903,0.854492C 8.20642,1.42419
8.66541,2.23309 8.86719,3.28125L 7.15826,3.54492C 6.99548,2.84827 6.7074,2.32422 6.29401,1.97266C
5.88055,1.62109 5.38092,1.44531 4.79492,1.44531C 3.90955,1.44531 3.19012,1.7627 2.63672,2.39746C
2.08337,3.03223 1.8067,4.0365 1.8067,5.41016C 1.8067,6.80334 2.07361,7.81573 2.60748,8.44727C 3.1413,9.0788
3.83795,9.39453 4.69733,9.39453C 5.38739,9.39453 5.96356,9.18292 6.42578,8.75977C 6.88806,8.33655
7.18103,7.68555 7.30469,6.80664'/>
<Path Canvas.Left='33.623' Canvas.Top='0.322266' Fill='#FF000000' Data='F1 M
4.80469,12.4219L 5.05865,13.9746C 4.56384,14.0788 4.12115,14.1309 3.73053,14.1309C 3.09247,14.1309
2.59766,14.03 2.24609,13.8281C 1.89453,13.6263 1.64716,13.361 1.50391,13.0322C 1.36072,12.7034 1.28906,12.0117
1.28906,10.957L 1.28906,4.99023L 0,4.99023L 0,3.62305L 1.28906,3.62305L 1.28906,1.05469L 3.03711,0L
3.03711,3.62305L 4.80469,3.62305L 4.80469,4.99023L 3.03711,4.99023L 3.03711,11.0547C 3.03711,11.556
3.06805,11.8782 3.12994,12.0215C 3.19177,12.1647 3.29266,12.2786 3.43268,12.3633C 3.57263,12.4479
3.77283,12.4902 4.03326,12.4902C 4.22852,12.4902 4.48572,12.4674 4.80469,12.4219'/>

<Path Canvas.Left='39.4927' Canvas.Top='3.71094' Fill='#FF000000' Data='F1 M


0,5.41992C 0,3.49933 0.533813,2.07678 1.60156,1.15234C 2.49347,0.384094 3.58075,0 4.86328,0C 6.28906,0
7.45441,0.467102 8.35938,1.40137C 9.26428,2.33563 9.7168,3.62628 9.7168,5.27344C 9.7168,6.60803 9.5166,7.65784
9.11621,8.42285C 8.71582,9.18781 8.13312,9.78186 7.36816,10.2051C 6.60321,10.6282 5.76825,10.8398
4.86328,10.8398C 3.41144,10.8398 2.23792,10.3743 1.34277,9.44336C 0.447571,8.51233 0,7.1712 0,5.41992M
1.80664,5.41992C 1.80664,6.74805 2.09637,7.74255 2.67578,8.40332C 3.25519,9.06415 3.98438,9.39453
4.86328,9.39453C 5.73566,9.39453 6.46155,9.0625 7.04102,8.39844C 7.62042,7.73438 7.91016,6.72198
7.91016,5.36133C 7.91016,4.07874 7.61884,3.10706 7.03613,2.44629C 6.45343,1.78546 5.72913,1.45508
4.86328,1.45508C 3.98438,1.45508 3.25519,1.78381 2.67578,2.44141C 2.09637,3.099 1.80664,4.0918
1.80664,5.41992'/>

<Path Canvas.Left='51.2503' Canvas.Top='3.71094' Fill='#FF000000' Data='F1 M


0,10.6055L 0,0.234375L 1.58197,0.234375L 1.58197,1.80664C 1.98566,1.07092 2.3584,0.585938 2.7002,0.351563C
3.04199,0.117188 3.41797,0 3.82813,0C 4.42053,0 5.02277,0.188782 5.63477,0.566406L 5.0293,2.19727C
4.59961,1.94336 4.16992,1.81641 3.74023,1.81641C 3.35608,1.81641 3.01105,1.93195 2.70508,2.16309C
2.39905,2.39417 2.18097,2.71484 2.05072,3.125C 1.85547,3.75 1.75781,4.43359 1.75781,5.17578L 1.75781,10.6055L
0,10.6055'/>

<Path Canvas.Left='63.7116' Canvas.Top='0' Fill='#FF000000' Data='F1 M 0,14.3164L


0,0L 4.93158,0C 6.04492,0 6.89453,0.0683594 7.48041,0.205078C 8.30078,0.39386 9.00061,0.735657
9.58002,1.23047C 10.3352,1.86847 10.9,2.6839 11.2744,3.67676C 11.6487,4.66956 11.8359,5.80402 11.8359,7.08008C
11.8359,8.1673 11.709,9.13086 11.4551,9.9707C 11.2011,10.8105 10.8756,11.5056 10.4785,12.0557C 10.0814,12.6058
9.64679,13.0388 9.1748,13.3545C 8.70276,13.6702 8.13312,13.9095 7.46576,14.0723C 6.79846,14.235
6.03186,14.3164 5.16595,14.3164L 0,14.3164M 1.89447,12.627L 4.95117,12.627C 5.89514,12.627 6.63574,12.5391
7.17279,12.3633C 7.7099,12.1875 8.138,11.9401 8.45697,11.6211C 8.90619,11.1719 9.25616,10.568 9.50684,9.80957C
9.75745,9.05109 9.88281,8.13147 9.88281,7.05078C 9.88281,5.55334 9.63702,4.40265 9.14545,3.59863C
8.65393,2.79456 8.05658,2.25586 7.35345,1.98242C 6.84564,1.78711 6.02863,1.68945 4.90228,1.68945L
1.89447,1.68945L 1.89447,12.627'/>

<Path Canvas.Left='77.9103' Canvas.Top='3.71094' Fill='#FF000000' Data='F1 M


0,10.6055L 0,0.234375L 1.58203,0.234375L 1.58203,1.80664C 1.98572,1.07092 2.3584,0.585938 2.7002,0.351563C
3.04199,0.117188 3.41797,0 3.82813,0C 4.42059,0 5.02283,0.188782 5.63477,0.566406L 5.0293,2.19727C
4.59961,1.94336 4.16992,1.81641 3.74023,1.81641C 3.35614,1.81641 3.01111,1.93195 2.70508,2.16309C
2.39911,2.39417 2.18097,2.71484 2.05078,3.125C 1.85547,3.75 1.75781,4.43359 1.75781,5.17578L 1.75781,10.6055L
0,10.6055'/>

<Path Canvas.Left='83.9941' Canvas.Top='3.71094' Fill='#FF000000' Data='F1 M


7.36328,9.32617C 6.71222,9.87952 6.08557,10.2701 5.4834,10.498C 4.88116,10.7259 4.23499,10.8398
3.54492,10.8398C 2.40558,10.8398 1.52997,10.5615 0.917969,10.0049C 0.305969,9.44824 0,8.737 0,7.87109C
0,7.36328 0.11554,6.89941 0.34668,6.47949C 0.57782,6.05957 0.880493,5.72266 1.25488,5.46875C 1.62921,5.21484
2.05078,5.02277 2.51953,4.89258C 2.86456,4.80145 3.38538,4.71356 4.08203,4.62891C 5.50128,4.45959
6.5462,4.25781 7.2168,4.02344C 7.22333,3.78253 7.22656,3.62958 7.22656,3.56445C 7.22656,2.84833
7.06055,2.34375 6.72845,2.05078C 6.2793,1.65363 5.612,1.45508 4.72656,1.45508C 3.89972,1.45508 3.28937,1.59991
2.89551,1.88965C 2.50165,2.17938 2.21027,2.69208 2.02148,3.42773L 0.302734,3.19336C 0.458984,2.4577
0.716125,1.86359 1.07422,1.41113C 1.43225,0.958679 1.94983,0.610352 2.62689,0.366211C 3.30402,0.12207 4.0885,0
4.98047,0C 5.86584,0 6.58527,0.104126 7.13867,0.3125C 7.69208,0.520813 8.09894,0.782837 8.35938,1.09863C
8.61981,1.41437 8.80206,1.81317 8.90625,2.29492C 8.96484,2.59442 8.99408,3.13477 8.99408,3.91602L
8.99408,6.25977C 8.99408,7.89386 9.03156,8.92737 9.10645,9.36035C 9.18134,9.79327 9.32941,10.2083
9.55078,10.6055L 7.71484,10.6055C 7.53253,10.2409 7.41534,9.81445 7.36328,9.32617M 7.2168,5.40039C
6.57874,5.66077 5.6217,5.88214 4.34564,6.06445C 3.62305,6.16858 3.11194,6.28577 2.8125,6.41602C 2.513,6.5462
2.28186,6.73663 2.11914,6.9873C 1.95636,7.23798 1.875,7.5163 1.875,7.82227C 1.875,8.29102 2.05243,8.68164
2.40723,8.99414C 2.76202,9.30664 3.28125,9.46289 3.96484,9.46289C 4.64191,9.46289 5.24414,9.31476
5.77148,9.01855C 6.29883,8.72235 6.68622,8.31708 6.93359,7.80273C 7.12238,7.40558 7.2168,6.81964
7.2168,6.04492L 7.2168,5.40039'/>

<Path Canvas.Left='94.4529' Canvas.Top='3.94531' Fill='#FF000000' Data='F1 M


3.17377,10.3711L 0,0L 1.81641,0L 3.4668,5.98633L 4.08203,8.21289C 4.10803,8.10217 4.28705,7.38928
4.61908,6.07422L 6.26953,0L 8.07617,0L 9.62891,6.01563L 10.1465,7.99805L 10.7422,5.99609L 12.5195,0L
14.2285,0L 10.9863,10.3711L 9.16016,10.3711L 7.5097,4.16016L 7.10938,2.39258L 5.0097,10.3711L
3.17377,10.3711'/>
<Path Canvas.Left='110.165' Canvas.Top='0' Fill='#FF000000' Data='F1 M 0,2.02148L
0,0L 1.75781,0L 1.75781,2.02148L 0,2.02148M 0,14.3164L 0,3.94531L 1.75781,3.94531L 1.75781,14.3164L
0,14.3164'/>

<Path Canvas.Left='114.598' Canvas.Top='3.71094' Fill='#FF000000' Data='F1 M


0,10.6055L 0,0.234375L 1.58203,0.234375L 1.58203,1.70898C 2.34375,0.569641 3.44403,0 4.88281,0C 5.50781,0
6.08234,0.112305 6.60645,0.336914C 7.13055,0.561523 7.52277,0.856079 7.7832,1.2207C 8.04364,1.58527
8.22589,2.01819 8.33008,2.51953C 8.3952,2.84503 8.42773,3.41467 8.42773,4.22852L 8.42773,10.6055L
6.66992,10.6055L 6.66992,4.29688C 6.66992,3.58069 6.60156,3.04523 6.46484,2.69043C 6.32813,2.33557
6.08563,2.05237 5.7373,1.84082C 5.38898,1.62921 4.98047,1.52344 4.51172,1.52344C 3.76306,1.52344
3.11688,1.76105 2.57324,2.23633C 2.0296,2.71161 1.75781,3.61328 1.75781,4.94141L 1.75781,10.6055L 0,10.6055'/>

<Path Canvas.Left='125.047' Canvas.Top='3.71094' Fill='#FF000000' Data='F1 M


0.351563,11.4648L 2.06055,11.7188C 2.13214,12.2461 2.33075,12.6302 2.65625,12.8711C 3.09247,13.1967
3.68817,13.3594 4.44336,13.3594C 5.2572,13.3594 5.88544,13.1967 6.32813,12.8711C 6.77087,12.5456
7.07031,12.0898 7.22656,11.5039C 7.31769,11.1458 7.36005,10.3939 7.35352,9.24805C 6.58527,10.153
5.6283,10.6055 4.48242,10.6055C 3.05664,10.6055 1.95313,10.0911 1.17188,9.0625C 0.390625,8.03387 0,6.80011
0,5.36133C 0,4.3717 0.179077,3.45862 0.537109,2.62207C 0.895203,1.78546 1.41437,1.13928 2.09473,0.683594C
2.77509,0.227844 3.57422,0 4.49219,0C 5.71619,0 6.72528,0.494751 7.51953,1.48438L 7.51953,0.234375L
9.14063,0.234375L 9.14063,9.19922C 9.14063,10.8138 8.97626,11.958 8.64746,12.6318C 8.31873,13.3057
7.79785,13.8379 7.08496,14.2285C 6.37207,14.6191 5.49481,14.8145 4.45313,14.8145C 3.21613,14.8145
2.2168,14.5361 1.45508,13.9795C 0.693359,13.4229 0.325562,12.5847 0.351563,11.4648M 1.80664,5.23438C
1.80664,6.59503 2.07684,7.58789 2.61719,8.21289C 3.15753,8.83789 3.83466,9.15039 4.64844,9.15039C
5.45575,9.15039 6.13281,8.83948 6.67969,8.21777C 7.22656,7.59601 7.5,6.62109 7.5,5.29297C 7.5,4.02344
7.21844,3.06641 6.65527,2.42188C 6.09216,1.77734 5.41339,1.45508 4.61914,1.45508C 3.83789,1.45508
3.17383,1.77246 2.62695,2.40723C 2.08008,3.04199 1.80664,3.98438 1.80664,5.23438'/>

<Path Canvas.Left='137.342' Canvas.Top='12.3145' Fill='#FF000000' Data='F1 M


0,2.00195L 0,0L 2.00189,0L 2.00189,2.00195L 0,2.00195'/>

</Canvas>
<Path Canvas.Left='397.111' Canvas.Top='270.871' Fill='#34FFFFFF' Data='F1 M
0.296112,0C 7.02383,6.12756 8.51117,17.194 7.75146,26.2622C 7.31982,29.4223 5.53839,32.2619 4.07693,35.0968L
3.73489,34.9761C 5.0965,32.134 6.84088,29.3306 7.27322,26.209C 8.04324,17.2848 6.48596,6.53064 0,0.31842L
0.296112,0'/>

<Path Canvas.Left='396.815' Canvas.Top='271.189' Fill='#67FFFFFF' Data='F1 M


0.296112,0C 6.76669,6.20398 8.33994,16.9595 7.56934,25.8906C 7.13699,29.0122 5.39261,31.8156 4.03101,34.6577L
3.68933,34.5374C 4.95511,31.6925 6.65759,28.921 7.09109,25.8375C 7.87228,17.0457 6.20364,6.60797 0,0.31842L
0.296112,0'/>

<Path Canvas.Left='396.518' Canvas.Top='271.508' Fill='#B3FFFFFF' Data='F1 M


0.296326,0C 6.49658,6.28503 8.16879,16.725 7.38742,25.519C 6.95392,28.6025 5.25143,31.3741 3.98566,34.219L
3.81497,34.1592L 3.64447,34.0995L 3.6474,34.0922C 4.8204,31.2507 6.4744,28.5092 6.90915,25.4659C
7.70126,16.809 5.91669,6.68738 0,0.318481L 0.148285,0.15918L 0.296326,0'/>

<Path Canvas.Left='396.221' Canvas.Top='271.826' Fill='#67FFFFFF' Data='F1 M


0.297333,0C 6.21402,6.3689 7.9986,16.4905 7.20648,25.1475C 6.77173,28.1907 5.11774,30.9322 3.94473,33.7737L
3.9418,33.781L 3.6008,33.6616L 3.60959,33.6396C 4.69244,30.8074 6.29196,28.095 6.72824,25.0943C
7.53079,16.5743 5.62329,6.76935 0,0.318604L 0.297333,0'/>

<Path Canvas.Left='395.923' Canvas.Top='272.145' Fill='#34FFFFFF' Data='F1 M


0.298279,0C 5.92157,6.45074 7.82907,16.2557 7.02652,24.7757C 6.59024,27.7764 4.99072,30.4888 3.90787,33.321L
3.89908,33.343L 3.55811,33.2236L 3.57275,33.187C 4.56918,30.3671 6.10971,27.6809 6.54828,24.7225C
7.36111,16.3394 5.31812,6.84955 0,0.318481L 0.298279,0'/>

<Path Canvas.Left='278.485' Canvas.Top='250.324' Fill='#345C5C5C' Data='F1 M


5.77518,41.8961C 4.82028,40.4924 3.66159,39.2117 2.88733,37.7009C 1.01059,34.0387 0,29.5687 0.803497,25.5328C
1.87845,20.1334 6.41992,15.7242 10.7938,12.3808C 13.3438,10.5339 16.1544,9.01251 19.0771,7.84137C
22.4019,6.59198 25.7593,5.41638 29.1691,4.42194C 38.2685,1.91235 47.7014,0.165466 57.1392,0L 57.1563,0.670166C
47.7667,0.80603 38.3677,2.45483 29.3074,4.9234C 25.9111,5.90942 22.5658,7.07257 19.2522,8.30835C 16.37,9.45575
13.5968,10.9486 11.0822,12.7654C 6.79935,16.0332 2.34061,20.3438 1.29871,25.6293C 0.221069,31.0961
2.78665,37.1425 6.07108,41.6746L 5.77518,41.8961'/>

<Path Canvas.Left='278.705' Canvas.Top='250.995' Fill='#675C5C5C' Data='F1 M


5.85153,41.0044C 2.5784,36.4852 0,30.4337 1.07916,24.9591C 2.12106,19.6736 6.5798,15.363 10.8627,12.0952C
13.3773,10.2784 16.1505,8.78558 19.0327,7.63818C 22.3463,6.4024 25.6916,5.23926 29.0879,4.25323C
38.1482,1.78467 47.5471,0.135864 56.9368,0L 56.9537,0.670227C 47.6121,0.776917 38.2477,2.32764
29.2262,4.75464C 25.8434,5.7326 22.5102,6.883 19.2078,8.10522C 16.3659,9.22876 13.6302,10.693 11.1512,12.4798C
6.95941,15.6723 2.58298,19.884 1.57437,25.0555C 0.529785,30.4116 3.0903,36.2526 6.1474,40.7828L
5.85153,41.0044'/>

<Path Canvas.Left='279.234' Canvas.Top='251.665' Fill='#B35C5C5C' Data='F1 M


5.6181,40.1126C 2.56418,35.5871 0,29.7439 1.04507,24.3853C 2.05368,19.2137 6.43011,15.0021 10.6219,11.8096C
13.1009,10.0228 15.8366,8.55853 18.6785,7.435C 21.9809,6.21277 25.3141,5.06238 28.6969,4.08441C
37.7184,1.65741 47.0828,0.106689 56.4244,0L 56.4327,0.335266L 56.441,0.67041L 56.4327,0.67041C
47.1417,0.747375 37.815,2.20026 28.8352,4.58588C 25.4659,5.55554 22.1446,6.69305 18.8536,7.90204C
16.0521,9.00159 13.354,10.4376 10.9102,12.1941C 6.80988,15.3115 2.51517,19.424 1.54025,24.4818C
0.529663,29.7245 3.08151,35.3651 5.91425,39.8909L 5.76605,40.0018L 5.6181,40.1126'/>

<Path Canvas.Left='279.764' Canvas.Top='252.335' Fill='#675C5C5C' Data='F1 M


5.38458,39.2205C 2.55185,34.6946 0,29.0541 1.01059,23.8113C 1.9855,18.7535 6.28021,14.6411 10.3806,11.5237C
12.8244,9.76715 15.5224,8.33118 18.3239,7.23163C 21.6149,6.02264 24.9363,4.88513 28.3055,3.91547C
37.2853,1.52985 46.6121,0.0769653 55.903,0L 55.9113,0L 55.928,0.670471L 55.903,0.670471C 46.6653,0.718079
37.3797,2.07404 28.4439,4.41687C 25.0882,5.37842 21.7788,6.5033 18.4991,7.69867C 15.7379,8.77429
13.0774,10.1816 10.669,11.9083C 6.66003,14.9506 2.44681,18.9638 1.5058,23.9078C 0.529907,29.035
3.07019,34.4796 5.68152,38.9987L 5.38458,39.2205'/>

<Path Canvas.Left='280.294' Canvas.Top='253.006' Fill='#345C5C5C' Data='F1 M


5.15161,38.3282C 2.54028,33.8091 0,28.3646 0.975891,23.2373C 1.9169,18.2933 6.13013,14.2802 10.1391,11.2378C
12.5475,9.51117 15.208,8.10382 17.9692,7.0282C 21.2489,5.83282 24.5583,4.70795 27.914,3.7464C 36.8498,1.40356
46.1354,0.0476074 55.3731,0L 55.3981,0L 55.4147,0.670532L 55.3731,0.670532C 46.1885,0.687866 36.9442,1.94708
28.0523,4.24786C 24.71,5.20087 21.4128,6.31335 18.1443,7.49518C 15.4236,8.54712 12.8005,9.9259
10.4276,11.6224C 6.50995,14.5897 2.37778,18.5035 1.4711,23.3337C 0.530273,28.3458 3.05893,33.6015
5.44931,38.1061L 5.15161,38.3282'/>

<Path Canvas.Left='363.858' Canvas.Top='249.441' Data='F1 M 5.84181,0C 9.06813,0


11.6836,1.66449 11.6836,3.71753C 11.6836,5.77069 9.06813,7.43512 5.84181,7.43512C 2.61548,7.43512 9.22428e-
006,5.77069 9.22428e-006,3.71753C 9.22428e-006,1.66449 2.61548,0 5.84181,0'>
<Shape.Fill>
<!-- fade -->
<LinearGradientBrush MappingMode='Absolute' StartPoint='4.77966,6.63849'
EndPoint='4.77966,-5.57617'>
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color='#FFFFFFFF' Offset='0'/>
<GradientStop Color='#FF646464' Offset='0.734375'/>
<GradientStop Color='#FF828282' Offset='1'/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Shape.Fill>
</Path>

<Path Canvas.Left='362.305' Canvas.Top='247.887' Fill='#23000000' Data='F1 M


7.39518,0C 9.29688,0.0611572 11.3461,0.512573 12.8515,1.67615C 13.9287,2.50873 14.7364,3.91058
14.7904,5.27094L 14.7904,5.27094C 14.7364,6.63135 13.9287,8.03326 12.8515,8.86584C 11.3461,10.0294
9.29685,10.4807 7.39518,10.5419L 7.39518,10.5419C 5.49352,10.4807 3.44423,10.0294 1.93883,8.86584C
0.861628,8.03326 0.0540072,6.63135 -1.07996e-005,5.27094L -1.07996e-005,5.27094C 0.0540072,3.91058
0.861628,2.50873 1.93883,1.67615C 3.44423,0.512573 5.49349,0.0611572 7.39518,0L 7.39518,0.621399C
5.62698,0.678162 3.71831,1.08673 2.31824,2.16821C 1.38535,2.88885 0.668116,4.09308 0.621367,5.27094L
0.621367,5.27094C 0.667994,6.44885 1.3853,7.6532 2.31824,8.37378C 3.71836,9.4552 5.62698,9.86365
7.39518,9.92053L 7.39518,9.92053C 9.16339,9.86365 11.072,9.4552 12.4721,8.37378C 13.4051,7.6532
14.1224,6.44885 14.169,5.27094L 14.169,5.27094C 14.1223,4.09308 13.405,2.88885 12.4721,2.16821C
11.0721,1.08673 9.16339,0.678162 7.39518,0.621399L 7.39518,0'/>

<Path Canvas.Left='362.926' Canvas.Top='248.509' Fill='#46000000' Data='F1 M


6.77382,0C 8.54202,0.0567627 10.4507,0.465332 11.8508,1.54681C 12.7837,2.26746 13.5009,3.47168
13.5476,4.64954L 13.5476,4.64954C 13.501,5.82745 12.7837,7.0318 11.8508,7.75238C 10.4506,8.8338
8.54202,9.24225 6.77382,9.29913L 6.77382,9.29913C 5.00561,9.24225 3.09699,8.8338 1.69687,7.75238C
0.763933,7.0318 0.046626,5.82745 -1.65217e-006,4.64954L -1.65217e-006,4.64954C 0.0467475,3.47168
0.763982,2.26746 1.69687,1.54681C 3.09694,0.465332 5.00561,0.0567627 6.77382,0L 6.77382,0.621338C
5.13908,0.673828 3.37114,1.03961 2.07631,2.03888C 1.28763,2.64752 0.660808,3.65405 0.621352,4.64954L
0.621352,4.64954C 0.660783,5.64502 1.28761,6.65161 2.07631,7.26031C 3.37114,8.25958 5.1391,8.62518
6.77382,8.6778L 6.77382,8.6778C 8.40853,8.62518 10.1765,8.25958 11.4713,7.26031C 12.26,6.65161 12.8868,5.64502
12.9263,4.64954L 12.9263,4.64954C 12.8868,3.65405 12.26,2.64752 11.4713,2.03888C 10.1765,1.03961
8.40855,0.673828 6.77382,0.621338L 6.77382,0'/>
<Path Canvas.Left='363.547' Canvas.Top='249.13' Fill='#7A000000' Data='F1 M 6.15248,0C
7.78722,0.0524902 9.55515,0.418274 10.85,1.41754C 11.6387,2.02618 12.2655,3.03271 12.3049,4.0282L
12.3049,4.0282C 12.2655,5.02368 11.6387,6.03027 10.85,6.63898C 9.55515,7.63824 7.78719,8.00385
6.15248,8.05646L 6.15248,8.05646C 4.51776,8.00385 2.7498,7.63824 1.45498,6.63898C 0.666269,6.03027
0.0394454,5.02368 1.37023e-005,4.0282L 1.37023e-005,4.0282C 0.0394697,3.03271 0.666293,2.02618
1.45498,1.41754C 2.7498,0.418274 4.51774,0.0524902 6.15248,0L 6.15248,0.621399C 3.98821,0.690674
0.707208,1.8645 0.621343,4.0282L 0.621343,4.0282C 0.707183,6.19189 3.98821,7.36566 6.15248,7.43512L
6.15248,7.43512C 8.31675,7.36566 11.5978,6.19189 11.6836,4.0282L 11.6836,4.0282C 11.5977,1.8645
8.31675,0.690674 6.15248,0.621399L 6.15248,0'/>

<Path Canvas.Left='364.169' Canvas.Top='249.751' Fill='#46000000' Data='F1 M


5.53114,0C 7.69541,0.0692749 10.9764,1.2431 11.0623,3.4068C 10.9764,5.5705 7.69541,6.74426 5.53114,6.81372C
3.36687,6.74426 0.0858453,5.5705 4.74625e-006,3.4068C 0.0858696,1.2431 3.36687,0.0692749 5.53114,0L
5.53114,0.621277C 3.65048,0.681519 0.695797,1.52661 0.621358,3.4068L 0.621358,3.4068C 0.696162,5.28699
3.65048,6.13196 5.53114,6.19238L 5.53114,6.19238C 7.4118,6.13196 10.3661,5.28699 10.4409,3.4068L
10.4409,3.4068C 10.3665,1.52661 7.4118,0.681519 5.53114,0.621277L 5.53114,0'/>

<Path Canvas.Left='364.79' Canvas.Top='250.373' Fill='#23000000' Data='F1 M 4.90977,0C


6.79044,0.0602417 9.74512,0.905334 9.81955,2.78552C 9.74475,4.66571 6.79044,5.51068 4.90977,5.57111C
3.02911,5.51068 0.0747931,4.66571 -1.04168e-005,2.78552C 0.0744285,0.905334 3.02911,0.0602417 4.90977,0L
4.90977,0.621399C 3.30941,0.672607 0.684356,1.18561 0.621367,2.78552L 0.621367,2.78552C 0.684259,4.3855
3.30941,4.89838 4.90977,4.94971L 4.90977,4.94971C 6.51014,4.89838 9.13529,4.3855 9.19818,2.78552L
9.19818,2.78552C 9.13519,1.18561 6.51014,0.672607 4.90977,0.621399L 4.90977,0'/>

<Path Canvas.Left='358.46' Canvas.Top='252.798' Fill='#14000000' Data='F1 M


1.19113,0.256409C 0.55159,1.58075 0.87575,3.42487 1.70687,4.63818C 2.65651,6.02454 4.4031,6.9057
6.0612,7.17877C 10.4255,7.70062 16.0481,7.29547 18.8315,3.89368L 19.2003,4.13928L 19.2003,4.13928C
16.3651,7.76593 10.4766,8.55157 5.91706,7.91766C 4.08638,7.56732 2.18284,6.5199 1.17769,4.9502C
0.284474,3.55524 9.12741e-007,1.4798 0.744196,0L 1.19113,0.256409'/>

<Path Canvas.Left='357.909' Canvas.Top='252.542' Fill='#28000000' Data='F1 M


1.29504,0.256409C 0.550843,1.73621 0.835316,3.81165 1.72853,5.2066C 2.73368,6.77631 4.63722,7.82373
6.4679,8.17407C 11.0274,8.80798 16.9159,8.02234 19.7511,4.39569L 20.1199,4.64124L 20.1199,4.64124C
17.2317,8.49268 11.0795,9.66052 6.32378,8.91284C 4.32012,8.48486 2.25992,7.27161 1.19938,5.51862C
0.245284,3.94147 8.71646e-006,1.63654 0.848103,0L 1.29504,0.256409'/>

<Path Canvas.Left='357.359' Canvas.Top='252.285' Fill='#46000000' Data='F1 M


1.39821,0.25647C 0.550119,1.89301 0.795394,4.19794 1.74949,5.77509C 2.81003,7.52808 4.87023,8.74133
6.87389,9.16931C 11.6296,9.91699 17.7818,8.74915 20.67,4.89771L 21.0388,5.14325L 21.0388,5.14325C
19.6173,7.11298 17.5065,8.72772 15.2085,9.51508C 12.532,10.4322 9.51713,10.3932 6.72974,9.90814C
4.55285,9.40204 2.33619,8.02344 1.2203,6.08698C 0.206241,4.32727 2.89093e-006,1.79443 0.951295,0L
1.39821,0.25647'/>

<Path Canvas.Left='356.809' Canvas.Top='252.029' Fill='#28000000' Data='F1 M


1.50128,0.256409C 0.549991,2.05084 0.756229,4.58368 1.77029,6.34338C 2.88618,8.27985 5.10284,9.65845
7.27972,10.1646C 10.0671,10.6497 13.082,10.6886 15.7585,9.77148C 18.0564,8.98413 20.1672,7.36938
21.5888,5.39966L 21.9575,5.6452L 21.9575,5.6452C 20.4979,7.74017 18.3541,9.51184 15.9677,10.4196C
13.2118,11.4678 10.0323,11.4531 7.1356,10.9034C 4.7854,10.3185 2.41243,8.77521 1.24114,6.6554C
0.167813,4.71289 7.01993e-006,1.95288 1.05435,0L 1.50128,0.256409'/>

<Path Canvas.Left='356.26' Canvas.Top='251.772' Fill='#14000000' Data='F1 M


1.60403,0.256409C 0.54969,2.20929 0.717495,4.9693 1.79082,6.9118C 2.96211,9.03162 5.33508,10.5749
7.68529,11.1598C 10.582,11.7095 13.7615,11.7242 16.5173,10.676C 18.9038,9.76825 21.0476,7.99658
22.5072,5.90161L 22.876,6.14716L 22.876,6.14716C 21.1842,8.65582 18.5755,10.7662 15.6991,11.7051C
13.1133,12.5491 10.2061,12.4434 7.54115,11.8987C 5.0176,11.2343 2.48832,9.52698 1.26164,7.22382C
0.129575,5.09827 5.52603e-006,2.11194 1.15709,0L 1.60403,0.256409'/>

<Path Canvas.Left='333.978' Canvas.Top='260.613' Fill='#34FFFFFF' Data='F1 M


0,1.87567C 0.853149,1.19275 1.59885,0.0772095 2.68893,0C 3.40631,0.0150757 4.20428,0.512085 4.49786,1.16681C
4.8504,1.95306 4.65067,2.9173 4.43286,3.75098C 4.17505,4.42596 3.31134,4.86377 3.27841,5.58551C
3.26959,5.77905 3.48907,5.24573 3.51248,5.05341C 3.50577,4.80481 3.4686,4.54974 3.37167,4.32074C
3.30945,4.17371 3.22525,4.03473 3.12619,3.90955C 3.05661,3.82159 2.97842,3.73944 2.89175,3.66833C
2.43103,3.29034 2.50369,3.50317 2.68893,3.40485C 2.54819,3.40588 2.40576,3.41302 2.26852,3.44427C
2.21103,3.4574 1.88986,3.67981 2.08511,3.49609C 2.30716,3.28717 2.56421,3.11578 2.82678,2.96082L
3.31955,3.78888C 3.07086,3.93396 2.83575,4.10199 2.60477,4.27386C 2.57758,4.29413 2.65506,4.3302
2.68893,4.33093C 2.44836,4.34796 2.6445,4.81226 2.64972,5.05341C 2.5759,5.354 3.04163,4.57416 3.23727,4.33429C
3.44708,4.07709 3.6138,3.78088 3.73529,3.47198C 4.00925,2.51923 3.68005,0.710449 2.68893,0.688049C
1.76352,0.748108 1.10529,1.67914 0.408905,2.3468L 0,1.87567'/>
1.76352,0.748108 1.10529,1.67914 0.408905,2.3468L 0,1.87567'/>

<Path Canvas.Left='334.387' Canvas.Top='261.301' Fill='#67FFFFFF' Data='F1 M


0,1.65875C 0.696869,1.02808 1.34213,0.0608521 2.28003,0C 3.27115,0.0223999 3.60034,1.83118 3.32639,2.78394C
3.11957,3.30969 2.73251,3.74921 2.37503,4.18671C 2.32208,4.25153 2.20798,4.47424 2.24081,4.36536C
2.2381,4.2395 2.21954,4.11041 2.17108,3.99426C 1.88803,3.31567 2.11093,3.65485 2.28003,3.64288C 2.0029,3.63696
2.67123,3.24054 2.91064,3.10083L 3.384,3.94086C 3.01645,4.151 2.70169,4.53088 2.28003,4.56897C 1.97446,4.56268
1.62714,4.55023 1.37805,4.36536C 1.37805,3.6181 2.34262,3.19519 2.62881,2.50488C 2.81827,1.91803
2.89648,0.704224 2.28003,0.688049C 1.49789,0.729187 1.0062,1.60413 0.408905,2.12982L 0,1.65875'/>

<Path Canvas.Left='334.796' Canvas.Top='261.989' Fill='#B3FFFFFF' Data='F1 M


0,1.44177C 0.593109,0.923889 1.08484,0.0413818 1.87112,0C 2.48758,0.0161743 2.40936,1.22998 2.21991,1.81683C
1.93372,2.50714 0.969147,2.93005 0.969147,3.67731C 1.24167,3.82129 1.56296,3.87457 1.87112,3.88092C
2.29279,3.84283 2.60754,3.46295 2.9751,3.25281L 3.20447,3.67731L 3.43167,4.10376L 3.4205,4.10938C
2.92361,4.38129 2.43698,4.7821 1.87112,4.80707C 1.17377,4.76801 0.136292,4.37512 0.106415,3.67731C
0.153381,2.82336 1.15576,2.31042 1.52234,1.53778C 1.5654,1.4223 1.61166,1.30798 1.65152,1.19141C
1.67355,1.12695 1.69156,1.0611 1.70792,0.994934C 1.90915,0.181641 1.78229,0.662903 1.87112,0.687988C
1.23599,0.691956 0.89502,1.50092 0.410217,1.91125L 0.204468,1.67731L 0,1.44177'/>

<Path Canvas.Left='334.039' Canvas.Top='262.526' Fill='#67FFFFFF' Data='F1 M


1.16656,1.37512C 1.65137,0.964783 1.99234,0.155823 2.62747,0.151855C 2.32617,0.0973511 2.38568,0.714783
2.27869,1.00165C 1.91211,1.77429 0.909729,2.28723 0.862762,3.14117C 0.892639,3.83899 1.93011,4.23187
2.62747,4.27094C 3.19333,4.24597 3.67996,3.84515 4.17685,3.57324L 4.18802,3.56763L 4.64249,4.42065L
4.60895,4.43744C 3.96561,4.73151 3.33438,5.17175 2.62747,5.19702C 1.51846,5.11456 0.0415649,4.25244 0,3.14117C
0.06427,2.18774 0.897491,1.42383 1.58112,0.722595C 1.65967,0.547729 1.63098,0.290222 1.79318,0.188049C
2.0918,0 2.27457,0.835693 2.62747,0.839905C 2.69641,0.813965 2.50333,0.921204 2.45129,0.973328C
2.16391,1.26135 1.90118,1.5766 1.58762,1.83588L 1.16656,1.37512'/>

<Path Canvas.Left='333.176' Canvas.Top='262.377' Fill='#34FFFFFF' Data='F1 M


2.45038,1.98438C 2.82028,1.67853 3.88098,0.709717 3.49023,0.988403C 3.31818,0.986328 3.1387,0.929443
2.99945,0.828369C 2.21472,0.258911 2.60803,0.505676 2.44388,0.871094C 1.74619,1.53516 0.927551,2.32867
0.862762,3.28967C 0.904327,4.40094 2.38123,5.26306 3.49023,5.34552C 4.19714,5.32025 4.82837,4.88
5.47171,4.58594L 5.50525,4.56915L 5.95972,5.42218L 5.90381,5.45013C 5.09122,5.69897 4.33963,6.24402
3.49023,6.27161C 1.96561,6.14099 0.0545959,4.81891 0,3.28967C 0.0557556,2.52448 0.38092,1.72522
0.920959,1.1803C 1.15875,0.940308 1.80658,0.259705 1.74631,0.592102C 2.08981,0 2.80579,1.66632
3.49023,1.67645C 3.63046,1.65802 4.02829,1.52673 3.88687,1.52576C 3.43561,1.52271 3.23413,2.15051
2.88419,2.43542L 2.45038,1.98438'/>

<Path Canvas.Left='395.462' Canvas.Top='184.631' Fill='#18FFFFFF' Data='F1 M


2.41568,15.1037C 1.31152,12.8954 0,10.533 0.105377,8.06622C 0.189392,6.09912 1.4686,4.05804 3.12088,2.98724C
8.24686,0 15.2148,2.22858 20.8938,3.94556C 29.121,6.37976 37.132,10.0992 44.0641,15.1547L 43.1903,16.4434C
36.4215,11.5452 28.4005,8.35626 20.3515,6.11487C 15.1683,4.62628 8.89404,2.1817 4.22104,4.87323C
3.13663,5.57458 2.32138,6.86383 2.14236,8.14282C 1.84436,10.2718 2.70322,12.487 3.66461,14.4098L
2.41568,15.1037'/>

<Path Canvas.Left='397.306' Canvas.Top='186.813' Fill='#2FFFFFFF' Data='F1 M


1.82025,12.2281C 0.858856,10.3053 0,8.09009 0.298004,5.96112C 0.47702,4.68213 1.29227,3.39288 2.37668,2.69153C
7.04968,0 13.3239,2.44458 18.5071,3.93317C 26.5561,6.17456 34.5771,9.36346 41.346,14.2617L 40.4677,15.5464C
33.8577,10.8049 25.836,8.15643 17.9648,6.10248C 15.3017,5.37469 12.6468,4.57092 9.92273,4.12231C
7.79739,3.77228 5.35492,3.52277 3.47687,4.57751C 1.52966,5.82745 2.02017,9.43689 3.06918,11.5341L
1.82025,12.2281'/>

<Path Canvas.Left='398.828' Canvas.Top='190.336' Fill='#53FFFFFF' Data='F1 M


1.54709,8.01135C 0.508026,5.9339 0,2.30957 1.95477,1.05475C 3.83282,0 6.2753,0.249512 8.40063,0.599548C
11.1247,1.04816 13.7796,1.85193 16.4427,2.57971C 24.3139,4.63367 32.3356,7.2821 38.9456,12.0236L
38.5049,12.6644L 38.0631,13.3052L 38.0382,13.2866C 31.5898,8.70715 23.5851,6.61902 15.9004,4.74902C
13.2872,4.06836 10.6937,3.27203 8.02972,2.83014C 6.3934,2.55872 4.52975,2.18176 3.05493,2.94073C 1.992,3.9469
2.25214,5.96765 2.80139,7.32428L 2.17154,7.66437L 1.54709,8.01135'/>

<Path Canvas.Left='400.888' Canvas.Top='192.517' Fill='#2FFFFFFF' Data='F1 M


0.742126,5.14252C 0.194,3.7887 0,1.84869 0.995667,0.758972C 2.47049,0 4.33414,0.376953 5.97046,0.648376C
8.63446,1.09027 11.2279,1.8866 13.8411,2.56726C 21.5259,4.43726 29.5306,6.52539 35.9789,11.1048L
36.0038,11.1235L 35.1203,12.4052L 35.0457,12.3492C 28.7607,7.935 20.7907,6.42712 13.2988,4.73657C
9.60855,3.81915 5.86926,2.98535 2.09586,2.64496C 2.22012,2.56299 2.34314,2.47693 2.45163,2.375C
2.48297,2.34552 2.51337,2.31506 2.61743,2.19684C 3.02753,1.69183 2.80463,1.74451 2.80356,1.74408C
2.53955,1.64313 2.44153,2.19104 2.3428,2.45587C 2.10245,3.10059 2.00021,3.80896 2.02972,4.50598L
0.742126,5.14252'/>

<Path Canvas.Left='402.909' Canvas.Top='194.105' Fill='#18FFFFFF' Data='F1 M


0.00842285,2.91809C 0,2.44379 0.0231018,1.9621 0.131531,1.50031C 0.157135,1.39124 0.186096,1.2829
0.00842285,2.91809C 0,2.44379 0.0231018,1.9621 0.131531,1.50031C 0.157135,1.39124 0.186096,1.2829
0.218323,1.1756C 0.249451,1.07202 0.283722,0.969299 0.321503,0.867981C 0.35611,0.775146 0.393677,0.68335
0.435364,0.593445C 0.470947,0.516724 0.51178,0.442505 0.55304,0.368713C 0.73587,0.0415649 0.747314,0
0.794067,0.198059C 0.879883,0.561584 0.386353,0.85144 0.0745544,1.05707C 1.15195,1.51453 2.42377,1.09808
3.57825,1.29114C 6.18216,1.72656 8.71542,2.51172 11.2775,3.14868C 18.7694,4.83923 26.7393,6.34711
33.0244,10.7613L 33.099,10.8173L 32.2154,12.0989L 32.091,12.0057C 25.9619,7.75385 18.0385,6.83655
10.7352,5.31799C 8.49432,4.78558 6.28546,4.1109 4.02469,3.67065C 3.28555,3.52673 2.54108,3.40393
1.79224,3.32477C 1.61301,3.30585 1.43323,3.2926 1.25357,3.27856C 0.115112,3.18958 1.11761,2.9812
1.17471,2.94305C 1.72018,2.58563 2.24747,2.13049 2.55252,1.55414C 2.63559,1.39722 2.70276,1.22937
2.74124,1.05603C 2.77881,0.88678 2.49051,0.605896 2.35242,0.710693C 1.84265,1.09753 1.90869,2.06018
1.33151,2.33655L 1.02914,2.46637L 0.00842285,2.91809'/>

<Path Canvas.Left='351.466' Canvas.Top='241.478' Fill='#344D4A41' Data='F1 M


0,12.9303C 1.62814,10.7594 2.59155,8.08313 4.47549,6.13013C 5.8891,4.84857 7.56577,3.85101 9.2901,3.03412C
14.0585,0.983276 20.0102,0 24.8238,1.9422C 28.597,3.78986 33.1422,6.99451 33.3889,11.1885C 33.2286,15.7654
30.027,19.86 27.1714,23.4404L 26.6495,23.0729C 29.3697,19.5672 32.4614,15.6219 32.6469,11.1885C
32.4368,7.22638 28.1097,4.24219 24.5745,2.44073C 19.9366,0.493408 14.1127,1.44202 9.52097,3.49591C
7.86395,4.31244 6.25342,5.29736 4.8989,6.55347C 3.06485,8.48944 1.73843,10.8591 0.346924,13.1669L 0,12.9303'/>

<Path Canvas.Left='351.813' Canvas.Top='241.972' Fill='#674D4A41' Data='F1 M


0,12.6735C 1.3829,10.3823 2.71143,8.00287 4.55197,6.06006C 5.90649,4.80396 7.51703,3.81903 9.17404,3.0025C
13.7658,0.948608 19.5897,0 24.2276,1.94733C 27.7628,3.74878 32.0899,6.73297 32.3,10.6951C 32.1145,15.1285
29.0228,19.0738 26.3026,22.5795L 25.781,22.2121C 28.3683,18.784 31.3431,14.9846 31.558,10.6951C 31.389,6.96472
27.2765,4.19708 23.9783,2.44586C 19.5181,0.491455 13.8198,1.40936 9.40491,3.46423C 7.81488,4.2796
6.27081,5.25275 4.97534,6.48346C 3.18094,8.41553 1.81964,10.7116 0.346924,12.9102L 0,12.6735'/>

<Path Canvas.Left='352.16' Canvas.Top='242.463' Fill='#B34D4A41' Data='F1 M 0,12.4187C


1.46939,10.2255 2.83188,7.92639 4.62842,5.992C 5.92389,4.76129 7.46796,3.78815 9.05798,2.97278C
13.4728,0.917908 19.1711,0 23.6314,1.95441C 26.9296,3.70563 31.0421,6.47327 31.2111,10.2037C 30.9962,14.4932
28.0214,18.2925 25.4341,21.7206L 25.1734,21.537L 24.9128,21.3533L 24.9185,21.3458C 27.3734,18.0005
30.2192,14.3455 30.4691,10.2037C 30.3493,6.70496 26.4445,4.14923 23.3821,2.45294C 19.1017,0.489807
13.5264,1.38049 9.28888,3.43457C 7.76553,4.2478 6.2883,5.20996 5.05176,6.41534C 3.30026,8.34357
1.89749,10.5621 0.346802,12.6552L 0.173431,12.537L 0,12.4187'/>

<Path Canvas.Left='352.507' Canvas.Top='242.953' Fill='#674D4A41' Data='F1 M


0,12.1654C 1.55069,10.0723 2.95346,7.85376 4.70496,5.92554C 5.9415,4.72015 7.41873,3.758 8.94208,2.94476C
13.1796,0.890686 18.7549,0 23.0353,1.96313C 26.0977,3.65942 30.0025,6.21515 30.1223,9.71387C 29.8724,13.8557
27.0266,17.5107 24.5717,20.856L 24.566,20.8635L 24.0448,20.4962L 24.0617,20.4735C 26.385,17.2164
29.0877,13.7039 29.3803,9.71387C 29.3232,6.44702 25.614,4.09827 22.7861,2.46167C 18.6882,0.487488
13.2329,1.35547 9.17294,3.40649C 7.71582,4.21674 6.30606,5.16888 5.12833,6.34894C 3.42303,8.27313
1.97305,10.4099 0.347534,12.4019L 0,12.1654'/>

<Path Canvas.Left='352.854' Canvas.Top='243.44' Fill='#344D4A41' Data='F1 M 0,11.9144C


1.62552,9.92236 3.0755,7.78564 4.78079,5.86145C 5.95853,4.6814 7.36829,3.72925 8.82541,2.91901C
12.8854,0.867981 18.3407,0 22.4385,1.97418C 25.2664,3.61078 28.9757,5.95953 29.0328,9.22638C 28.7402,13.2164
26.0375,16.7289 23.7142,19.986L 23.6972,20.0087L 23.176,19.6413L 23.2043,19.6036C 25.3984,16.4373
27.944,13.063 28.2908,9.22638C 28.3258,6.19269 24.7844,4.04425 22.1893,2.47272C 18.277,0.485413 12.9383,1.3349
9.05627,3.3808C 7.66495,4.18701 6.32324,5.13007 5.20419,6.28479C 3.54688,8.20752 2.04199,10.2603
0.348602,12.1513L 0,11.9144'/>

<Path Canvas.Left='348.9' Canvas.Top='236.655' Fill='#345C5C5C' Data='F1 M


1.52966,17.3979C 0,11.7979 4.83112,4.78735 10.0254,2.19525C 14.4117,0.296692 19.5351,0 24.2758,0.607727C
28.1803,1.26941 31.7028,3.60797 34.8688,5.98706C 37.6928,8.36609 38.6076,12.7787 38.4552,16.4681C
37.9461,21.2475 35.7448,27.1149 31.3236,29.0002L 31.0986,28.6048C 35.3155,26.6357 37.3999,21.0445
37.9132,16.4189C 38.0764,12.9001 37.26,8.66095 34.5614,6.39691C 31.4628,4.08374 28.0211,1.79706
24.2056,1.16931C 19.5809,0.602905 14.5712,0.877136 10.3221,2.78851C 7.31464,4.33209 5.05054,7.24554
3.38821,10.189C 2.21463,12.267 1.36407,14.9207 2.0246,17.2434L 1.52966,17.3979'/>

<Path Canvas.Left='350.27' Canvas.Top='237.258' Fill='#675C5C5C' Data='F1 M


0.653931,16.6405C 0,14.3365 0.839783,11.6715 2.01755,9.58606C 3.67987,6.64264 5.94397,3.72919 8.95139,2.18561C
13.2005,0.274231 18.2103,0 22.8349,0.566406C 26.6505,1.19415 30.0921,3.48083 33.1907,5.79401C 35.8893,8.05804
36.7058,12.2972 36.5425,15.816C 36.0293,20.4416 33.9448,26.0328 29.7279,28.0019L 29.5061,27.6064C
33.5089,25.5474 35.4828,20.2382 36.0006,15.7667C 36.1739,12.4185 35.4568,8.35272 32.8833,6.20386C
29.8524,3.95605 26.4913,1.72101 22.7647,1.12799C 18.2563,0.601929 13.3594,0.855408 9.24799,2.77881C
6.38144,4.29901 4.21677,7.09198 2.64383,9.92993C 1.55856,11.888 0.621735,14.3006 1.14883,16.486L
0.653931,16.6405'/>

<Path Canvas.Left='350.892' Canvas.Top='237.86' Fill='#B35C5C5C' Data='F1 M


0.526764,15.8841C 0,13.7054 0.93515,11.2885 2.02176,9.328C 3.5947,6.49005 5.75937,3.69708 8.62592,2.17688C
12.7373,0.253479 17.6342,0 22.1427,0.526062C 25.8692,1.11908 29.2303,3.35413 32.2613,5.60193C 34.8348,7.75079
12.7373,0.253479 17.6342,0 22.1427,0.526062C 25.8692,1.11908 29.2303,3.35413 32.2613,5.60193C 34.8348,7.75079
35.5518,11.8166 35.3785,15.1648C 34.8607,19.6362 32.8868,24.9455 28.884,27.0045L 28.7743,26.8069L
28.6647,26.6088L 28.6731,26.6046C 32.4473,24.4498 34.3146,19.43 34.8366,15.1155C 35.0191,11.9376
34.4027,8.04523 31.9539,6.01172C 28.9908,3.82922 25.7101,1.64557 22.0725,1.08759C 17.6803,0.601013
12.8954,0.835144 8.92255,2.77014C 6.19916,4.2702 4.13168,6.93951 2.64798,9.67188C 1.65024,11.5093
0.643951,13.6738 1.02255,15.7301L 0.774231,15.8068L 0.526764,15.8841'/>

<Path Canvas.Left='351.536' Canvas.Top='238.461' Fill='#675C5C5C' Data='F1 M


0.378601,15.1291C 0,13.0728 1.00629,10.9083 2.00403,9.07086C 3.48773,6.3385 5.55521,3.66919 8.27859,2.16913C
12.2515,0.234131 17.0363,0 21.4285,0.486572C 25.0661,1.04456 28.3469,3.22821 31.3099,5.41071C 33.7588,7.44421
34.3752,11.3366 34.1927,14.5145C 33.6707,18.829 31.8033,23.8488 28.0292,26.0036L 28.0207,26.0078L
27.8017,25.6118L 27.827,25.5992C 31.3537,23.3398 33.1244,18.6204 33.6507,14.4652C 33.8417,11.4575
33.3274,7.73828 31.0025,5.82056C 28.1078,3.7027 24.9071,1.56934 21.3583,1.04816C 17.0826,0.599976
12.4088,0.816467 8.5752,2.76233C 5.70358,4.41846 3.5098,7.33704 2.1684,10.3685C 1.52252,11.8281
0.709625,13.3922 0.877533,14.9794L 0.378601,15.1291'/>

<Path Canvas.Left='352.246' Canvas.Top='239.061' Fill='#345C5C5C' Data='F1 M


0.167908,14.3795C 0,12.7922 0.812897,11.2281 1.45877,9.76849C 2.80017,6.73706 4.99396,3.81848 7.86557,2.16235C
11.6992,0.216492 16.373,0 20.6487,0.448181C 24.1974,0.96936 27.3981,3.10272 30.2929,5.22058C 32.6177,7.13831
33.1321,10.8575 32.9411,13.8652C 32.4147,18.0204 30.644,22.7398 27.1174,24.9992L 27.0921,25.0118L
26.873,24.6159L 26.9152,24.5948C 27.6656,24.0482 28.1379,23.1953 28.6985,22.4553C 30.5903,19.9581
31.9866,16.9215 32.3991,13.816C 32.5978,10.9783 32.187,7.43195 29.9855,5.63043C 27.1592,3.57703
24.0385,1.49286 20.5785,1.00977C 16.4193,0.598938 11.8556,0.799377 8.1622,2.75562C 5.19983,4.56262
2.9501,7.71442 1.78357,10.9824C 1.39832,12.0617 0.679932,13.0891 0.669861,14.235L 0.167908,14.3795'/>

<Path Canvas.Left='375.445' Canvas.Top='237.673' Fill='#34FFFFFF' Data='F1 M


0.0742798,0C 3.21741,1.12329 6.48233,2.41449 8.91788,4.69684C 11.2753,6.90601 12.9019,10.1898 13.1628,13.41C
13.3164,19.2955 9.74338,25.2823 5.4306,29.2902L 4.81262,28.5066C 9.03986,24.773 12.4554,19.05 12.4531,13.41C
12.2661,10.3286 10.8738,7.09979 8.63809,4.97101C 6.27005,2.71625 3.10052,1.38831 0,0.264038L 0.0742798,0'/>

<Path Canvas.Left='375.37' Canvas.Top='237.937' Fill='#67FFFFFF' Data='F1 M


0.0742493,0C 3.15698,1.11774 6.33755,2.4458 8.71234,4.70697C 10.9481,6.83575 12.3404,10.0646 12.5273,13.146C
12.5297,18.7859 9.11411,24.509 4.88687,28.2426L 4.27045,27.4565C 8.41269,24.0032 11.6613,18.5367
11.8177,13.146C 11.7116,10.382 10.6843,7.45734 8.83084,5.40411C 6.55069,2.87817 3.1976,1.4552 0,0.263977L
0.0742493,0'/>

<Path Canvas.Left='375.296' Canvas.Top='238.201' Fill='#B3FFFFFF' Data='F1 M


0.0743713,0C 3.26608,1.1889 6.62299,2.61188 8.90521,5.14014C 10.7586,7.19336 11.7859,10.118 11.8921,12.882C
11.7357,18.2727 8.48706,23.7393 4.34482,27.1926L 4.0372,26.7986L 3.72961,26.4043L 3.73715,26.3986C
7.79245,23.2343 10.8588,18.0156 11.1824,12.882C 11.146,10.246 10.3476,7.38568 8.6095,5.40356C 6.40591,2.89063
3.12152,1.45874 0,0.264221L 0.0372314,0.132019L 0.0743713,0'/>

<Path Canvas.Left='375.221' Canvas.Top='238.466' Fill='#67FFFFFF' Data='F1 M


0.074646,0C 3.19617,1.19452 6.48056,2.6264 8.68414,5.13934C 10.4222,7.12146 11.2207,9.98181 11.257,12.6178C
10.9334,17.7514 7.8671,22.97 3.8118,26.1344L 3.80426,26.1401L 3.189,25.3511L 3.21164,25.3342C 7.17935,22.4699
10.047,17.4857 10.5474,12.6178C 10.5787,10.2755 10.1143,7.71747 8.72659,5.83026C 6.68274,3.05066
3.21106,1.52643 0,0.264465L 0.074646,0'/>

<Path Name='Rectangle1' Canvas.Left='375.147' Canvas.Top='238.73' Fill='#34FFFFFF'


Data='F1 M 0.0749207,0C 3.28598,1.26196 6.75766,2.78619 8.80151,5.5658C 10.1892,7.453 10.6536,10.011
10.6223,12.3533C 10.1219,17.2212 7.25427,22.2054 3.28656,25.0697L 3.26392,25.0867L 2.64868,24.2978L
2.6864,24.2695C 6.56754,21.7168 9.22403,16.9473 9.91266,12.3533C 10.0096,10.1268 9.74622,7.65833
8.48349,5.8219C 6.56812,3.03632 3.1348,1.52991 0,0.264587L 0.0749207,0'/>

</Canvas>
</Canvas>
</Canvas>
</Canvas>
</Canvas>
</Window>

Vea también
BitmapCache
BitmapCacheBrush
CacheMode
Cómo: Usar un elemento almacenado en caché como pincel
Procedimiento para usar un elemento almacenado
en caché como pincel
23/10/2019 • 2 minutes to read • Edit Online

Use la BitmapCacheBrush clase para reutilizar un elemento almacenado en caché eficazmente. Para almacenar en
caché un elemento, crear una nueva instancia de la BitmapCache clase y se asigna a la propiedad del elemento
CacheMode propiedad.

Ejemplo
El ejemplo de código siguiente muestra cómo reutilizar un elemento almacenado en caché. El elemento
almacenado en caché es un Image control que muestra una imagen grande. El Image control se almacena en
caché como un mapa de bits mediante el uso de la BitmapCache clase y la memoria caché se reutiliza mediante la
asignación a un BitmapCacheBrush. El pincel se asigna al fondo de veinticinco botones para mostrar una
reutilización eficiente.

<Window x:Class="BitmapCacheBrushDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Height="300" Width="300" >
<Window.Resources>
<RichTextBox x:Key="cachedRichTextBox" >
<RichTextBox.CacheMode>
<BitmapCache EnableClearType="True" RenderAtScale="1" SnapsToDevicePixels="True" />
</RichTextBox.CacheMode>
</RichTextBox>

<BitmapCacheBrush x:Key="cachedRichTextBoxBrush" Target="{StaticResource cachedRichTextBox}">


<BitmapCacheBrush.BitmapCache>
<BitmapCache EnableClearType="False" RenderAtScale="0.4" SnapsToDevicePixels="False" />
</BitmapCacheBrush.BitmapCache>
</BitmapCacheBrush>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button1"
FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button2"
Grid.Column="1" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button3"
Grid.Column="2" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button4"
Grid.Column="3" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button5"
Grid.Column="4" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button6"
Grid.Row="1" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="1"
Name="button7" Grid.Row="1" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="2"
Name="button8" Grid.Row="1" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="3"
Name="button9" Grid.Row="1" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="4"
Name="button10" Grid.Row="1" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button11"
Grid.Row="2" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="1"
Name="button12" Grid.Row="2" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="2"
Name="button13" Grid.Row="2" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="3"
Name="button14" Grid.Row="2" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="4"
Name="button15" Grid.Row="2" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button16"
Grid.Row="3" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="1"
Name="button17" Grid.Row="3" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="2"
Name="button18" Grid.Row="3" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="3"
Name="button19" Grid.Row="3" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="4"
Name="button20" Grid.Row="3" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Name="button21"
Grid.Row="4" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="1"
Name="button22" Grid.Row="4" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="2"
Name="button23" Grid.Row="4" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="3"
Name="button24" Grid.Row="4" FontWeight="Bold" />
<Button Background="{StaticResource cachedRichTextBoxBrush}" Content="Button" Grid.Column="4"
Name="button25" Grid.Row="4" FontWeight="Bold" />
</Grid>
</Window>

Vea también
BitmapCache
BitmapCacheBrush
CacheMode
Cómo: Mejorar el rendimiento al almacenar en caché un elemento de la representación
Información general sobre gráficos 3D
23/10/2019 • 31 minutes to read • Edit Online

La funcionalidad 3D en Windows Presentation Foundation (WPF ) permite a los programadores dibujar,


transformar y animar gráficos 3D en el código de marcado y procedimientos. Los desarrolladores pueden
combinar gráficos en 2D y 3D para crear controles enriquecidos, proporcionar ilustraciones complejas de datos
o mejorar la experiencia del usuario de la interfaz de la aplicación. 3-d support en WPF no está diseñado para
proporcionar una plataforma de desarrollo de juegos completa. Este tema proporciona información general de
la funcionalidad 3D de la WPF sistema de gráficos.

3D en un contenedor 2D
Gráficos 3D contenidos en WPF se encapsula en un elemento, Viewport3D, que puede participar en la
estructura de elementos bidimensionales. El sistema de gráficos trata Viewport3D como elementos visuales
bidimensionales, como muchos otros elementos de WPF. Viewport3D funciona como una ventana, una
ventanilla, en una escena tridimensional. Más concretamente, es una superficie en la que se proyecta una
escena 3D.
En una aplicación de 2-D convencional, utilice Viewport3D como lo haría con cualquier otro elemento
contenedor, como Grid o Canvas. Aunque puede usar Viewport3D con otros objetos de dibujo 2D en el mismo
gráfico de escena, no puede interpenetrar objetos 2D y 3D en un Viewport3D. En este tema se centrará en cómo
dibujar gráficos en 3D dentro de la Viewport3D.

Espacio de coordenadas 3D
El WPF del sistema de coordenadas para gráficos 2D localiza el origen en la parte superior izquierda del área
de representación (que suele ser la pantalla). En el sistema 2D, los valores positivos del eje X se extienden hacia
la derecha, y los valores positivos del eje Y se extienden hacia abajo. En el sistema de coordenadas 3D, sin
embargo, el origen se encuentra en el centro del área de representación, con valores positivos del eje x hacia la
derecha pero valores positivos del eje y continuando hacia arriba en su lugar y los valores del eje z positivo
extienden hacia el exterior partiendo del origen , hacia el espectador.

Representaciones convencionales de los sistemas de coordenadas 2D y 3D


El espacio definido por estos ejes es el marco estático de referencia para los objetos 3D en WPF. Cuando se
generan modelos en este espacio y se crean luces y cámaras para verlos, es útil distinguir este marco estático de
referencia, o "espacio universal", del marco de referencia local creado para cada modelo al aplicarle
transformaciones. Recuerde también que los objetos del espacio universal podrían parecer completamente
diferentes, o incluso no verse en absoluto, dependiendo de la configuración de las luces y la cámara, pero que la
posición de la cámara no cambia la ubicación de los objetos en el espacio universal.

Cámaras y proyecciones
Los desarrolladores que trabajan en 2D están acostumbrados a colocar los elementos de dibujo primitivos en
una pantalla bidimensional. Al crear una escena 3D, es importante recordar que realmente está creando una
representación 2D de objetos 3D. Dado que una escena 3D tiene un aspecto diferente dependiendo de la
perspectiva del espectador, debe especificar ese punto de vista. La Camera clase le permite especificar este
punto de vista de una escena 3D.
Es otra manera de comprender cómo se representa una escena 3D en una superficie 2D en describir dicha
escena como una proyección sobre la superficie de visualización. El ProjectionCamera le permite especificar
proyecciones diferentes y sus propiedades para cambiar cómo el espectador ve los modelos 3D. Un
PerspectiveCamera especifica una proyección en escorzo de la escena. En otras palabras, el PerspectiveCamera
proporciona una perspectiva de punto de fuga. Puede especificar la posición de la cámara en el espacio de
coordenadas de la escena, la dirección y el campo de visión de la cámara y un vector que define la dirección de
"arriba" en la escena. El siguiente diagrama ilustra la PerspectiveCamerade proyección.
El NearPlaneDistance y FarPlaneDistance propiedades de ProjectionCamera limite el intervalo de proyección
de la cámara. Dado que las cámaras se pueden ubicar en cualquier parte de la escena, es posible situarlas
dentro de un modelo o muy cerca de él, con lo que resultaría difícil distinguir correctamente los objetos.
NearPlaneDistance le permite especificar una distancia mínima de la cámara más allá del cual no se dibujarán
objetos. Por el contrario, FarPlaneDistance le permite especificar una distancia desde la cámara más allá del cual
no se dibujarán objetos, lo que garantiza que los objetos demasiado lejos para ser reconocibles no se incluirán
en la escena.

Posición de la cámara
OrthographicCamera Especifica una proyección ortogonal de un modelo 3D en una superficie visual 2D. Al
igual que otras cámaras, especifica una posición, dirección de visualización y dirección "hacia arriba". A
diferencia de PerspectiveCamera, sin embargo, OrthographicCamera describe una proyección que no incluye la
perspectiva en escorzo. En otras palabras, OrthographicCamera describe un cuadro de vista cuyos lados son
paralelos, en lugar de uno cuyos lados convergen en un punto de la cámara. La siguiente imagen muestra el
mismo modelo visto con PerspectiveCamera y OrthographicCamera.

Proyecciones ortográfica y en perspectiva


En el código siguiente se muestran algunas configuraciones de cámara típicas.
// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();

// Specify where in the 3D scene the camera is.


myPCamera.Position = new Point3D(0, 0, 2);

// Specify the direction that the camera is pointing.


myPCamera.LookDirection = new Vector3D(0, 0, -1);

// Define camera's horizontal field of view in degrees.


myPCamera.FieldOfView = 60;

// Asign the camera to the viewport


myViewport3D.Camera = myPCamera;

' Defines the camera used to view the 3D object. In order to view the 3D object,
' the camera must be positioned and pointed such that the object is within view
' of the camera.
Dim myPCamera As New PerspectiveCamera()

' Specify where in the 3D scene the camera is.


myPCamera.Position = New Point3D(0, 0, 2)

' Specify the direction that the camera is pointing.


myPCamera.LookDirection = New Vector3D(0, 0, -1)

' Define camera's horizontal field of view in degrees.


myPCamera.FieldOfView = 60

' Asign the camera to the viewport


myViewport3D.Camera = myPCamera

Elementos primitivos de modelo y de malla


Model3D es la clase base abstracta que representa un objeto 3D genérico. Para crear una escena 3D, necesita
algunos objetos para ver y los objetos que componen el gráfico de escena se derivan de Model3D.
Actualmente, el WPF admite geometrías de modelado con GeometryModel3D. El Geometry propiedad de este
modelo toma una malla primitivo.
Para crear un modelo, comience por crear un elemento primitivo, o malla. Un tipo primitivo 3D es una colección
de vértices que constituyen una sola entidad 3D. La mayoría de los sistemas 3D proporcionan elementos
primitivos modelados en la figura cerrada más simple: un triángulo definido por tres vértices. Dado que los tres
puntos de un triángulo son coplanares, puede seguir agregando triángulos para modelar formas más
complejas, denominadas mallas.
El WPF sistema 3D proporciona actualmente las MeshGeometry3D (clase), que le permite especificar cualquier
geometría; actualmente no hace 3D primitivas de soporte técnico predefinido como esferas y formas cúbicas.
Empezar a crear un MeshGeometry3D especificando una lista de vértices de triángulos como su Positions
propiedad. Cada vértice se especifica como un Point3D. (En Lenguaje Lenguaje XAML (Extensible Application
Markup Language), especifique esta propiedad como una lista de números agrupados en ternas, que
representan las coordenadas de cada vértice). Según cuál sea la geometría, la malla puede estar compuesta de
muchos triángulos, algunos de los cuales compartirán las mismas esquinas (vértices). WPF necesita
información sobre qué triángulos comparten qué vértices para dibujar la malla correctamente. Esta información
se proporciona especificando una lista de índices de triángulos con la TriangleIndices propiedad. Esta lista
especifica el orden en que se especifican los puntos en el Positions lista determinarán un triángulo.
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0"
Normals="0 0 1 0 0 1 0 0 1 0 0 1"
TextureCoordinates="0 1 1 1 0 0 1 0 "
TriangleIndices="0 1 2 1 3 2" />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<!-- Translate the plane. -->
<GeometryModel3D.Transform>
<TranslateTransform3D
OffsetX="2" OffsetY="0" OffsetZ="-1" >
</TranslateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>

En el ejemplo anterior, el Positions lista especifica ocho vértices para definir una malla en forma de cubo. El
TriangleIndices propiedad especifica una lista de doce grupos de tres índices. Cada número en la lista hace
referencia a un desplazamiento en el Positions lista. Por ejemplo, los tres primeros vértices especificados por el
Positions lista son (1,1,0), (0,1,0) y (0,0,0). Los tres primeros índices especificados por el TriangleIndices lista son
0, 2 y 1, que corresponden a la primera, en tercer lugar y segundo puntos en el Positions lista. Como resultado,
el primer triángulo que constituye el modelo del cubo se creará de (1,1,0) a (0,1,0) y a (0,0,0), y los once
triángulos restantes se determinarán de igual forma.
Puede seguir definiendo el modelo especificando valores para el Normals y TextureCoordinates propiedades.
Para representar la superficie del modelo, el sistema de gráficos necesita información sobre en qué dirección
mira la superficie de cualquier triángulo dado. Utiliza esta información para realizar los cálculos de iluminación
del modelo: las superficies que miran directamente hacia una fuente de luz parecen más luminosas que las que
tienen un ángulo que las oculta de la luz. Aunque WPF puede determinar los vectores normales
predeterminados utilizando las coordenadas de posición, también es posible especificar vectores normales
diferentes para crear un aspecto más aproximado de las superficies curvas.
El TextureCoordinates propiedad especifica una colección de Pointque indica el sistema de gráficos cómo
asignar las coordenadas que determinan cómo trazar una textura en los vértices de la malla.
TextureCoordinates se especifican como un valor comprendido entre 0 y 1, ambos incluidos. Igual que con el
Normals propiedad, el sistema de gráficos puede calcular las coordenadas de textura de predeterminado, pero
decide establecer coordenadas de textura diferentes para controlar la asignación de una textura que incluya
parte de un patrón repetitivo, por ejemplo. Encontrará más información sobre coordenadas de textura en los
temas siguientes o en el SDK de Managed Direct3D.
En el ejemplo siguiente se muestra cómo crear una cara del modelo del cubo en código de procedimiento.
Observe que puede dibujar el cubo completo como un solo objeto GeometryModel3D; en este ejemplo se
dibuja la cara del cubo como un modelo distinto a fin de aplicar después texturas independientes a cada cara.

MeshGeometry3D side1Plane = new MeshGeometry3D();

Private side1Plane As New MeshGeometry3D()


side1Plane.Positions.Add(new Point3D(-0.5, -0.5, -0.5));
side1Plane.Positions.Add(new Point3D(-0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, -0.5, -0.5));
side1Plane.Positions.Add(new Point3D(-0.5, -0.5, -0.5));

side1Plane.TriangleIndices.Add(0);
side1Plane.TriangleIndices.Add(1);
side1Plane.TriangleIndices.Add(2);
side1Plane.TriangleIndices.Add(3);
side1Plane.TriangleIndices.Add(4);
side1Plane.TriangleIndices.Add(5);

side1Plane.Normals.Add(new Vector3D(0, 0, -1));


side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));

side1Plane.TextureCoordinates.Add(new Point(1, 0));


side1Plane.TextureCoordinates.Add(new Point(1, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 0));
side1Plane.TextureCoordinates.Add(new Point(1, 0));

side1Plane.Positions.Add(New Point3D(-0.5, -0.5, -0.5))


side1Plane.Positions.Add(New Point3D(-0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, -0.5, -0.5))
side1Plane.Positions.Add(New Point3D(-0.5, -0.5, -0.5))

side1Plane.TriangleIndices.Add(0)
side1Plane.TriangleIndices.Add(1)
side1Plane.TriangleIndices.Add(2)
side1Plane.TriangleIndices.Add(3)
side1Plane.TriangleIndices.Add(4)
side1Plane.TriangleIndices.Add(5)

side1Plane.Normals.Add(New Vector3D(0, 0, -1))


side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))

side1Plane.TextureCoordinates.Add(New Point(1, 0))


side1Plane.TextureCoordinates.Add(New Point(1, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 0))
side1Plane.TextureCoordinates.Add(New Point(1, 0))

Aplicación de materiales al modelo


Para que una malla parezca un objeto tridimensional, debe tener una textura aplicada que cubra la superficie
definida por sus vértices y triángulos, de manera que se pueda iluminar y proyectar por la cámara. En 2D, se
usa el Brush clase para aplicar colores, patrones, degradados u otro contenido visual a las áreas de la pantalla.
La apariencia de los objetos 3D, sin embargo, es una función del modelo de iluminación, no solo del color o del
patrón que se les aplica. Los objetos reales reflejan la luz de manera distinta según la calidad de su superficie:
las superficies satinadas y brillantes no tienen el mismo aspecto que las superficies ásperas o mates, y algunos
objetos parecen absorber la luz, mientras que otros la emiten. Puede aplicar los mismos pinceles a los objetos
3D que se pueden aplicar a objetos 2D, pero no puede aplicar directamente.
Para definir las características de la superficie de un modelo, WPF usa el Material clase abstracta. Las subclases
concretas de Material determinan algunas de las características del aspecto de la superficie del modelo y,
además, cada una de ellas proporciona una propiedad Brush a la que puede pasar SolidColorBrush, TileBrush o
VisualBrush.
DiffuseMaterial Especifica que el pincel se aplicará al modelo como si estuviera iluminado con una luz
difusa. Utilizar DiffuseMaterial más es similar al uso de pinceles directamente en los modelos de 2D; las
superficies del modelo no reflejan la luz como si brillasen.
SpecularMaterial Especifica que el pincel se aplicará al modelo como si fuera de la superficie del modelo
dura o brillante, capaz de reflejar la iluminación. Puede establecer el grado al que la textura sugerirá esta
cualidad, o "brillo", especificando un valor para el SpecularPower propiedad.
EmissiveMaterial le permite especificar que la textura se aplicará como si el modelo estuviera emitiendo
luz igual al color del pincel. Esto no convierte el modelo en una luz; sin embargo, participará de manera
diferente en el sombreado que si se aplica textura con DiffuseMaterial o SpecularMaterial.
Para mejorar el rendimiento, la ocultas de un GeometryModel3D (esas caras que están fuera de la vista porque
están en el lado opuesto del modelo de la cámara) se seleccionan de la escena. Para especificar un Material para
aplicar a la cara oculta de un modelo como un plano, establezca el modelo BackMaterial propiedad.
Para lograr algunas cualidades de la superficie, como el brillo o los efectos de reflejo, puede ser conveniente
aplicar sucesivamente varios pinceles diferentes a un modelo. Puede aplicar y reutilizar varios materiales
mediante la MaterialGroup clase. Los elementos secundarios de MaterialGroup se aplican del primero al último
en varias pasadas de representación.
Ejemplos de código siguientes muestran cómo aplicar un color sólido y un dibujo como pinceles a los modelos
3D.

<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<DrawingBrush x:Key="patternBrush" Viewport="0,0,0.1,0.1" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Geometry="M0,0.1 L0.1,0 1,0.9, 0.9,1z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.9,0 L1,0.1 0.1,1 0,0.9z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.25,0.25 L0.5,0.125 0.75,0.25 0.5,0.5z"
Brush="#FFFF00" />
<GeometryDrawing Geometry="M0.25,0.75 L0.5,0.875 0.75,0.75 0.5,0.5z"
Brush="Black" />
<GeometryDrawing Geometry="M0.25,0.75 L0.125,0.5 0.25,0.25 0.5,0.5z"
Brush="#FF0000" />
<GeometryDrawing Geometry="M0.75,0.25 L0.875,0.5 0.75,0.75 0.5,0.5z"
Brush="MediumBlue" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>

DiffuseMaterial side5Material = new DiffuseMaterial((Brush)Application.Current.Resources["patternBrush"]);

Dim side5Material As New DiffuseMaterial(CType(Application.Current.Resources("patternBrush"), Brush))

Iluminación de la escena
Las luces en los gráficos 3D es ¿qué luces en el mundo real: permiten ver las superficies. Más concretamente,
las luces determinan qué parte de una escena se incluye en la proyección. Los objetos de luz en WPF crean
gran variedad de efectos de luz y sombra y siguen el modelo de comportamiento de diversas luces del mundo
real. Debe incluir por lo menos una luz en la escena, pues de lo contrario no habrá ningún modelo visible.
Las luces siguientes se derivan de la clase base Light:
AmbientLight: Proporciona iluminación de ambiente que ilumina todos los objetos uniformemente,
independientemente de su ubicación u orientación.
DirectionalLight: Ilumina como una fuente de luz distante. Las luces direccionales tienen un Direction
especificado como un Vector3D, pero ninguna ubicación concreta.
PointLight: Ilumina como una fuente de luz cercana. Las luces puntuales tienen posición y emiten la luz
desde esa posición. Los objetos de la escena se iluminan dependiendo de su posición y distancia con
respecto a la luz. PointLightBase expone un Range propiedad, que determina una distancia más allá del
cual no se iluminará los modelos por la luz. PointLight también expone propiedades de atenuación que
determinan cómo disminuye la intensidad de la luz con la distancia. Puede especificar interpolaciones
constantes, lineales o cuadráticas para la atenuación de la luz.
SpotLight: Se hereda de PointLight. Los focos de luz iluminan como las luces puntuales, y tienen
posición y dirección. Proyectan la luz en un área cónica establecido por InnerConeAngle y
OuterConeAngle propiedades, especificadas en grados.
Las luces son Model3D objetos, por lo que puede transformar y animar propiedades de la luz, incluida la
posición, color, dirección y rango.
<ModelVisual3D.Content>
<AmbientLight Color="#333333" />
</ModelVisual3D.Content>

DirectionalLight myDirLight = new DirectionalLight();

Private myDirLight As New DirectionalLight()

myDirLight.Color = Colors.White;
myDirLight.Direction = new Vector3D(-3, -4, -5);

myDirLight.Color = Colors.White
myDirLight.Direction = New Vector3D(-3, -4, -5)

modelGroup.Children.Add(myDirLight);

modelGroup.Children.Add(myDirLight)

Transformación de modelos
Al crear modelos, estos tienen una ubicación determinada en la escena. Para mover esos modelos por la escena,
girarlos o cambiar su tamaño, no es práctico cambiar los vértices que definen los propios modelos. En lugar de
ello, al igual que en 2D, se aplican transformaciones a los modelos.
Cada objeto de modelo tiene un Transform propiedad con el que puede mover, reorientar o cambiar el tamaño
del modelo. Al aplicar una transformación, en realidad lo que se hace es desplazar todos los puntos del modelo
según un vector o valor especificado por la transformación. Es decir, se transforma el espacio de coordenadas
en el que se ha definido el modelo ("espacio del modelo"), pero no se cambian los valores que constituyen la
geometría del modelo en el sistema de coordenadas de la escena completa ("espacio universal").
Para más información acerca de la transformación de modelos, consulte Información general sobre
transformaciones de modelos 3D.

Animación de modelos
La implementación 3-D en WPF utiliza el mismo sistema de control de tiempo y animación que los gráficos 2D.
En otras palabras, para animar una escena 3D, se animan las propiedades de sus modelos. Es posible animar
directamente las propiedades de los elementos primitivos, pero suele ser más fácil animar las transformaciones
que cambian la posición o el aspecto de los modelos. Dado que se pueden aplicar transformaciones a
Model3DGroup objetos, así como los modelos individuales, es posible aplicar un conjunto de animaciones a un
elemento secundario de un Model3DGroup y otro conjunto de animaciones a un grupo de objetos secundarios.
También puede lograr gran variedad de efectos visuales animando las propiedades de iluminación de la escena.
Finalmente, si lo desea, puede animar la propia proyección, animando la posición de la cámara o el campo de
visión. Para información general sobre el sistema de control de tiempo y animación de WPF, consulte los temas
Información general sobre animaciones, Información general sobre objetos Storyboard y Información general
sobre objetos Freezable.
Para animar un objeto en WPF, se crea una escala de tiempo, se define una animación (que, en realidad, es un
cambio de algún valor de propiedad a lo largo del tiempo) y se especifica la propiedad a la que aplicar la
animación. Dado que todos los objetos en una escena 3D son elementos secundarios de Viewport3D, las
propiedades de destino de cualquier animación que desea aplicar a la escena son propiedades de las
propiedades de Viewport3D.
Supongamos que desea hacer que un modelo parezca tambalearse en su lugar. Podría optar por aplicar un
RotateTransform3D al modelo y animar el eje de giro de un vector a otro. En el ejemplo de código siguiente se
muestra cómo aplicar Vector3DAnimation a la propiedad Axis de la propiedad Rotation3D de la
transformación, suponiendo que RotateTransform3D es una de las diversas transformaciones aplicadas al
modelo con TransformGroup.

//Define a rotation
RotateTransform3D myRotateTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0),
1));

'Define a rotation
Dim myRotateTransform As New RotateTransform3D(New AxisAngleRotation3D(New Vector3D(0, 1, 0), 1))

Vector3DAnimation myVectorAnimation = new Vector3DAnimation(new Vector3D(-1, -1, -1), new


Duration(TimeSpan.FromMilliseconds(5000)));
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever;

Dim myVectorAnimation As New Vector3DAnimation(New Vector3D(-1, -1, -1), New


Duration(TimeSpan.FromMilliseconds(5000)))
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever

myRotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AxisProperty, myVectorAnimation);

myRotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AxisProperty, myVectorAnimation)

//Add transformation to the model


cube1TransformGroup.Children.Add(myRotateTransform);

'Add transformation to the model


cube1TransformGroup.Children.Add(myRotateTransform)

Incorporación de contenido 3D a la ventana


Para representar la escena, agregue modelos y luces a un Model3DGroup, a continuación, establezca el
Model3DGroup como el Content de un ModelVisual3D. Agregar el ModelVisual3D a la Children colección de
la Viewport3D. Agregue cámaras a la Viewport3D estableciendo su Camera propiedad.
Por último, agregue el Viewport3D a la ventana. Cuando el Viewport3D se incluye como el contenido de un
elemento de diseño, como Canvas, especifique el tamaño de la Viewport3D estableciendo su Height y Width
propiedades (se hereda de FrameworkElement).

<UserControl x:Class="HostingWpfUserControlInWf.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
>

<Grid>

<!-- Place a Label control at the top of the view. -->


<Label
HorizontalAlignment="Center"
TextBlock.TextAlignment="Center"
FontSize="20"
Foreground="Red"
Content="Model: Cone"/>

<!-- Viewport3D is the rendering surface. -->


<Viewport3D Name="myViewport" >

<!-- Add a camera. -->


<Viewport3D.Camera>
<PerspectiveCamera
FarPlaneDistance="20"
LookDirection="0,0,1"
UpDirection="0,1,0"
NearPlaneDistance="1"
Position="0,0,-3"
FieldOfView="45" />
</Viewport3D.Camera>

<!-- Add models. -->


<Viewport3D.Children>

<ModelVisual3D>
<ModelVisual3D.Content>

<Model3DGroup >
<Model3DGroup.Children>

<!-- Lights, MeshGeometry3D and DiffuseMaterial objects are added to the ModelVisual3D. -
->
<DirectionalLight Color="#FFFFFFFF" Direction="3,-4,5" />

<!-- Define a red cone. -->


<GeometryModel3D>

<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="0.293893 -0.5 0.404509 0.475528 -0.5 0.154509 0 0.5 0 0.475528 -0.5 0.154509 0 0.5 0 0
0.5 0 0.475528 -0.5 0.154509 0.475528 -0.5 -0.154509 0 0.5 0 0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0
0.475528 -0.5 -0.154509 0.293893 -0.5 -0.404509 0 0.5 0 0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0
0.293893 -0.5 -0.404509 0 -0.5 -0.5 0 0.5 0 0 -0.5 -0.5 0 0.5 0 0 0.5 0 0 -0.5 -0.5 -0.293893 -0.5 -
0.404509 0 0.5 0 -0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 -0.293893 -0.5 -0.404509 -0.475528 -0.5 -
0.154509 0 0.5 0 -0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 -0.154509 -0.475528 -0.5
0.154509 0 0.5 0 -0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 0.154509 -0.293892 -0.5
0.404509 0 0.5 0 -0.293892 -0.5 0.404509 0 0.5 0 0 0.5 0 -0.293892 -0.5 0.404509 0 -0.5 0.5 0 0.5 0
0 -0.5 0.5 0 0.5 0 0 0.5 0 0 -0.5 0.5 0.293893 -0.5 0.404509 0 0.5 0 0.293893 -0.5 0.404509 0 0.5 0
0 0.5 0 "
Normals="0.7236065,0.4472139,0.5257313 0.2763934,0.4472138,0.8506507 0.5308242,0.4294462,0.7306172
0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 0.5308242,0.4294462,0.7306172
0.2763934,0.4472138,0.8506507 -0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 -
0.2763934,0.4472138,0.8506507 -0.5308242,0.4294462,0.7306172 0,0.4294458,0.9030925 -
0.2763934,0.4472138,0.8506507 -0.7236065,0.4472139,0.5257313 -0.5308242,0.4294462,0.7306172 -
0.7236065,0.4472139,0.5257313 -0.858892,0.429446,0.279071 -0.5308242,0.4294462,0.7306172 -
0.7236065,0.4472139,0.5257313 -0.8944269,0.4472139,0 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0
-0.858892,0.429446,-0.279071 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.7236065,0.4472139,-
0.5257313 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.5308242,0.4294462,-0.7306172
-0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.2763934,0.4472138,-0.8506507 -
0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 -
0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0.2763934,0.4472138,-0.8506507
0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.5308249,0.4294459,-0.7306169 0,0.4294458,-
0.9030925 0.2763934,0.4472138,-0.8506507 0.7236068,0.4472141,-0.5257306 0.5308249,0.4294459,-0.7306169
0.7236068,0.4472141,-0.5257306 0.8588922,0.4294461,-0.27907 0.5308249,0.4294459,-0.7306169
0.7236068,0.4472141,-0.5257306 0.8944269,0.4472139,0 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0
0.858892,0.429446,0.279071 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0
0.7236065,0.4472139,0.5257313 0.858892,0.429446,0.279071 0.7236065,0.4472139,0.5257313
0.5308242,0.4294462,0.7306172 0.858892,0.429446,0.279071 " TriangleIndices="0 1 2 3 4 5
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 " />
</GeometryModel3D.Geometry>

<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush
Color="Red"
Opacity="1.0"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>

</GeometryModel3D>

</Model3DGroup.Children>
</Model3DGroup>

</ModelVisual3D.Content>

</ModelVisual3D>

</Viewport3D.Children>

</Viewport3D>
</Grid>

</UserControl>

Vea también
Viewport3D
PerspectiveCamera
DirectionalLight
Material
Información general sobre transformaciones de modelos 3D
Maximizar el rendimiento de representación 3D en WPF
Temas "Cómo..."
Información general sobre formas y dibujo básico en WPF
Pintar con imágenes, dibujos y elementos visuales
Información general sobre transformaciones de
modelos 3D
20/02/2020 • 23 minutes to read • Edit Online

En este tema se describe cómo aplicar las transformaciones a los modelos 3D del sistema de gráficos de Windows
Presentation Foundation (WPF ). Las transformaciones permiten que el desarrollador cambie la posición y el
tamaño de los modelos, así como que los vuelva a orientar sin cambiar los valores base que los definen.

Espacio de coordenadas 3D
el contenido de gráficos 3D de Windows Presentation Foundation (WPF ) se encapsula en un elemento,
Viewport3D, que puede participar en la estructura de elementos bidimensionales. El sistema de gráficos trata los
objetos Viewport3D como elementos visuales bidimensionales, al igual que ocurre con muchos otros elementos
de Windows Presentation Foundation (WPF ). Viewport3D funciona como ventana (una ventanilla) de una escena
tridimensional. Más concretamente, es una superficie en la que se proyecta una escena 3D. Aunque puede usar
Viewport3D con otros objetos de dibujo 2D en el mismo gráfico de escena, no puede interpenetrar objetos 2D y
3D en un Viewport3D. El elemento Viewport3D contiene el espacio de coordenadas descrito en la siguiente
descripción.
El sistema de coordenadas de Windows Presentation Foundation (WPF ) para gráficos 2D localiza el origen en la
parte superior izquierda de la superficie de representación (que suele ser la pantalla). En el sistema 2D, los valores
positivos del eje X se extienden hacia la derecha, y los valores positivos del eje Y se extienden hacia abajo. En el
sistema de coordenadas 3D, sin embargo, el origen se encuentra en el centro del área de la pantalla, los valores
positivos del eje X se extienden hacia la derecha, los del eje Y, hacia arriba (no hacia abajo) y los del eje Z, hacia el
exterior partiendo del origen; es decir, hacia el lector.

Coordinación de la comparación de sistemas


El espacio definido por estos ejes es el marco estático de referencia para los objetos 3D en Windows Presentation
Foundation (WPF ). Cuando se generan modelos en este espacio y se crean luces y cámaras para verlos, es útil
distinguir este marco estático de referencia, o "espacio universal", del marco de referencia local creado para cada
modelo al aplicarle transformaciones. Recuerde también que los objetos del espacio universal podrían parecer
completamente diferentes, o incluso no verse en absoluto, dependiendo de la configuración de las luces y la
cámara, pero que la posición de la cámara no cambia la ubicación de los objetos en el espacio universal.

Transformación de modelos
Al crear modelos, estos tienen una ubicación determinada en la escena. Para mover esos modelos por la escena,
girarlos o cambiar su tamaño, no es práctico cambiar los vértices que definen los propios modelos. En lugar de
ello, al igual que en 2D, se aplican transformaciones a los modelos.
Cada objeto de modelo tiene una propiedad Transform con la que puede desplace, vuelva a orientar o cambiar el
tamaño del modelo. Al aplicar una transformación, en realidad lo que se hace es desplazar todos los puntos del
modelo según un vector o valor especificado por la transformación. Es decir, se transforma el espacio de
coordenadas en el que se ha definido el modelo ("espacio del modelo"), pero no se cambian los valores que
constituyen la geometría del modelo en el sistema de coordenadas de la escena completa ("espacio universal").

Transformaciones de la traslación
las transformaciones 3D heredan de la clase base abstracta Transform3D; entre ellas se incluyen las clases de
transformación afín TranslateTransform3D, ScaleTransform3Dy RotateTransform3D. El Windows Presentation
Foundation (WPF ) sistema 3D también proporciona una clase MatrixTransform3D que le permite especificar las
mismas transformaciones en operaciones de matriz más concisas.
TranslateTransform3D mueve todos los puntos del Model3D en la dirección del vector de desplazamiento que
especifique con las propiedades OffsetX, OffsetYy OffsetZ. Por ejemplo, dado un vértice de un cubo en (2,2,2), un
vector de desplazamiento de (0,1.6,1) movería el vértice (2,2,2) a (2,3.6,3). El vértice del cubo sigue siendo (2,2,2)
en el espacio del modelo, pero ahora dicho espacio ha cambiado su relación al espacio universal, de tal forma que
(2,2,2) en el espacio del modelo es (2,3.6,3) en el espacio universal.

Traslación con desplazamiento


En los ejemplos de código siguientes se muestra cómo aplicar una traslación.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="600" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="600" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the light cast in the scene. Without light, the
3D object cannot be seen. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. The OffsetX property is
animated
in the Storyboard below. -->
<GeometryModel3D.Transform>
<TranslateTransform3D x:Name="myTranslateTransform3D" OffsetX="0" OffsetY="0" OffsetZ="0"
/>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
<!-- Trigger the TranslateTransform3D animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the OffsetX property of the TranslateTransform3D. -->
<DoubleAnimation
Storyboard.TargetName="myTranslateTransform3D"
Storyboard.TargetProperty="OffsetX"
To="-0.8"
AutoReverse="True" RepeatBehavior="Forever" />

<!-- If you want to animate OffsetY and/or OffsetZ, create similar DoubleAnimations
respectively. -->

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Transformaciones de escala
ScaleTransform3D cambia la escala del modelo en un vector de escala especificado con referencia a un punto
central. Especifique una escala uniforme, que escala el modelo mediante el mismo valor en los ejes X, Y y Z, para
cambiar proporcionalmente el tamaño del modelo. Por ejemplo, si se establecen las propiedades ScaleX, ScaleYy
ScaleZ de la transformación en 0,5 a la mitad del tamaño del modelo; al establecer las mismas propiedades en 2,
se duplica su escala en los tres ejes.

Ejemplo de ScaleVector
Si se especifica una transformación de escala no uniforme (una transformación de escala cuyos valores X, Y y Z no
son iguales), se puede provocar el estiramiento o la contracción del modelo en una o dos dimensiones sin afectar
el resto. Por ejemplo, si se establece ScaleX en 1, ScaleY en 2 y ScaleZ en 1, el modelo transformado se duplicará
en alto, pero permanecerá sin cambios a lo largo de los ejes X y Z.
De forma predeterminada, ScaleTransform3D provoca la expansión o contracción de los vértices en el origen
(0,0,0). Sin, embargo, si el modelo que desea transformar no se dibuja partiendo del origen, al escalar el modelo a
partir del origen, no se escalará el modelo "en contexto". En su lugar, cuando se multiplican los vértices del modelo
por el vector de escala, la operación de la escala tendrá el efecto de trasladar y escalar el modelo.

Ejemplo de ScaleCenter
Para escalar un modelo "en contexto", especifique el centro del modelo mediante el establecimiento de las
propiedades ScaleTransform3D's CenterX, CenterYy CenterZ. Esto garantiza que el sistema de gráficos escale el
espacio del modelo y, a continuación, lo traduce al centro en el Point3Despecificado. A la inversa, si ha creado el
modelo en el origen y especifica un punto central diferente, espere ver el modelo trasladado fuera del origen.

Transformaciones de giro
Puede girar un modelo 3D de varias maneras diferentes. Una transformación de giro típica especifica un eje y un
ángulo de giro alrededor de ese eje. La clase RotateTransform3D permite definir un Rotation3D con su propiedad
Rotation. A continuación, especifique Axis y Angle propiedades en el Rotation3D, en este caso un
AxisAngleRotation3D, para definir la transformación. En los ejemplos siguientes se gira un modelo 60 grados
sobre el eje Y.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- Two ModelVisual3D define the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

<!-- The Transform specifies how to transform the 3D object. The properties of the
Rotation object are animated causing the 3D object to rotate and "wobble" (see
Storyboard below).-->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="myAngleRotation" Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

<!-- Trigger the rotation animation when the 3D object loads. -->
<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the Angle property of the AxisAngleRotation3D


making the 3D object rotate from -60 degrees to 60 degrees. -->
<DoubleAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Angle"
From="-60" To="60" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>

<!-- This animation animates the Axis property of the AxisAngleRotation3D


making the 3D wobble as it rotates. -->
<Vector3DAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Axis"
From="0,3,0" To="1,0,1" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>

</Viewbox>
</DockPanel>
</Page>

Nota: 3D de Windows Presentation Foundation (WPF ) es un sistema a la derecha, es decir, un valor angular
positivo de un giro tiene como resultado un giro en el sentido contrario a las agujas del reloj sobre el eje.
Los giros angulares de eje suponen una rotación sobre el origen si no se especifica un valor para las propiedades
CenterX, CenterYy CenterZ en RotateTransform3D. Como ocurre con el escalado, es útil recordar que el giro
transforma el espacio de coordenadas de todo el modelo. Si el modelo no se creó sobre el origen, o se ha
trasladado previamente, el giro podría "pivotar" sobre el origen en lugar de girar en contexto.

Rotation con nuevo centro especificado


Para girar el modelo "en contexto", especifique el centro real del modelo como el centro de giro. Puesto que la
geometría se suele modelar en el origen, la mayor parte de las veces puede obtener el resultado esperado de un
conjunto de transformaciones si primero ajusta el tamaño del modelo (lo escala), después establece su orientación
(lo gira) y, finalmente, lo mueve a la ubicación deseada (lo traslada).

Ejemplo de giro
Los giros angulares sobre el eje funcionan bien para las transformaciones estáticas y algunas animaciones. Sin
embargo, considere girar un modelo de cubo 60 grados sobre el eje X y luego 45 grados sobre el eje Z. Puede
describir esta transformación como dos transformaciones afines discretas o como matriz. Sin embargo, quizá sea
difícil animar un giro definido así de forma continua. Aunque las posiciones inicial y final del modelo, calculadas
mediante cualquiera de los enfoque son las mismas, varía el cálculo de las posiciones intermedias tomadas por el
modelo. Los cuaterniones representan una forma alternativa de calcular la interpolación entre el inicio y el fin de
un giro.
Un cuaternión representa un eje en el espacio 3D y un giro alrededor de ese eje. Por ejemplo, un cuaternión
podría representar un eje (1,1,2) y un giro de 50 grados. La capacidad de los cuaterniones al definir los giros
procede de las dos operaciones que puede realizar en ellos: composición e interpolación. La composición de dos
cuaterniones aplicada a una geometría significa "girar la geometría sobre el eje2 mediante giro2, después girarla
sobre el eje1 mediante giro1". Utilizando la composición, puede combinar los dos giros en la geometría para
obtener un solo cuaternión que representa el resultado. Puesto que la interpolación del cuaternión puede calcular
una ruta de acceso continuada y correcta desde un eje y la orientación a otro, puede interpolar desde el cuaternión
original al compuesto para lograr una transición continuada de uno a otro, permitiéndole animar la
transformación. En el caso de los modelos que desea animar, puede especificar un Quaternion de destino para la
rotación mediante el uso de un QuaternionRotation3D para la propiedad Rotation.

Uso de colecciones de transformaciones


Al crear una escena, es normal aplicar más de una transformación a un modelo. Agregue transformaciones a la
colección de Children de la clase Transform3DGroup para agrupar las transformaciones para que se apliquen a
varios modelos de la escena. A menudo es conveniente volver a usar una transformación en varios grupos
diferentes, de la misma forma que puede volver a usar un modelo aplicando un conjunto diferente de
transformaciones a cada instancia. Observe que el orden en el que las transformaciones se agregan a la colección
es importante: las transformaciones de la colección se aplican de la primera a la última.

Animación de transformaciones
La implementación 3-D en Windows Presentation Foundation (WPF ) utiliza el mismo sistema de control de
tiempo y animación que los gráficos 2D. En otras palabras, para animar una escena 3D, se animan las propiedades
de sus modelos. Es posible animar directamente las propiedades de los elementos primitivos, pero suele ser más
fácil animar las transformaciones que cambian la posición o el aspecto de los modelos. Dado que las
transformaciones se pueden aplicar a los objetos de Model3DGroup, así como a los modelos individuales, es
posible aplicar un conjunto de animaciones a los elementos secundarios de un Model3Dgroup y otro conjunto de
animaciones a un grupo de objetos. Para información general sobre el sistema de control de tiempo y animación
de Windows Presentation Foundation (WPF ), consulte los temas Información general sobre animaciones e
Información general sobre objetos Storyboard.
Para animar un objeto en Windows Presentation Foundation (WPF ), se crea una escala de tiempo, se define una
animación (que, en realidad, es un cambio de algún valor de propiedad a lo largo del tiempo) y se especifica la
propiedad a la que aplicar la animación. Esta propiedad debe ser una propiedad de FrameworkElement. Dado que
todos los objetos de una escena 3D son elementos secundarios de Viewport3D, las propiedades de destino de
cualquier animación que desea aplicar a la escena son propiedades de propiedades de Viewport3D. Es importante
obtener la ruta de acceso de la propiedad de la animación correctamente, ya que la sintaxis puede ser prolija.
Suponga que desea girar un objeto en contexto, pero también aplicar un movimiento oscilante para que se vean
más partes del objeto. Podría aplicar RotateTransform3D al modelo y animar el eje de giro de un vector a otro. En
el ejemplo de código siguiente se muestra cómo aplicar un Vector3DAnimation a la propiedad AXIS del
Rotation3D de la transformación, suponiendo que el RotateTransform3D sea una de las diversas transformaciones
aplicadas al modelo con un TransformGroup.
//Define a rotation
RotateTransform3D myRotateTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0),
1));

'Define a rotation
Dim myRotateTransform As New RotateTransform3D(New AxisAngleRotation3D(New Vector3D(0, 1, 0), 1))

Vector3DAnimation myVectorAnimation = new Vector3DAnimation(new Vector3D(-1, -1, -1), new


Duration(TimeSpan.FromMilliseconds(5000)));
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever;

Dim myVectorAnimation As New Vector3DAnimation(New Vector3D(-1, -1, -1), New


Duration(TimeSpan.FromMilliseconds(5000)))
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever

Utilice una sintaxis similar para que otras propiedades de la transformación muevan o escalen el objeto. Por
ejemplo, puede aplicar un Point3DAnimation a la propiedad ScaleCenter de una transformación de escala para
hacer que un modelo distorsione suavemente su forma.
Aunque los ejemplos anteriores transforman las propiedades de GeometryModel3D, también es posible
transformar las propiedades de otros modelos de la escena. Animando traslaciones aplicadas a objetos Light, por
ejemplo, puede crear luz en movimiento y efectos de sombra que pueden cambiar el aspecto de los modelos
espectacularmente.
Puesto que las cámaras también son modelos, igualmente se pueden transformar las propiedades de la cámara.
Aunque puede cambiar el aspecto de la escena transformando la ubicación de la cámara o las distancias de los
planos (de hecho, transformando toda la proyección de la escena), tenga en cuenta que muchos de los efectos
obtenidos de esta forma quizá no tengan tanto "sentido visual" para el lector como las transformaciones aplicadas
a la ubicación o posición de los modelos de la escena.

Consulte también
Información general sobre gráficos 3D
Información general sobre transformaciones
Ejemplo de transformaciones 2D
Maximizar el rendimiento de representación 3D en
WPF
03/02/2020 • 10 minutes to read • Edit Online

Al usar el Windows Presentation Foundation (WPF ) para compilar controles 3D e incluir escenas 3D en las
aplicaciones, es importante tener en cuenta la optimización del rendimiento. En este tema se proporciona una lista
de las clases y propiedades 3D que tienen implicaciones de rendimiento para la aplicación, junto con
recomendaciones para optimizar el rendimiento cuando se usan.
En este tema se da por supuesto un conocimiento avanzado de Windows Presentation Foundation (WPF )
características 3D. Las sugerencias de este documento se aplican a "nivel de representación 2", que se define
aproximadamente como hardware que admite el sombreador de píxeles versión 2,0 y la versión 2,0 del
sombreador de vértices. Para obtener más información, consulte niveles de representación de gráficos.

Impacto en el rendimiento: alto


PROPIEDAD RECOMENDACIÓN

Brush Velocidad del pincel (más rápido a más lenta):

SolidColorBrush

LinearGradientBrush

ImageBrush

DrawingBrush (en caché)

VisualBrush (en caché)

RadialGradientBrush

DrawingBrush (no almacenado en caché)

VisualBrush (no almacenado en caché)

ClipToBoundsProperty Establezca Viewport3D.ClipToBounds en false siempre que


no necesite Windows Presentation Foundation (WPF) recortar
explícitamente el contenido de una Viewport3D al rectángulo
Viewport3D's. Windows Presentation Foundation (WPF) el
recorte antialias puede ser muy lento y ClipToBounds está
habilitado (lento) de forma predeterminada en Viewport3D.

IsHitTestVisible Establezca Viewport3D.IsHitTestVisible en false siempre


que no necesite Windows Presentation Foundation (WPF) para
considerar el contenido de un Viewport3D al realizar la prueba
de posicionamiento del mouse. La prueba de posicionamiento
de contenido 3D se realiza en el software y puede ser lenta
con mallas grandes. de forma predeterminada, IsHitTestVisible
está habilitado (lento) en Viewport3D.
PROPIEDAD RECOMENDACIÓN

GeometryModel3D Cree modelos diferentes solo cuando requieran materiales o


transformaciones diferentes. De lo contrario, intente fusionar
muchas instancias de GeometryModel3D con los mismos
materiales y transformaciones en algunas instancias de
GeometryModel3D y MeshGeometry3D más grandes.

MeshGeometry3D Animación de malla: cambiar los vértices individuales de una


malla en cada fotograma: no siempre es eficaz en Windows
Presentation Foundation (WPF). Para minimizar el impacto en
el rendimiento de las notificaciones de cambios cuando se
modifica cada vértice, Desasocie la malla del árbol visual antes
de realizar la modificación por vértice. Una vez que se haya
modificado la malla, vuelva a adjuntarla al árbol visual. Además,
intente minimizar el tamaño de las mallas que se animarán de
esta manera.

suavizado de contorno 3D Para aumentar la velocidad de representación, deshabilite el


muestreo múltiple en un Viewport3D estableciendo la
propiedad adjunta EdgeMode en Aliased . De forma
predeterminada, el suavizado de contorno 3D está habilitado
en Windows con 4 muestras por píxel.

Texto El texto en directo de una escena 3D (en vivo porque está en


un DrawingBrush o VisualBrush) puede ser lento. Intente usar
imágenes del texto en su lugar (a través de
RenderTargetBitmap) a menos que el texto cambie.

TileBrush Si debe usar un VisualBrush o un DrawingBrush en una escena


3D porque el contenido del pincel no es estático, intente
almacenar en caché el pincel (estableciendo la propiedad
adjunta CachingHint en Cache ). Establezca los umbrales de
invalidación de escala mínima y máxima (con las propiedades
adjuntas CacheInvalidationThresholdMinimum y
CacheInvalidationThresholdMaximum) para que los pinceles
almacenados en caché no se vuelvan a generar con demasiada
frecuencia, manteniendo el nivel de calidad deseado. De forma
predeterminada, DrawingBrush y VisualBrush no se almacenan
en caché, lo que significa que cada vez que se debe volver a
representar algo pintado con el pincel, todo el contenido del
pincel se debe volver a representar en una superficie
intermedia.

BitmapEffect BitmapEffect fuerza la representación de todo el contenido


afectado sin aceleración de hardware. Para obtener el mejor
rendimiento, no utilice BitmapEffect.

Impacto en el rendimiento: medio


PROPIEDAD RECOMENDACIÓN

MeshGeometry3D Cuando una malla se define como triángulos colindantes con


vértices compartidos y esos vértices tienen la misma posición,
normales y coordenadas de textura, defina cada vértice
compartido solo una vez y, a continuación, defina los
triángulos por índice con TriangleIndices.
PROPIEDAD RECOMENDACIÓN

ImageBrush Intente minimizar los tamaños de textura cuando tenga un


control explícito sobre el tamaño (cuando esté usando un
RenderTargetBitmap y/o un ImageBrush). Tenga en cuenta que
las texturas de resolución inferior pueden reducir la calidad
visual, así que intente encontrar el equilibrio adecuado entre
calidad y rendimiento.

Opacidad Al representar contenido 3D translúcido (como reflexiones),


use las propiedades de opacidad de los pinceles o materiales
(a través de Opacity o Color) en lugar de crear un Viewport3D
translúcido independiente estableciendo
Viewport3D.Opacity en un valor menor que 1.

Viewport3D Minimice el número de objetos de Viewport3D que está


usando en una escena. Coloque muchos modelos 3D en el
mismo Viewport3D en lugar de crear instancias de
Viewport3D independientes para cada modelo.

Freezable Normalmente, es beneficioso reutilizar MeshGeometry3D,


GeometryModel3D, pinceles y materiales. Todos son
multiprimarios, ya que se derivan de Freezable .

Freezable Llame al método Freeze en elementos inmovilizables cuando


sus propiedades permanezcan sin cambios en la aplicación. La
inmovilización puede reducir el espacio de trabajo y aumentar
la velocidad.

Brush Use ImageBrush en lugar de VisualBrush o DrawingBrush


cuando el contenido del pincel no cambie. el contenido 2D se
puede convertir en un Image a través de RenderTargetBitmap
y, después, se usa en un ImageBrush.

BackMaterial No use BackMaterial a menos que realmente necesite ver las


caras trasvueltas de la GeometryModel3D.

Light Velocidad ligera (más rápida a más lenta):

AmbientLight

DirectionalLight

PointLight

SpotLight

MeshGeometry3D Intente mantener los tamaños de malla en estos límites:

Positions: 20.001 Point3D instancias

TriangleIndices: 60.003 Int32 instancias


PROPIEDAD RECOMENDACIÓN

Material Velocidad del material (más rápida a más lenta):

EmissiveMaterial

DiffuseMaterial

SpecularMaterial

Brush Windows Presentation Foundation (WPF) 3D no deja de


participar en los pinceles invisibles (pinceles de ambiente
negros, pinceles claros, etc.) de una manera coherente.
Considere la posibilidad de omitirlos de la escena.

MaterialGroup Cada Material en un MaterialGroup produce otro paso de


representación, por lo que incluir muchos materiales, incluso
materiales sencillos, puede aumentar drásticamente las
demandas de relleno en la GPU. Minimice el número de
materiales en el MaterialGroup.

Impacto en el rendimiento: bajo


PROPIEDAD RECOMENDACIÓN

Transform3DGroup Cuando no necesite animación o enlace de datos, en lugar de


utilizar un grupo de transformación que contenga varias
transformaciones, utilice un solo MatrixTransform3D,
estableciendo que sea el producto de todas las
transformaciones que, de otro modo, existen de forma
independiente en el grupo de transformación.

Light Minimice el número de luces de la escena. Demasiadas luces


en una escena forzarán Windows Presentation Foundation
(WPF) a revertir a la representación de software. Los límites
son aproximadamente 110 objetos DirectionalLight, 70
PointLight objetos o 40 SpotLight objetos.

ModelVisual3D Separe los objetos móviles de los objetos estáticos


colocándolos en instancias de ModelVisual3D independientes.
ModelVisual3D es "pesado" que GeometryModel3D porque
almacena en caché los límites transformados.
GeometryModel3D está optimizado para ser un modelo;
ModelVisual3D está optimizado para ser un nodo de escena.
Use ModelVisual3D para colocar instancias compartidas de
GeometryModel3D en la escena.

Light Minimice el número de veces que cambia el número de luces


de la escena. Cada cambio de recuento ligero fuerza una
regeneración y recompilación del sombreador a menos que la
configuración haya existido anteriormente (y, por tanto, su
sombreador se almacenó en caché).

Ligero Las luces negras no estarán visibles, pero se agregarán al


tiempo de representación; considere la posibilidad de
omitirlos.
PROPIEDAD RECOMENDACIÓN

MeshGeometry3D Para minimizar el tiempo de construcción de colecciones


grandes en Windows Presentation Foundation (WPF), como
un MeshGeometry3D's Positions, Normals,
TextureCoordinatesy TriangleIndices, ajuste el tamaño de las
colecciones antes del rellenado de valores. Si es posible, pase a
las estructuras de datos rellenados previamente de los
constructores de colecciones como matrices o listas.

Consulte también
Información general sobre gráficos 3D
Temas "Cómo..." de gráficos 3D
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección muestran cómo usar gráficos 3D en Windows Presentation Foundation (WPF )
aplicaciones.

En esta sección
Crear una escena 3D
Aplicar un dibujo a un modelo 3D
Aplicar material a la parte anterior y posterior de un objeto 3D
Aplicar material emisor a un objeto tridimensional
Transformar la escala de un modelo 3D
Aplicar varias transformaciones a un modelo 3D
Animar traslaciones 3D
Animar un giro 3D mediante Storyboards
Animar un giro 3D mediante Rotation3DAnimation
Animar un giro 3D mediante cuaterniones
Animar un giro 3D mediante fotogramas clave (Rotation3DAnimationUsingKeyFrames)
Animar un giro 3D mediante fotogramas clave (QuaternionAnimationUsingKeyFrames)
Animar la posición y la dirección de una cámara en una escena 3D
Animar la posición y la dirección de una cámara mediante fotogramas clave
Animar propiedades de material en una escena 3D
Hacer una prueba de posicionamiento en Viewport3D
Comprobar la igualdad y la desigualdad de estructuras Test Point4D

Referencia
Viewport3D
PerspectiveCamera
DirectionalLight
Material

Secciones relacionadas
Gráficos y multimedia
Procedimiento Crear una escena 3D
23/10/2019 • 7 minutes to read • Edit Online

En este ejemplo se muestra cómo crear un objeto 3D que parece una hoja de papel que se ha girado plana. Un
Viewport3D junto con los siguientes componentes se usan para crear esta escena 3D sencilla:
Se crea una cámara mediante un PerspectiveCamera. La cámara especifica qué parte de la escena 3D es
visible.
Se crea una malla para especificar la forma del objeto 3D (hoja de papel) mediante el Geometry propiedad
de GeometryModel3D.
Se especifica el material que se mostrará en la superficie del objeto (degradado lineal en este ejemplo)
mediante el Material propiedad de GeometryModel3D.
Se crea una luz para destacar del objeto mediante DirectionalLight.

Ejemplo
El código siguiente muestra cómo crear una escena 3D en XAML.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D ClipToBounds="True" Width="150" Height="150" Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the light cast in the scene. Without light, the 3D
object cannot be seen. Also, the direction of the lights affect shadowing. If desired,
you can create multiple lights with different colors that shine from different directions. --
>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifies the shape of the 3D plane. In this sample, a flat sheet is
created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the 3D object. In this sample a linear
gradient
covers the surface of the 3D object.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

<!-- Apply a transform to the object. In this sample, a rotation transform is applied,
rendering the
3D object rotated. -->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Ejemplo
El código siguiente muestra cómo crear la misma escena 3D en el código de procedimiento.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace SDKSample
{
public partial class Basic3DShapeExample : Page
{
public Basic3DShapeExample()
{

// Declare scene objects.


Viewport3D myViewport3D = new Viewport3D();
Model3DGroup myModel3DGroup = new Model3DGroup();
GeometryModel3D myGeometryModel = new GeometryModel3D();
ModelVisual3D myModelVisual3D = new ModelVisual3D();
// Defines the camera used to view the 3D object. In order to view the 3D object,
// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();

// Specify where in the 3D scene the camera is.


myPCamera.Position = new Point3D(0, 0, 2);

// Specify the direction that the camera is pointing.


myPCamera.LookDirection = new Vector3D(0, 0, -1);

// Define camera's horizontal field of view in degrees.


myPCamera.FieldOfView = 60;

// Asign the camera to the viewport


myViewport3D.Camera = myPCamera;
// Define the lights cast in the scene. Without light, the 3D object cannot
// be seen. Note: to illuminate an object from additional directions, create
// additional lights.
DirectionalLight myDirectionalLight = new DirectionalLight();
myDirectionalLight.Color = Colors.White;
myDirectionalLight.Direction = new Vector3D(-0.61, -0.5, -0.61);

myModel3DGroup.Children.Add(myDirectionalLight);

// The geometry specifes the shape of the 3D plane. In this sample, a flat sheet
// is created.
MeshGeometry3D myMeshGeometry3D = new MeshGeometry3D();

// Create a collection of normal vectors for the MeshGeometry3D.


Vector3DCollection myNormalCollection = new Vector3DCollection();
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myMeshGeometry3D.Normals = myNormalCollection;

// Create a collection of vertex positions for the MeshGeometry3D.


Point3DCollection myPositionCollection = new Point3DCollection();
myPositionCollection.Add(new Point3D(-0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(-0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(-0.5, -0.5, 0.5));
myMeshGeometry3D.Positions = myPositionCollection;

// Create a collection of texture coordinates for the MeshGeometry3D.


PointCollection myTextureCoordinatesCollection = new PointCollection();
myTextureCoordinatesCollection.Add(new Point(0, 0));
myTextureCoordinatesCollection.Add(new Point(1, 0));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myTextureCoordinatesCollection.Add(new Point(0, 1));
myTextureCoordinatesCollection.Add(new Point(0, 0));
myMeshGeometry3D.TextureCoordinates = myTextureCoordinatesCollection;

// Create a collection of triangle indices for the MeshGeometry3D.


Int32Collection myTriangleIndicesCollection = new Int32Collection();
myTriangleIndicesCollection.Add(0);
myTriangleIndicesCollection.Add(1);
myTriangleIndicesCollection.Add(2);
myTriangleIndicesCollection.Add(3);
myTriangleIndicesCollection.Add(4);
myTriangleIndicesCollection.Add(5);
myMeshGeometry3D.TriangleIndices = myTriangleIndicesCollection;

// Apply the mesh to the geometry model.


// Apply the mesh to the geometry model.
myGeometryModel.Geometry = myMeshGeometry3D;

// The material specifies the material applied to the 3D object. In this sample a
// linear gradient covers the surface of the 3D object.

// Create a horizontal linear gradient with four stops.


LinearGradientBrush myHorizontalGradient = new LinearGradientBrush();
myHorizontalGradient.StartPoint = new Point(0, 0.5);
myHorizontalGradient.EndPoint = new Point(1, 0.5);
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));

// Define material and apply to the mesh geometries.


DiffuseMaterial myMaterial = new DiffuseMaterial(myHorizontalGradient);
myGeometryModel.Material = myMaterial;

// Apply a transform to the object. In this sample, a rotation transform is applied,


// rendering the 3D object rotated.
RotateTransform3D myRotateTransform3D = new RotateTransform3D();
AxisAngleRotation3D myAxisAngleRotation3d = new AxisAngleRotation3D();
myAxisAngleRotation3d.Axis = new Vector3D(0,3,0);
myAxisAngleRotation3d.Angle = 40;
myRotateTransform3D.Rotation = myAxisAngleRotation3d;
myGeometryModel.Transform = myRotateTransform3D;

// Add the geometry model to the model group.


myModel3DGroup.Children.Add(myGeometryModel);

// Add the group of models to the ModelVisual3d.


myModelVisual3D.Content = myModel3DGroup;

//
myViewport3D.Children.Add(myModelVisual3D);

// Apply the viewport to the page so it will be rendered.


this.Content = myViewport3D;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Media3D

Namespace SDKSample
Partial Public Class Basic3DShapeExample
Inherits Page
Public Sub New()

' Declare scene objects.


Dim myViewport3D As New Viewport3D()
Dim myModel3DGroup As New Model3DGroup()
Dim myGeometryModel As New GeometryModel3D()
Dim myModelVisual3D As New ModelVisual3D()
' Defines the camera used to view the 3D object. In order to view the 3D object,
' the camera must be positioned and pointed such that the object is within view
' of the camera.
Dim myPCamera As New PerspectiveCamera()

' Specify where in the 3D scene the camera is.


myPCamera.Position = New Point3D(0, 0, 2)

' Specify the direction that the camera is pointing.


' Specify the direction that the camera is pointing.
myPCamera.LookDirection = New Vector3D(0, 0, -1)

' Define camera's horizontal field of view in degrees.


myPCamera.FieldOfView = 60

' Asign the camera to the viewport


myViewport3D.Camera = myPCamera
' Define the lights cast in the scene. Without light, the 3D object cannot
' be seen. Note: to illuminate an object from additional directions, create
' additional lights.
Dim myDirectionalLight As New DirectionalLight()
myDirectionalLight.Color = Colors.White
myDirectionalLight.Direction = New Vector3D(-0.61, -0.5, -0.61)

myModel3DGroup.Children.Add(myDirectionalLight)

' The geometry specifes the shape of the 3D plane. In this sample, a flat sheet
' is created.
Dim myMeshGeometry3D As New MeshGeometry3D()

' Create a collection of normal vectors for the MeshGeometry3D.


Dim myNormalCollection As New Vector3DCollection()
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myMeshGeometry3D.Normals = myNormalCollection

' Create a collection of vertex positions for the MeshGeometry3D.


Dim myPositionCollection As New Point3DCollection()
myPositionCollection.Add(New Point3D(-0.5, -0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, -0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(-0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(-0.5, -0.5, 0.5))
myMeshGeometry3D.Positions = myPositionCollection

' Create a collection of texture coordinates for the MeshGeometry3D.


Dim myTextureCoordinatesCollection As New PointCollection()
myTextureCoordinatesCollection.Add(New Point(0, 0))
myTextureCoordinatesCollection.Add(New Point(1, 0))
myTextureCoordinatesCollection.Add(New Point(1, 1))
myTextureCoordinatesCollection.Add(New Point(1, 1))
myTextureCoordinatesCollection.Add(New Point(0, 1))
myTextureCoordinatesCollection.Add(New Point(0, 0))
myMeshGeometry3D.TextureCoordinates = myTextureCoordinatesCollection

' Create a collection of triangle indices for the MeshGeometry3D.


Dim myTriangleIndicesCollection As New Int32Collection()
myTriangleIndicesCollection.Add(0)
myTriangleIndicesCollection.Add(1)
myTriangleIndicesCollection.Add(2)
myTriangleIndicesCollection.Add(3)
myTriangleIndicesCollection.Add(4)
myTriangleIndicesCollection.Add(5)
myMeshGeometry3D.TriangleIndices = myTriangleIndicesCollection

' Apply the mesh to the geometry model.


myGeometryModel.Geometry = myMeshGeometry3D

' The material specifies the material applied to the 3D object. In this sample a
' linear gradient covers the surface of the 3D object.

' Create a horizontal linear gradient with four stops.


Dim myHorizontalGradient As New LinearGradientBrush()
myHorizontalGradient.StartPoint = New Point(0, 0.5)
myHorizontalGradient.StartPoint = New Point(0, 0.5)
myHorizontalGradient.EndPoint = New Point(1, 0.5)
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Yellow, 0.0))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Red, 0.25))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Blue, 0.75))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.LimeGreen, 1.0))

' Define material and apply to the mesh geometries.


Dim myMaterial As New DiffuseMaterial(myHorizontalGradient)
myGeometryModel.Material = myMaterial

' Apply a transform to the object. In this sample, a rotation transform is applied,
' rendering the 3D object rotated.
Dim myRotateTransform3D As New RotateTransform3D()
Dim myAxisAngleRotation3d As New AxisAngleRotation3D()
myAxisAngleRotation3d.Axis = New Vector3D(0,3,0)
myAxisAngleRotation3d.Angle = 40
myRotateTransform3D.Rotation = myAxisAngleRotation3d
myGeometryModel.Transform = myRotateTransform3D

' Add the geometry model to the model group.


myModel3DGroup.Children.Add(myGeometryModel)

' Add the group of models to the ModelVisual3d.


myModelVisual3D.Content = myModel3DGroup

'
myViewport3D.Children.Add(myModelVisual3D)

' Apply the viewport to the page so it will be rendered.


Me.Content = myViewport3D
End Sub
End Class
End Namespace

Vea también
Información general sobre gráficos 3D
Cómo: Aplicar un dibujo a un modelo 3D
04/11/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un DrawingBrush como Material aplicado a un modelo 3D.
En el código siguiente se define un DrawingGroup como contenido de un DrawingBrush. El DrawingBrush se
establece como la propiedad Brush de la DiffuseMaterial que se aplica a un plano 3D.

NOTE
A menudo es conveniente definir objetos y valores complejos como el dibujo siguiente como recursos que se pueden volver a
usar y simplificar el código. Vea recursos XAML para obtener más información.

<!-- The material specifies the material applied to the 3D object. In this sample a tiled drawing
covers the surface of the 3D object.-->
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<DrawingBrush Viewport="0,0,0.1,0.1" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Geometry="M0,0.1 L0.1,0 1,0.9, 0.9,1z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.9,0 L1,0.1 0.1,1 0,0.9z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.25,0.25 L0.5,0.125 0.75,0.25 0.5,0.5z"
Brush="#FFFF00" />
<GeometryDrawing Geometry="M0.25,0.75 L0.5,0.875 0.75,0.75 0.5,0.5z"
Brush="Black" />
<GeometryDrawing Geometry="M0.25,0.75 L0.125,0.5 0.25,0.25 0.5,0.5z"
Brush="#FF0000" />
<GeometryDrawing Geometry="M0.75,0.25 L0.875,0.5 0.75,0.75 0.5,0.5z"
Brush="MediumBlue" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>

Ejemplo
En el código siguiente se muestra el ejemplo completo.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D ClipToBounds="True" Width="150" Height="150" Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<Viewport3D.Camera>
<PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the light cast in the scene. Without light, the 3D
object cannot be seen. Also, the direction of the lights affect shadowing. If desired,
you can create multiple lights with different colors that shine from different directions. --
>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifies the shape of the 3D plane. In this sample, a flat sheet is
created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>
<!-- The material specifies the material applied to the 3D object. In this sample a tiled
drawing
covers the surface of the 3D object.-->
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<DrawingBrush Viewport="0,0,0.1,0.1" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Geometry="M0,0.1 L0.1,0 1,0.9, 0.9,1z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.9,0 L1,0.1 0.1,1 0,0.9z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.25,0.25 L0.5,0.125 0.75,0.25 0.5,0.5z"
Brush="#FFFF00" />
<GeometryDrawing Geometry="M0.25,0.75 L0.5,0.875 0.75,0.75 0.5,0.5z"
Brush="Black" />
<GeometryDrawing Geometry="M0.25,0.75 L0.125,0.5 0.25,0.25 0.5,0.5z"
Brush="#FF0000" />
<GeometryDrawing Geometry="M0.75,0.25 L0.875,0.5 0.75,0.75 0.5,0.5z"
Brush="MediumBlue" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<!-- Apply a transform to the object. In this sample, a rotation transform is applied,
rendering the
3D object rotated. -->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Vea también
Recursos XAML
Crear una escena 3D
Información general sobre objetos Drawing
Información general sobre gráficos 3D
Procedimiento Aplicar material a la parte anterior y
posterior de un objeto 3D
23/10/2019 • 2 minutes to read • Edit Online

El ejemplo siguiente muestra cómo aplicar un Material objeto a la parte frontal y posterior de un 3D y animar el
objeto para mostrar ambos lados del objeto. El Material propiedad de un GeometryModel3D se usa para aplicar
un color rojo Brush a la parte frontal del objeto y el BackMaterial propiedad de la GeometryModel3D se usa para
aplicar un azul Brush a la parte posterior del objeto. El código siguiente muestra la aplicación de los materiales en
el objeto:

<!-- This material is applied to the front of the 3D object (red side).-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Red"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

<!-- This material is applied to the back of the 3D object (blue side).-->
<GeometryModel3D.BackMaterial>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Blue"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.BackMaterial>

Ejemplo
El código siguiente muestra el ejemplo completo.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- Two ModelVisual3D define the lights cast in the scene. Without light, the
<!-- Two ModelVisual3D define the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>
<!-- This material is applied to the front of the 3D object (red side).-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Red"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

<!-- This material is applied to the back of the 3D object (blue side).-->
<GeometryModel3D.BackMaterial>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Blue"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.BackMaterial>
<!-- The Transform specifies how to transform the 3D object. The properties of the
Rotation object are animated causing the 3D object to rotate (see Storyboard below).--
>
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="myAngleRotation" Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

<!-- Trigger the rotation animation when the 3D object loads. This animation is used to show
both sides of the 3D object. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the Angle property of the AxisAngleRotation3D


<!-- This animation animates the Angle property of the AxisAngleRotation3D
making the 3D object rotate from -0 degrees to 360 degrees. -->
<DoubleAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Angle"
From="0" To="360" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Vea también
Crear una escena 3D
Información general sobre gráficos 3D
Animar propiedades de material en una escena 3D
Aplicar material emisor a un objeto tridimensional
Procedimiento Aplicar material emisor a un objeto
3D
23/10/2019 • 10 minutes to read • Edit Online

El ejemplo siguiente muestra cómo usar EmissiveMaterial para agregar color a un Material existente igual que el
color de pincel de EmissiveMaterial. El código siguiente muestra DiffuseMaterial y EmissiveMaterial aplicados en
combinación para agregar azul a la apariencia de DiffuseMaterial.

<!-- The material applied to the 3D object is made up of a DiffuseMaterial (gradient brush) with
an EmissiveMaterial layered on top (blue SolidColorBrush). The EmissiveMaterial adds blue to the
gradient. -->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
<EmissiveMaterial>
<EmissiveMaterial.Brush>
<SolidColorBrush x:Name="mySolidColorBrush" Color="Blue" />
</EmissiveMaterial.Brush>
</EmissiveMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

En el código de procedimientos:
// The material property of GeometryModel3D specifies the material applied to the 3D object.
// In this sample the material applied to the 3D object is made up of two materials layered
// on top of each other - a DiffuseMaterial (gradient brush) with an EmissiveMaterial
// layered on top (blue SolidColorBrush). The EmmisiveMaterial alters the appearance of
// the gradient toward blue.

// Create a horizontal linear gradient with four stops.


LinearGradientBrush myHorizontalGradient = new LinearGradientBrush();
myHorizontalGradient.StartPoint = new Point(0, 0.5);
myHorizontalGradient.EndPoint = new Point(1, 0.5);
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));

// Define material that will use the gradient.


DiffuseMaterial myDiffuseMaterial = new DiffuseMaterial(myHorizontalGradient);

// Add this gradient to a MaterialGroup.


MaterialGroup myMaterialGroup = new MaterialGroup();
myMaterialGroup.Children.Add(myDiffuseMaterial);

// Define an Emissive Material with a blue brush.


Color c = new Color();
c.ScA = 1;
c.ScB = 255;
c.ScR = 0;
c.ScG = 0;
EmissiveMaterial myEmissiveMaterial = new EmissiveMaterial(new SolidColorBrush(c));

// Add the Emmisive Material to the Material Group.


myMaterialGroup.Children.Add(myEmissiveMaterial);

// Add the composite material to the 3D model.


myGeometryModel.Material = myMaterialGroup;
' The material property of GeometryModel3D specifies the material applied to the 3D object.
' In this sample the material applied to the 3D object is made up of two materials layered
' on top of each other - a DiffuseMaterial (gradient brush) with an EmissiveMaterial
' layered on top (blue SolidColorBrush). The EmmisiveMaterial alters the appearance of
' the gradient toward blue.

' Create a horizontal linear gradient with four stops.


Dim myHorizontalGradient As New LinearGradientBrush()
myHorizontalGradient.StartPoint = New Point(0, 0.5)
myHorizontalGradient.EndPoint = New Point(1, 0.5)
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Yellow, 0.0))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Red, 0.25))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Blue, 0.75))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.LimeGreen, 1.0))

' Define material that will use the gradient.


Dim myDiffuseMaterial As New DiffuseMaterial(myHorizontalGradient)

' Add this gradient to a MaterialGroup.


Dim myMaterialGroup As New MaterialGroup()
myMaterialGroup.Children.Add(myDiffuseMaterial)

' Define an Emissive Material with a blue brush.


Dim c As New Color()
c.ScA = 1
c.ScB = 255
c.ScR = 0
c.ScG = 0
Dim myEmissiveMaterial As New EmissiveMaterial(New SolidColorBrush(c))

' Add the Emmisive Material to the Material Group.


myMaterialGroup.Children.Add(myEmissiveMaterial)

' Add the composite material to the 3D model.


myGeometryModel.Material = myMaterialGroup

Ejemplo
El código siguiente muestra el ejemplo completo en XAML.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the lights cast in the scene. Without light, the
3D object cannot be seen. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifies the shape of the 3D plane. In this case, a flat sheet is
created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>
<!-- The material applied to the 3D object is made up of a DiffuseMaterial (gradient brush)
with
an EmissiveMaterial layered on top (blue SolidColorBrush). The EmissiveMaterial adds
blue to the gradient. -->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
<EmissiveMaterial>
<EmissiveMaterial.Brush>
<SolidColorBrush x:Name="mySolidColorBrush" Color="Blue" />
</EmissiveMaterial.Brush>
</EmissiveMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. This transform
rotates the object.-->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="myAngleRotation" Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Ejemplo
A continuación es el ejemplo completo en el código de procedimiento.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace SDKSample
{
public partial class EmissiveMaterialExample : Page
{
public EmissiveMaterialExample()
{

// Declare scene objects.


Viewport3D myViewport3D = new Viewport3D();
Model3DGroup myModel3DGroup = new Model3DGroup();
GeometryModel3D myGeometryModel = new GeometryModel3D();
ModelVisual3D myModelVisual3D = new ModelVisual3D();

// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();

// Specify where in the 3D scene the camera is.


myPCamera.Position = new Point3D(0, 0, 2);

// Specify the direction that the camera is pointing.


myPCamera.LookDirection = new Vector3D(0, 0, -1);

// Define camera's horizontal field of view in degrees.


myPCamera.FieldOfView = 60;

// Asign the camera to the viewport


myViewport3D.Camera = myPCamera;

// Define the lights cast in the scene. Without light, the 3D object cannot
// be seen. Note: to illuminate an object from additional directions, create
// additional lights.
DirectionalLight myDirectionalLight = new DirectionalLight();
myDirectionalLight.Color = Colors.White;
myDirectionalLight.Direction = new Vector3D(-0.61, -0.5, -0.61);

myModel3DGroup.Children.Add(myDirectionalLight);

// The geometry specifes the shape of the 3D plane. In this sample, a flat sheet
// is created.
MeshGeometry3D myMeshGeometry3D = new MeshGeometry3D();

// Create a collection of normal vectors for the MeshGeometry3D.


Vector3DCollection myNormalCollection = new Vector3DCollection();
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myMeshGeometry3D.Normals = myNormalCollection;

// Create a collection of vertex positions for the MeshGeometry3D.


Point3DCollection myPositionCollection = new Point3DCollection();
myPositionCollection.Add(new Point3D(-0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(-0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(-0.5, -0.5, 0.5));
myMeshGeometry3D.Positions = myPositionCollection;

// Create a collection of texture coordinates for the MeshGeometry3D.


PointCollection myTextureCoordinatesCollection = new PointCollection();
myTextureCoordinatesCollection.Add(new Point(0, 0));
myTextureCoordinatesCollection.Add(new Point(0, 0));
myTextureCoordinatesCollection.Add(new Point(1, 0));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myTextureCoordinatesCollection.Add(new Point(0, 1));
myTextureCoordinatesCollection.Add(new Point(0, 0));
myMeshGeometry3D.TextureCoordinates = myTextureCoordinatesCollection;

// Create a collection of triangle indices for the MeshGeometry3D.


Int32Collection myTriangleIndicesCollection = new Int32Collection();
myTriangleIndicesCollection.Add(0);
myTriangleIndicesCollection.Add(1);
myTriangleIndicesCollection.Add(2);
myTriangleIndicesCollection.Add(3);
myTriangleIndicesCollection.Add(4);
myTriangleIndicesCollection.Add(5);
myMeshGeometry3D.TriangleIndices = myTriangleIndicesCollection;

// Apply the mesh to the geometry model.


myGeometryModel.Geometry = myMeshGeometry3D;
// The material property of GeometryModel3D specifies the material applied to the 3D object.
// In this sample the material applied to the 3D object is made up of two materials layered
// on top of each other - a DiffuseMaterial (gradient brush) with an EmissiveMaterial
// layered on top (blue SolidColorBrush). The EmmisiveMaterial alters the appearance of
// the gradient toward blue.

// Create a horizontal linear gradient with four stops.


LinearGradientBrush myHorizontalGradient = new LinearGradientBrush();
myHorizontalGradient.StartPoint = new Point(0, 0.5);
myHorizontalGradient.EndPoint = new Point(1, 0.5);
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));

// Define material that will use the gradient.


DiffuseMaterial myDiffuseMaterial = new DiffuseMaterial(myHorizontalGradient);

// Add this gradient to a MaterialGroup.


MaterialGroup myMaterialGroup = new MaterialGroup();
myMaterialGroup.Children.Add(myDiffuseMaterial);

// Define an Emissive Material with a blue brush.


Color c = new Color();
c.ScA = 1;
c.ScB = 255;
c.ScR = 0;
c.ScG = 0;
EmissiveMaterial myEmissiveMaterial = new EmissiveMaterial(new SolidColorBrush(c));

// Add the Emmisive Material to the Material Group.


myMaterialGroup.Children.Add(myEmissiveMaterial);

// Add the composite material to the 3D model.


myGeometryModel.Material = myMaterialGroup;
// Apply a transform to the object. In this sample, a rotation transform is applied,
// rendering the 3D object rotated.
RotateTransform3D myRotateTransform3D = new RotateTransform3D();
AxisAngleRotation3D myAxisAngleRotation3d = new AxisAngleRotation3D();
myAxisAngleRotation3d.Axis = new Vector3D(0,3,0);
myAxisAngleRotation3d.Angle = 40;
myRotateTransform3D.Rotation = myAxisAngleRotation3d;
myGeometryModel.Transform = myRotateTransform3D;

// Add the geometry model to the model group.


myModel3DGroup.Children.Add(myGeometryModel);

// Add the group of models to the ModelVisual3d.


myModelVisual3D.Content = myModel3DGroup;
myViewport3D.Children.Add(myModelVisual3D);
myViewport3D.Children.Add(myModelVisual3D);

// Apply the viewport to the page so it will be rendered.


this.Content = myViewport3D;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Media3D

Namespace SDKSample
Partial Public Class EmissiveMaterialExample
Inherits Page
Public Sub New()

' Declare scene objects.


Dim myViewport3D As New Viewport3D()
Dim myModel3DGroup As New Model3DGroup()
Dim myGeometryModel As New GeometryModel3D()
Dim myModelVisual3D As New ModelVisual3D()

' Defines the camera used to view the 3D object. In order to view the 3D object,
' the camera must be positioned and pointed such that the object is within view
' of the camera.
Dim myPCamera As New PerspectiveCamera()

' Specify where in the 3D scene the camera is.


myPCamera.Position = New Point3D(0, 0, 2)

' Specify the direction that the camera is pointing.


myPCamera.LookDirection = New Vector3D(0, 0, -1)

' Define camera's horizontal field of view in degrees.


myPCamera.FieldOfView = 60

' Asign the camera to the viewport


myViewport3D.Camera = myPCamera

' Define the lights cast in the scene. Without light, the 3D object cannot
' be seen. Note: to illuminate an object from additional directions, create
' additional lights.
Dim myDirectionalLight As New DirectionalLight()
myDirectionalLight.Color = Colors.White
myDirectionalLight.Direction = New Vector3D(-0.61, -0.5, -0.61)

myModel3DGroup.Children.Add(myDirectionalLight)

' The geometry specifes the shape of the 3D plane. In this sample, a flat sheet
' is created.
Dim myMeshGeometry3D As New MeshGeometry3D()

' Create a collection of normal vectors for the MeshGeometry3D.


Dim myNormalCollection As New Vector3DCollection()
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myMeshGeometry3D.Normals = myNormalCollection

' Create a collection of vertex positions for the MeshGeometry3D.


Dim myPositionCollection As New Point3DCollection()
myPositionCollection.Add(New Point3D(-0.5, -0.5, 0.5))
myPositionCollection.Add(New Point3D(-0.5, -0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, -0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(-0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(-0.5, -0.5, 0.5))
myMeshGeometry3D.Positions = myPositionCollection

' Create a collection of texture coordinates for the MeshGeometry3D.


Dim myTextureCoordinatesCollection As New PointCollection()
myTextureCoordinatesCollection.Add(New Point(0, 0))
myTextureCoordinatesCollection.Add(New Point(1, 0))
myTextureCoordinatesCollection.Add(New Point(1, 1))
myTextureCoordinatesCollection.Add(New Point(1, 1))
myTextureCoordinatesCollection.Add(New Point(0, 1))
myTextureCoordinatesCollection.Add(New Point(0, 0))
myMeshGeometry3D.TextureCoordinates = myTextureCoordinatesCollection

' Create a collection of triangle indices for the MeshGeometry3D.


Dim myTriangleIndicesCollection As New Int32Collection()
myTriangleIndicesCollection.Add(0)
myTriangleIndicesCollection.Add(1)
myTriangleIndicesCollection.Add(2)
myTriangleIndicesCollection.Add(3)
myTriangleIndicesCollection.Add(4)
myTriangleIndicesCollection.Add(5)
myMeshGeometry3D.TriangleIndices = myTriangleIndicesCollection

' Apply the mesh to the geometry model.


myGeometryModel.Geometry = myMeshGeometry3D
' The material property of GeometryModel3D specifies the material applied to the 3D object.
' In this sample the material applied to the 3D object is made up of two materials layered
' on top of each other - a DiffuseMaterial (gradient brush) with an EmissiveMaterial
' layered on top (blue SolidColorBrush). The EmmisiveMaterial alters the appearance of
' the gradient toward blue.

' Create a horizontal linear gradient with four stops.


Dim myHorizontalGradient As New LinearGradientBrush()
myHorizontalGradient.StartPoint = New Point(0, 0.5)
myHorizontalGradient.EndPoint = New Point(1, 0.5)
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Yellow, 0.0))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Red, 0.25))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Blue, 0.75))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.LimeGreen, 1.0))

' Define material that will use the gradient.


Dim myDiffuseMaterial As New DiffuseMaterial(myHorizontalGradient)

' Add this gradient to a MaterialGroup.


Dim myMaterialGroup As New MaterialGroup()
myMaterialGroup.Children.Add(myDiffuseMaterial)

' Define an Emissive Material with a blue brush.


Dim c As New Color()
c.ScA = 1
c.ScB = 255
c.ScR = 0
c.ScG = 0
Dim myEmissiveMaterial As New EmissiveMaterial(New SolidColorBrush(c))

' Add the Emmisive Material to the Material Group.


myMaterialGroup.Children.Add(myEmissiveMaterial)

' Add the composite material to the 3D model.


myGeometryModel.Material = myMaterialGroup
' Apply a transform to the object. In this sample, a rotation transform is applied,
' rendering the 3D object rotated.
Dim myRotateTransform3D As New RotateTransform3D()
Dim myAxisAngleRotation3d As New AxisAngleRotation3D()
myAxisAngleRotation3d.Axis = New Vector3D(0,3,0)
myAxisAngleRotation3d.Axis = New Vector3D(0,3,0)
myAxisAngleRotation3d.Angle = 40
myRotateTransform3D.Rotation = myAxisAngleRotation3d
myGeometryModel.Transform = myRotateTransform3D

' Add the geometry model to the model group.


myModel3DGroup.Children.Add(myGeometryModel)

' Add the group of models to the ModelVisual3d.


myModelVisual3D.Content = myModel3DGroup
myViewport3D.Children.Add(myModelVisual3D)

' Apply the viewport to the page so it will be rendered.


Me.Content = myViewport3D
End Sub
End Class
End Namespace

Vea también
Crear una escena 3D
Información general sobre gráficos 3D
Animar propiedades de material en una escena 3D
Aplicar material a la parte anterior y posterior de un objeto 3D
Procedimiento Transformar la escala de un modelo
3D
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo escalar un objeto 3D. Para escalar un objeto 3D, use un ScaleTransform3D. El
ScaleX, ScaleY, y ScaleZ propiedades, cambie el tamaño del elemento por el factor que especifique. Por ejemplo,
un ScaleX valor de 1,5 ajusta un objeto al 150 por ciento de su ancho original. Un ScaleY valor de 0,5 reduce el
alto de un objeto en un 50%. El código siguiente muestra mediante un ScaleTransform3D como la transformación
para un GeometryModel3D.

<!-- Apply a scale transform to the object. You can transform the scale of the object
for the X, Y, or Z axis. The ScaleX, ScaleY, and ScaleZ properties resize the object
by the factor you specify. For example, a ScaleX value of 1.5 stretches the object to
150 percent of its original width. A ScaleY value of 0.5 shrinks the height of an object
by 50 percent. -->
<GeometryModel3D.Transform>

<!-- This Scale Transform stretches the object horizontally by 200 percent and shrinks it
vertically by 50 percent. -->
<ScaleTransform3D ScaleX="2" ScaleY="0.5" ScaleZ="1" CenterX="0" CenterY="0" CenterZ="0" />
</GeometryModel3D.Transform>

Ejemplo
El código siguiente muestra el ejemplo completo.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D ClipToBounds="True" Width="150" Height="150" Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the light cast in the scene. Without light, the 3D
object cannot be seen. Also, the direction of the lights affect shadowing. If desired,
you can create multiple lights with different colors that shine from different directions. --
>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifies the shape of the 3D plane. In this sample, a flat sheet is
<!-- The geometry specifies the shape of the 3D plane. In this sample, a flat sheet is
created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the 3D object. In this sample a linear
gradient
covers the surface of the 3D object.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- Apply a scale transform to the object. You can transform the scale of the object
for the X, Y, or Z axis. The ScaleX, ScaleY, and ScaleZ properties resize the object
by the factor you specify. For example, a ScaleX value of 1.5 stretches the object to
150 percent of its original width. A ScaleY value of 0.5 shrinks the height of an
object
by 50 percent. -->
<GeometryModel3D.Transform>

<!-- This Scale Transform stretches the object horizontally by 200 percent and shrinks it
vertically by 50 percent. -->
<ScaleTransform3D ScaleX="2" ScaleY="0.5" ScaleZ="1" CenterX="0" CenterY="0" CenterZ="0"
/>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Vea también
Animar traslaciones 3D
Crear una escena 3D
Información general sobre gráficos 3D
Procedimiento Aplicar varias transformaciones a un
modelo 3D
23/10/2019 • 9 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un RotateTransform3D y un ScaleTransform3D girar y cambiar la escala de
un modelo 3D. El código siguiente muestra cómo aplicar estas transformaciones a la Transform propiedad de un
GeometryModel3D en XAML.

<!-- Apply multiple transformations to the object. In this sample, a rotation and scale transform
is applied. -->
<GeometryModel3D.Transform>
<Transform3DGroup>
<Transform3DGroup.Children>
<RotateTransform3D>
<RotateTransform3D.Rotation>

<!-- This transformation rotates the object. -->


<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>

<!-- This Scale Transform stretches the object horizontally by 200 percent and shrinks it
vertically by 50 percent. -->
<ScaleTransform3D ScaleX="2" ScaleY="0.5" ScaleZ="1" CenterX="0" CenterY="0" CenterZ="0" />
</Transform3DGroup.Children>
</Transform3DGroup>
</GeometryModel3D.Transform>

Mediante código:

// Apply multiple transformations to the object. In this sample, a rotation and scale
// transform is applied.

// Create and apply a transformation that rotates the object.


RotateTransform3D myRotateTransform3D = new RotateTransform3D();
AxisAngleRotation3D myAxisAngleRotation3d = new AxisAngleRotation3D();
myAxisAngleRotation3d.Axis = new Vector3D(0,3,0);
myAxisAngleRotation3d.Angle = 40;
myRotateTransform3D.Rotation = myAxisAngleRotation3d;

// Add the rotation transform to a Transform3DGroup


Transform3DGroup myTransform3DGroup = new Transform3DGroup();
myTransform3DGroup.Children.Add(myRotateTransform3D);

// Create and apply a scale transformation that stretches the object along the local x-axis
// by 200 percent and shrinks it along the local y-axis by 50 percent.
ScaleTransform3D myScaleTransform3D = new ScaleTransform3D();
myScaleTransform3D.ScaleX = 2;
myScaleTransform3D.ScaleY = 0.5;
myScaleTransform3D.ScaleZ = 1;

// Add the scale transform to the Transform3DGroup.


myTransform3DGroup.Children.Add(myScaleTransform3D);

// Set the Transform property of the GeometryModel to the Transform3DGroup which includes
// both transformations. The 3D object now has two Transformations applied to it.
myGeometryModel.Transform = myTransform3DGroup;
' Apply multiple transformations to the object. In this sample, a rotation and scale
' transform is applied.

' Create and apply a transformation that rotates the object.


Dim myRotateTransform3D As New RotateTransform3D()
Dim myAxisAngleRotation3d As New AxisAngleRotation3D()
myAxisAngleRotation3d.Axis = New Vector3D(0,3,0)
myAxisAngleRotation3d.Angle = 40
myRotateTransform3D.Rotation = myAxisAngleRotation3d

' Add the rotation transform to a Transform3DGroup


Dim myTransform3DGroup As New Transform3DGroup()
myTransform3DGroup.Children.Add(myRotateTransform3D)

' Create and apply a scale transformation that stretches the object along the local x-axis
' by 200 percent and shrinks it along the local y-axis by 50 percent.
Dim myScaleTransform3D As New ScaleTransform3D()
myScaleTransform3D.ScaleX = 2
myScaleTransform3D.ScaleY = 0.5
myScaleTransform3D.ScaleZ = 1

' Add the scale transform to the Transform3DGroup.


myTransform3DGroup.Children.Add(myScaleTransform3D)

' Set the Transform property of the GeometryModel to the Transform3DGroup which includes
' both transformations. The 3D object now has two Transformations applied to it.
myGeometryModel.Transform = myTransform3DGroup

Ejemplo
El código siguiente muestra el ejemplo completo en XAML.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D ClipToBounds="True" Width="150" Height="150" Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the light cast in the scene. Without light, the 3D
object cannot be seen. Also, the direction of the lights affect shadowing. If desired,
you can create multiple lights with different colors that shine from different directions. --
>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifies the shape of the 3D plane. In this sample, a flat sheet is
created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the 3D object. In this sample a linear
gradient
covers the surface of the 3D object.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- Apply multiple transformations to the object. In this sample, a rotation and scale
transform
is applied. -->
<GeometryModel3D.Transform>
<Transform3DGroup>
<Transform3DGroup.Children>
<RotateTransform3D>
<RotateTransform3D.Rotation>

<!-- This transformation rotates the object. -->


<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>

<!-- This Scale Transform stretches the object horizontally by 200 percent and shrinks
it
vertically by 50 percent. -->
<ScaleTransform3D ScaleX="2" ScaleY="0.5" ScaleZ="1" CenterX="0" CenterY="0"
CenterZ="0" />
</Transform3DGroup.Children>
</Transform3DGroup>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Ejemplo
A continuación es el ejemplo completo en el código.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace SDKSample
{
public partial class MultipleTransformationsExample : Page
{
public MultipleTransformationsExample()
{

// Declare scene objects.


Viewport3D myViewport3D = new Viewport3D();
Model3DGroup myModel3DGroup = new Model3DGroup();
GeometryModel3D myGeometryModel = new GeometryModel3D();
ModelVisual3D myModelVisual3D = new ModelVisual3D();

// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();

// Specify where in the 3D scene the camera is.


myPCamera.Position = new Point3D(0, 0, 2);

// Specify the direction that the camera is pointing.


myPCamera.LookDirection = new Vector3D(0, 0, -1);

// Define camera's horizontal field of view in degrees.


myPCamera.FieldOfView = 60;

// Asign the camera to the viewport


myViewport3D.Camera = myPCamera;

// Define the lights cast in the scene. Without light, the 3D object cannot
// be seen. Note: to illuminate an object from additional directions, create
// additional lights.
DirectionalLight myDirectionalLight = new DirectionalLight();
myDirectionalLight.Color = Colors.White;
myDirectionalLight.Direction = new Vector3D(-0.61, -0.5, -0.61);

myModel3DGroup.Children.Add(myDirectionalLight);

// The geometry specifes the shape of the 3D plane. In this sample, a flat sheet
// is created.
MeshGeometry3D myMeshGeometry3D = new MeshGeometry3D();

// Create a collection of normal vectors for the MeshGeometry3D.


Vector3DCollection myNormalCollection = new Vector3DCollection();
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myNormalCollection.Add(new Vector3D(0,0,1));
myMeshGeometry3D.Normals = myNormalCollection;

// Create a collection of vertex positions for the MeshGeometry3D.


Point3DCollection myPositionCollection = new Point3DCollection();
myPositionCollection.Add(new Point3D(-0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(-0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(-0.5, -0.5, 0.5));
myMeshGeometry3D.Positions = myPositionCollection;

// Create a collection of texture coordinates for the MeshGeometry3D.


PointCollection myTextureCoordinatesCollection = new PointCollection();
PointCollection myTextureCoordinatesCollection = new PointCollection();
myTextureCoordinatesCollection.Add(new Point(0, 0));
myTextureCoordinatesCollection.Add(new Point(1, 0));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myTextureCoordinatesCollection.Add(new Point(0, 1));
myTextureCoordinatesCollection.Add(new Point(0, 0));
myMeshGeometry3D.TextureCoordinates = myTextureCoordinatesCollection;

// Create a collection of triangle indices for the MeshGeometry3D.


Int32Collection myTriangleIndicesCollection = new Int32Collection();
myTriangleIndicesCollection.Add(0);
myTriangleIndicesCollection.Add(1);
myTriangleIndicesCollection.Add(2);
myTriangleIndicesCollection.Add(3);
myTriangleIndicesCollection.Add(4);
myTriangleIndicesCollection.Add(5);
myMeshGeometry3D.TriangleIndices = myTriangleIndicesCollection;

// Apply the mesh to the geometry model.


myGeometryModel.Geometry = myMeshGeometry3D;

// The material specifies the material applied to the 3D object. In this sample a
// linear gradient covers the surface of the 3D object.

// Create a horizontal linear gradient with four stops.


LinearGradientBrush myHorizontalGradient = new LinearGradientBrush();
myHorizontalGradient.StartPoint = new Point(0, 0.5);
myHorizontalGradient.EndPoint = new Point(1, 0.5);
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));

// Define material and apply to the mesh geometries.


DiffuseMaterial myMaterial = new DiffuseMaterial(myHorizontalGradient);
myGeometryModel.Material = myMaterial;
// Apply multiple transformations to the object. In this sample, a rotation and scale
// transform is applied.

// Create and apply a transformation that rotates the object.


RotateTransform3D myRotateTransform3D = new RotateTransform3D();
AxisAngleRotation3D myAxisAngleRotation3d = new AxisAngleRotation3D();
myAxisAngleRotation3d.Axis = new Vector3D(0,3,0);
myAxisAngleRotation3d.Angle = 40;
myRotateTransform3D.Rotation = myAxisAngleRotation3d;

// Add the rotation transform to a Transform3DGroup


Transform3DGroup myTransform3DGroup = new Transform3DGroup();
myTransform3DGroup.Children.Add(myRotateTransform3D);

// Create and apply a scale transformation that stretches the object along the local x-axis
// by 200 percent and shrinks it along the local y-axis by 50 percent.
ScaleTransform3D myScaleTransform3D = new ScaleTransform3D();
myScaleTransform3D.ScaleX = 2;
myScaleTransform3D.ScaleY = 0.5;
myScaleTransform3D.ScaleZ = 1;

// Add the scale transform to the Transform3DGroup.


myTransform3DGroup.Children.Add(myScaleTransform3D);

// Set the Transform property of the GeometryModel to the Transform3DGroup which includes
// both transformations. The 3D object now has two Transformations applied to it.
myGeometryModel.Transform = myTransform3DGroup;
// Add the geometry model to the model group.
myModel3DGroup.Children.Add(myGeometryModel);

// Add the group of models to the ModelVisual3d.


myModelVisual3D.Content = myModel3DGroup;
myViewport3D.Children.Add(myModelVisual3D);

// Apply the viewport to the page so it will be rendered.


this.Content = myViewport3D;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Media3D

Namespace SDKSample
Partial Public Class MultipleTransformationsExample
Inherits Page
Public Sub New()

' Declare scene objects.


Dim myViewport3D As New Viewport3D()
Dim myModel3DGroup As New Model3DGroup()
Dim myGeometryModel As New GeometryModel3D()
Dim myModelVisual3D As New ModelVisual3D()

' Defines the camera used to view the 3D object. In order to view the 3D object,
' the camera must be positioned and pointed such that the object is within view
' of the camera.
Dim myPCamera As New PerspectiveCamera()

' Specify where in the 3D scene the camera is.


myPCamera.Position = New Point3D(0, 0, 2)

' Specify the direction that the camera is pointing.


myPCamera.LookDirection = New Vector3D(0, 0, -1)

' Define camera's horizontal field of view in degrees.


myPCamera.FieldOfView = 60

' Asign the camera to the viewport


myViewport3D.Camera = myPCamera

' Define the lights cast in the scene. Without light, the 3D object cannot
' be seen. Note: to illuminate an object from additional directions, create
' additional lights.
Dim myDirectionalLight As New DirectionalLight()
myDirectionalLight.Color = Colors.White
myDirectionalLight.Direction = New Vector3D(-0.61, -0.5, -0.61)

myModel3DGroup.Children.Add(myDirectionalLight)

' The geometry specifes the shape of the 3D plane. In this sample, a flat sheet
' is created.
Dim myMeshGeometry3D As New MeshGeometry3D()

' Create a collection of normal vectors for the MeshGeometry3D.


Dim myNormalCollection As New Vector3DCollection()
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myNormalCollection.Add(New Vector3D(0,0,1))
myMeshGeometry3D.Normals = myNormalCollection

' Create a collection of vertex positions for the MeshGeometry3D.


Dim myPositionCollection As New Point3DCollection()
Dim myPositionCollection As New Point3DCollection()
myPositionCollection.Add(New Point3D(-0.5, -0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, -0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(-0.5, 0.5, 0.5))
myPositionCollection.Add(New Point3D(-0.5, -0.5, 0.5))
myMeshGeometry3D.Positions = myPositionCollection

' Create a collection of texture coordinates for the MeshGeometry3D.


Dim myTextureCoordinatesCollection As New PointCollection()
myTextureCoordinatesCollection.Add(New Point(0, 0))
myTextureCoordinatesCollection.Add(New Point(1, 0))
myTextureCoordinatesCollection.Add(New Point(1, 1))
myTextureCoordinatesCollection.Add(New Point(1, 1))
myTextureCoordinatesCollection.Add(New Point(0, 1))
myTextureCoordinatesCollection.Add(New Point(0, 0))
myMeshGeometry3D.TextureCoordinates = myTextureCoordinatesCollection

' Create a collection of triangle indices for the MeshGeometry3D.


Dim myTriangleIndicesCollection As New Int32Collection()
myTriangleIndicesCollection.Add(0)
myTriangleIndicesCollection.Add(1)
myTriangleIndicesCollection.Add(2)
myTriangleIndicesCollection.Add(3)
myTriangleIndicesCollection.Add(4)
myTriangleIndicesCollection.Add(5)
myMeshGeometry3D.TriangleIndices = myTriangleIndicesCollection

' Apply the mesh to the geometry model.


myGeometryModel.Geometry = myMeshGeometry3D

' The material specifies the material applied to the 3D object. In this sample a
' linear gradient covers the surface of the 3D object.

' Create a horizontal linear gradient with four stops.


Dim myHorizontalGradient As New LinearGradientBrush()
myHorizontalGradient.StartPoint = New Point(0, 0.5)
myHorizontalGradient.EndPoint = New Point(1, 0.5)
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Yellow, 0.0))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Red, 0.25))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.Blue, 0.75))
myHorizontalGradient.GradientStops.Add(New GradientStop(Colors.LimeGreen, 1.0))

' Define material and apply to the mesh geometries.


Dim myMaterial As New DiffuseMaterial(myHorizontalGradient)
myGeometryModel.Material = myMaterial
' Apply multiple transformations to the object. In this sample, a rotation and scale
' transform is applied.

' Create and apply a transformation that rotates the object.


Dim myRotateTransform3D As New RotateTransform3D()
Dim myAxisAngleRotation3d As New AxisAngleRotation3D()
myAxisAngleRotation3d.Axis = New Vector3D(0,3,0)
myAxisAngleRotation3d.Angle = 40
myRotateTransform3D.Rotation = myAxisAngleRotation3d

' Add the rotation transform to a Transform3DGroup


Dim myTransform3DGroup As New Transform3DGroup()
myTransform3DGroup.Children.Add(myRotateTransform3D)

' Create and apply a scale transformation that stretches the object along the local x-axis
' by 200 percent and shrinks it along the local y-axis by 50 percent.
Dim myScaleTransform3D As New ScaleTransform3D()
myScaleTransform3D.ScaleX = 2
myScaleTransform3D.ScaleY = 0.5
myScaleTransform3D.ScaleZ = 1

' Add the scale transform to the Transform3DGroup.


myTransform3DGroup.Children.Add(myScaleTransform3D)
myTransform3DGroup.Children.Add(myScaleTransform3D)

' Set the Transform property of the GeometryModel to the Transform3DGroup which includes
' both transformations. The 3D object now has two Transformations applied to it.
myGeometryModel.Transform = myTransform3DGroup
' Add the geometry model to the model group.
myModel3DGroup.Children.Add(myGeometryModel)

' Add the group of models to the ModelVisual3d.


myModelVisual3D.Content = myModel3DGroup

myViewport3D.Children.Add(myModelVisual3D)

' Apply the viewport to the page so it will be rendered.


Me.Content = myViewport3D
End Sub
End Class
End Namespace

Vea también
Transformar la escala de un modelo 3D
Procedimiento Animar traslaciones 3D
23/10/2019 • 2 minutes to read • Edit Online

En este tema se muestra cómo animar una transformación de traslación establecido en un modelo 3D.
El código siguiente muestra la aplicación de un TranslateTransform3D de objeto para el Transform propiedad de
un GeometryModel3D.

<!-- The Transform specifies how to transform the 3D object. The OffsetX property is animated
in the Storyboard below. -->
<GeometryModel3D.Transform>
<TranslateTransform3D x:Name="myTranslateTransform3D" OffsetX="0" OffsetY="0" OffsetZ="0" />
</GeometryModel3D.Transform>

El OffsetX propiedad de este TranslateTransform3D objeto se anima mediante el código siguiente.

<!-- Trigger the TranslateTransform3D animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the OffsetX property of the TranslateTransform3D. -->
<DoubleAnimation
Storyboard.TargetName="myTranslateTransform3D"
Storyboard.TargetProperty="OffsetX"
To="-0.8"
AutoReverse="True" RepeatBehavior="Forever" />

<!-- If you want to animate OffsetY and/or OffsetZ, create similar DoubleAnimations
respectively. -->

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>

Ejemplo
El código siguiente muestra el ejemplo completo.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="600" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="600" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>
<!-- The ModelVisual3D children contain the 3D models -->
<Viewport3D.Children>

<!-- This ModelVisual3D defines the light cast in the scene. Without light, the
3D object cannot be seen. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. The OffsetX property is
animated
in the Storyboard below. -->
<GeometryModel3D.Transform>
<TranslateTransform3D x:Name="myTranslateTransform3D" OffsetX="0" OffsetY="0" OffsetZ="0"
/>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
<!-- Trigger the TranslateTransform3D animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the OffsetX property of the TranslateTransform3D. -->
<DoubleAnimation
Storyboard.TargetName="myTranslateTransform3D"
Storyboard.TargetProperty="OffsetX"
To="-0.8"
AutoReverse="True" RepeatBehavior="Forever" />

<!-- If you want to animate OffsetY and/or OffsetZ, create similar DoubleAnimations
respectively. -->

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Vea también
Información general sobre animaciones
Crear una escena 3D
Información general sobre gráficos 3D
Información general sobre transformaciones
Procedimiento Animar un giro 3D mediante
Storyboards
23/10/2019 • 2 minutes to read • Edit Online

El ejemplo siguiente muestra cómo hacer girar mientras se "tambalea" animar un objeto 3D el Angle y Axis las
propiedades de un AxisAngleRotation3D objeto. Esto AxisAngleRotation3D objeto especifica la transformación de
giro del objeto 3D y sus propiedades de animación por lo que crea el efecto de giro deseado. En el guión gráfico,
DoubleAnimation sirve para animar la Angle propiedad mientras Vector3DAnimation sirve para animar el Axis
propiedad.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- Two ModelVisual3D define the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>
<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

<!-- The Transform specifies how to transform the 3D object. The properties of the
Rotation object are animated causing the 3D object to rotate and "wobble" (see
Storyboard below).-->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="myAngleRotation" Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the Angle property of the AxisAngleRotation3D


making the 3D object rotate from -60 degrees to 60 degrees. -->
<DoubleAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Angle"
From="-60" To="60" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>

<!-- This animation animates the Axis property of the AxisAngleRotation3D


making the 3D wobble as it rotates. -->
<Vector3DAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Axis"
From="0,3,0" To="1,0,1" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>

</Viewbox>
</DockPanel>
</Page>

Vea también
Animar un giro 3D mediante Rotation3DAnimation
Animar un giro 3D mediante fotogramas clave (Rotation3DAnimationUsingKeyFrames)
Información general sobre gráficos 3D
Información general sobre objetos Storyboard
Procedimiento Animar un giro 3D mediante
Rotation3DAnimation
23/10/2019 • 2 minutes to read • Edit Online

El ejemplo siguiente muestra cómo hacer girar mientras se "tambalea" mediante el uso de un objeto 3D
Rotation3DAnimation para animar la Rotation propiedad de la RotateTransform3D objeto aplicado al objeto 3D.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- Two ModelVisual3D define the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

<!-- The Transform specifies how to transform the 3D object. The properties of the
Rotation object are animated causing the 3D object to rotate and "wobble" (see
Storyboard below).-->
<GeometryModel3D.Transform>
<RotateTransform3D x:Name="myRotateTransform3D" >
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the Rotation property of the RotateTransform


causing the 3D shape to rotate and wobble as the rotation angle and
axis are animated. -->
<Rotation3DAnimation
Storyboard.TargetName="myRotateTransform3D"
Storyboard.TargetProperty="Rotation"
AutoReverse="True" RepeatBehavior="Forever">
<Rotation3DAnimation.From>
<AxisAngleRotation3D Axis="0,3,0" Angle="-60" />
</Rotation3DAnimation.From>
<Rotation3DAnimation.To>
<AxisAngleRotation3D Axis="1,0,1" Angle="60" />
</Rotation3DAnimation.To>
</Rotation3DAnimation>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Vea también
Información general sobre gráficos 3D
Animar un giro 3D mediante fotogramas clave (Rotation3DAnimationUsingKeyFrames)
Animar un giro 3D mediante Storyboards
Animar un giro 3D mediante cuaterniones
Información general sobre animaciones
Procedimiento Animar un giro 3D mediante
cuaterniones
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo animar un giro de un objeto 3D mediante cuaterniones.


El código siguiente muestra un QuaternionRotation3D utilizar como el valor de la Rotation propiedad de un
RotateTransform3D.

<!-- The Transform specifies how to transform the 3D object. The rotation
is animated using the Storyboard below. -->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<QuaternionRotation3D x:Name="myQuaternionRotation3D" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>

Esto QuaternionRotation3D está animada con un QuaternionAnimation dentro de un Storyboard con el código
siguiente.

<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the Rotation property of the RotateTransform3D


causing the 3D shape to rotate. -->
<QuaternionAnimation
Storyboard.TargetName="myQuaternionRotation3D"
Storyboard.TargetProperty="Quaternion" From="0,0,1,0" To="0.3, 0.3, 1, 0"
Duration="0:0:2" />

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>

Ejemplo
El código siguiente muestra el ejemplo completo.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<!-- Defines the camera used to view the 3D object. -->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. The rotation
is animated using the Storyboard below. -->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<QuaternionRotation3D x:Name="myQuaternionRotation3D" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the Rotation property of the RotateTransform3D


causing the 3D shape to rotate. -->
causing the 3D shape to rotate. -->
<QuaternionAnimation
Storyboard.TargetName="myQuaternionRotation3D"
Storyboard.TargetProperty="Quaternion" From="0,0,1,0" To="0.3, 0.3, 1, 0"
Duration="0:0:2" />

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Vea también
Información general sobre animaciones
Crear una escena 3D
Información general sobre gráficos 3D
Información general sobre transformaciones
Animar un giro 3D mediante Storyboards
Animar un giro 3D mediante Rotation3DAnimation
Procedimiento Animar un giro 3D mediante
fotogramas clave
23/10/2019 • 3 minutes to read • Edit Online

En el ejemplo siguiente, Rotation3DAnimationUsingKeyFrames se usa para hacer girar mientras su eje de rotación
resultante en un "oscilante" anima un objeto 3D. Esta animación usa los fotogramas clave siguientes:
1. LinearRotation3DKeyFrame se usa para crear una interpolación lineal suave entre valores.
2. DiscreteRotation3DKeyFrame se usa para crear "saltos" súbitos entre los valores (sin interpolación).
3. SplineRotation3DKeyFrame se utiliza para crear una transición variable entre los valores según el
KeySpline propiedad. En el ejemplo siguiente, esta parte de la animación se inicia lentamente, pero hacia el
final del segmento temporal, se acelera exponencialmente.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- Two ModelVisual3D define the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

<!-- The Transform specifies how to transform the 3D object. The properties of the
Rotation object are animated causing the 3D object to rotate and "wobble" (see
Storyboard below).-->
<GeometryModel3D.Transform>
<RotateTransform3D x:Name="myRotateTransform3D" >
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the Rotation property of the RotateTransform


causing the 3D shape to rotate and wobble as the rotation angle and
axis are animated. -->
<Rotation3DAnimationUsingKeyFrames
Storyboard.TargetName="myRotateTransform3D"
Storyboard.TargetProperty="Rotation" >
<Rotation3DAnimationUsingKeyFrames.KeyFrames>

<!-- Using a LinearRotation3DKeyFrame, the object gradually rotates to an angle


of -60 degrees while the axis of rotation shifts (animates) to a new value. -->
<LinearRotation3DKeyFrame KeyTime="0:0:1">
<LinearRotation3DKeyFrame.Value>
<AxisAngleRotation3D Axis="1,0,1" Angle="-60" />
</LinearRotation3DKeyFrame.Value>
</LinearRotation3DKeyFrame>

<!-- Using a DiscreteRotation3DKeyFrame, the object suddenly rotates to the an angle


of 80 degrees on a new axis. This happens immdeiately after the first 1 and
a half seconds of the animation. -->
<DiscreteRotation3DKeyFrame KeyTime="0:0:1.5">
<DiscreteRotation3DKeyFrame.Value>
<AxisAngleRotation3D Axis="0,0,1" Angle="80" />
</DiscreteRotation3DKeyFrame.Value>
</DiscreteRotation3DKeyFrame>
<!-- Using a SplineRotation3DKeyFrame, the object rotates back to its starting position.
The animation starts out slowly at first and then speeds up. This KeyFrame ends
after the fourth second. -->
<SplineRotation3DKeyFrame KeySpline="0.6,0.0 0.9,0.00" KeyTime="0:0:4">
<SplineRotation3DKeyFrame.Value>
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</SplineRotation3DKeyFrame.Value>
</SplineRotation3DKeyFrame>

</Rotation3DAnimationUsingKeyFrames.KeyFrames>
</Rotation3DAnimationUsingKeyFrames>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>

</Viewbox>
</DockPanel>
</Page>

Vea también
Información general sobre gráficos 3D
Información general sobre animaciones de fotogramas clave
Animar un giro 3D mediante Storyboards
Animar un giro 3D mediante Rotation3DAnimation
Animar un giro 3D mediante cuaterniones
Animar un giro 3D mediante fotogramas clave (QuaternionAnimationUsingKeyFrames)
Procedimiento Animar un giro 3D mediante
fotogramas clave
(QuaternionAnimationUsingKeyFrames)
23/10/2019 • 2 minutes to read • Edit Online

En el ejemplo siguiente, QuaternionAnimationUsingKeyFrames se usa para hacer girar un objeto 3D. Esta
animación usa los fotogramas clave siguientes:
1. LinearRotation3DKeyFrame se usa para crear una interpolación lineal suave entre valores.
2. DiscreteRotation3DKeyFrame se usa para crear "saltos" súbitos entre los valores (sin interpolación).
3. SplineRotation3DKeyFrame se utiliza para crear una transición variable entre los valores según el KeySpline
propiedad. En el ejemplo siguiente, esta parte de la animación se inicia lentamente, pero hacia el final del
segmento temporal, se acelera exponencialmente.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>
</GeometryModel3D.Geometry>

<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

<!-- The Transform specifies how to transform the 3D object. The rotation
is animated using the Storyboard below. -->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<QuaternionRotation3D x:Name="myQuaternionRotation3D" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>

<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the Rotation property of the RotateTransform


causing the 3D shape to rotate and wobble as the rotation angle and
axis are animated. -->
<QuaternionAnimationUsingKeyFrames
Storyboard.TargetName="myQuaternionRotation3D"
Storyboard.TargetProperty="Quaternion" >
<QuaternionAnimationUsingKeyFrames.KeyFrames>

<!-- Using a LinearQuaternionKeyFrame, the 3D object gradually rotates from an askew


position to a flat position. -->
<LinearQuaternionKeyFrame KeyTime="0:0:1" Value="0,0,1,0" />

<!-- Using a DiscreteQuaternionKeyFrame, the object suddenly rotates to an askew


position. This happens immdeiately after the first 1 and a half seconds of the
animation. -->
<DiscreteQuaternionKeyFrame KeyTime="0:0:1.5" Value="0.3, 0.3, 1, 0" />

<!-- Using a SplineQuaternionKeyFrame, the object rotates back to a flat position.


The animation starts out slowly at first and then speeds up. This KeyFrame ends
after the fourth second. -->
<SplineQuaternionKeyFrame KeySpline="0.6,0.0 0.9,0.00" KeyTime="0:0:4" Value="0,0,1,0"
/>

</QuaternionAnimationUsingKeyFrames.KeyFrames>
</QuaternionAnimationUsingKeyFrames>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Vea también
Animar un giro 3D mediante Storyboards
Animar un giro 3D mediante Rotation3DAnimation
Animar un giro 3D mediante cuaterniones
Animar un giro 3D mediante fotogramas clave (Rotation3DAnimationUsingKeyFrames)
Información general sobre gráficos 3D
Información general sobre animaciones de fotogramas clave
Procedimiento Animar la posición y la dirección de
una cámara en una escena 3D
23/10/2019 • 2 minutes to read • Edit Online

El ejemplo siguiente muestra cómo animar la posición de una cámara y animar la dirección en la que apunta en
una escena 3D. Esto se realiza mediante Point3DAnimation y Vector3DAnimation para animar la Position y
LookDirection propiedades respectivamente, de la PerspectiveCamera. Puede usar una animación similar al
siguiente para cambiar la vista del espectador de una escena en respuesta a un evento.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. The position and direction of this
camera is animated in the Storyboard below. -->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="45" />
</Viewport3D.Camera>
<Viewport3D.Children>
<ModelVisual3D>
<ModelVisual3D.Children>

<!-- This resource defines the 3D cube that is used in this example.-->
<StaticResource ResourceKey="PictureCubeModelVisual3DResource" />
</ModelVisual3D.Children>

</ModelVisual3D>
</Viewport3D.Children>
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation moves the camera around the object. The object is not
changing position or rotating but moving the camera makes it appear that
it is.-->
<Point3DAnimation
Storyboard.TargetName="myPerspectiveCamera"
Storyboard.TargetProperty="Position"
From="0,0,2" To="1,2,3" Duration="0:0:4" RepeatBehavior="Forever"/>

<!-- As the position of the camera changes using the Point3DAnimation


above, the direction the camera is pointing swivels to keep the object
within the view of the camera. -->
<Vector3DAnimation
Storyboard.TargetName="myPerspectiveCamera"
Storyboard.TargetProperty="LookDirection"
From="0,0,-1" To="-1,-2,-3" Duration="0:0:4" RepeatBehavior="Forever"/>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>

</Viewbox>
</DockPanel>
</Page>

Vea también
Vector3DAnimation
Point3DAnimation
Animar la posición y la dirección de una cámara mediante fotogramas clave
Información general sobre gráficos 3D
Procedimiento Animar la posición y la dirección de
una cámara mediante fotogramas clave
23/10/2019 • 2 minutes to read • Edit Online

En el ejemplo siguiente, Point3DAnimationUsingKeyFrames sirve para animar la posición de un


PerspectiveCamera en una escena 3D. Además, Vector3DAnimationUsingKeyFrames se usa para animar la
dirección señala la cámara en la escena 3D. Ambas animaciones utilizan varios fotogramas clave que crean una
serie de efectos de animación:
1. LinearPoint3DKeyFrame y LinearVector3DKeyFrame se utilizan para crear una interpolación lineal suave
entre valores.
2. DiscretePoint3DKeyFrame y DiscreteVector3DKeyFrame se utilizan para crear "saltos" súbitos entre los
valores (sin interpolación).
3. SplinePoint3DKeyFrame y SplineVector3DKeyFrame se utilizan para crear una transición variable entre los
valores según el KeySpline propiedad. En el ejemplo siguiente, la animación se inicia lentamente, pero hacia
el final del segmento temporal, se acelera exponencialmente.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. The position and direction of this
camera is animated in the Storyboard below. -->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="45" />
</Viewport3D.Camera>
<Viewport3D.Children>
<ModelVisual3D>
<ModelVisual3D.Children>

<!-- This resource defines the 3D cube that is used in this example.-->
<StaticResource ResourceKey="PictureCubeModelVisual3DResource" />
</ModelVisual3D.Children>

</ModelVisual3D>
</Viewport3D.Children>
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation moves the camera around the object. The object is not
changing position or rotating but moving the camera makes it appear that
it is.-->
<Point3DAnimationUsingKeyFrames
Storyboard.TargetName="myPerspectiveCamera"
Storyboard.TargetProperty="Position" >
Storyboard.TargetProperty="Position" >
<Point3DAnimationUsingKeyFrames.KeyFrames>

<!-- Using a LinearPoint3DKeyFrame, the camera moves steadily from its


starting position to a new position that is to the upper right and a
little farther away. This happens over the first second of the animation. -->
<LinearPoint3DKeyFrame Value="1,2,3" KeyTime="0:0:1" />

<!-- Using a DiscretePoint3DKeyFrame, the camera suddenly moves farther away


from the object. This happens immdeiately after the first 1 and a half second
of the animation. -->
<DiscretePoint3DKeyFrame Value="1,2,5" KeyTime="0:0:1.5" />

<!-- Using a SplinePoint3DKeyFrame, the camera moves back to its starting point. The
animation starts out slowly at first and then speeds up. This KeyFrame ends
after the fourth second. -->
<SplinePoint3DKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0,0,2" KeyTime="0:0:4" />
</Point3DAnimationUsingKeyFrames.KeyFrames>
</Point3DAnimationUsingKeyFrames>

<!-- As the position of the camera changes using the Point3DAnimation


above, the direction the camera is pointing swivels to keep the object
within the view of the camera. -->
<Vector3DAnimationUsingKeyFrames
Storyboard.TargetName="myPerspectiveCamera"
Storyboard.TargetProperty="LookDirection" >
<Vector3DAnimationUsingKeyFrames.KeyFrames>

<!-- Using a LinearVector3DKeyFrame, the camera swivels steadily from its


starting position down and to the left. This happens over the
first second of the animation. -->
<LinearVector3DKeyFrame Value="-1,-2,-3" KeyTime="0:0:1" />

<!-- Using a DiscreteVector3DKeyFrame, the camera suddenly swivels up. This happens
immdeiately after the first 1 and a half second of the animation. -->
<DiscreteVector3DKeyFrame Value="-1,-1,-3" KeyTime="0:0:1.5" />

<!-- Using a SplineVector3DKeyFrame, the camera swivels back to its starting point.
The animation starts out slowly at first and then speeds up. This KeyFrame ends
after the fourth second. -->
<SplineVector3DKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0,0,-1" KeyTime="0:0:4" />

</Vector3DAnimationUsingKeyFrames.KeyFrames>
</Vector3DAnimationUsingKeyFrames>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>

</Viewbox>
</DockPanel>
</Page>

Vea también
Animar la posición y la dirección de una cámara en una escena 3D
Información general sobre gráficos 3D
Procedimiento Animar propiedades de material en
una escena 3D
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo animar la Opacity propiedad de la Material aplicado a un modelo 3D.
En el ejemplo de código siguiente se define la LinearGradientBrush usa como el Material aplicado al objeto 3D.

<!-- The material specifies the material applied to the plane. In this case it is a linear gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>

<!-- The Opacity property of this LinearGradient is animated. See Storyboard below. -->
<LinearGradientBrush x:Name="myGradientBrush" StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>

El Opacity propiedad de este LinearGradientBrush se anima mediante el ejemplo de código siguiente.

<!-- Trigger the animation when the 3D object loads. -->


<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the opacity of the material applied to the 3D Object. -->
<DoubleAnimation
Storyboard.TargetName="myGradientBrush"
Storyboard.TargetProperty="Opacity"
Duration="0:0:2"
To="0.1"
AutoReverse="True" RepeatBehavior="Forever" />

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>

Ejemplo
El código siguiente muestra el ejemplo completo.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">

<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">

<!-- Defines the camera used to view the 3D object. -->


<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>

<!-- The ModelVisual3D children contain the 3D models -->


<Viewport3D.Children>

<!-- This ModelVisual3D defines the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the light affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>

<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created.
-->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5
" />
</GeometryModel3D.Geometry>
<!-- The material specifies the material applied to the plane. In this case it is a linear
gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>

<!-- The Opacity property of this LinearGradient is animated. See Storyboard below.
-->
<LinearGradientBrush x:Name="myGradientBrush" StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. In this sample, the object is
rotated.-->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
<!-- Trigger the animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- This animation animates the opacity of the material applied to the 3D Object. -->
<DoubleAnimation
Storyboard.TargetName="myGradientBrush"
Storyboard.TargetProperty="Opacity"
Duration="0:0:2"
To="0.1"
AutoReverse="True" RepeatBehavior="Forever" />

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>

Vea también
Crear una escena 3D
Información general sobre gráficos 3D
Procedimiento Hacer una prueba de posicionamiento
en Viewport3D
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo hacer una prueba de posicionamiento para objetos Viewport3Dvisuales 3D en
un.
Dado HitTest que devuelve información en 2D y 3D, es posible recorrer en iteración los resultados de pruebas para
leer solo los resultados 3D.

public void HitTest(object sender, System.Windows.Input.MouseButtonEventArgs args)


{
Point mouseposition = args.GetPosition(myViewport);
Point3D testpoint3D = new Point3D(mouseposition.X, mouseposition.Y, 0);
Vector3D testdirection = new Vector3D(mouseposition.X, mouseposition.Y, 10);
PointHitTestParameters pointparams = new PointHitTestParameters(mouseposition);
RayHitTestParameters rayparams = new RayHitTestParameters(testpoint3D, testdirection);

//test for a result in the Viewport3D


VisualTreeHelper.HitTest(myViewport, null, HTResult, pointparams);

Public Sub HitTest(ByVal sender As Object, ByVal args As MouseButtonEventArgs)


Dim mouseposition As Point = args.GetPosition(myViewport)
Dim testpoint3D As New Point3D(mouseposition.X, mouseposition.Y, 0)
Dim testdirection As New Vector3D(mouseposition.X, mouseposition.Y, 10)
Dim pointparams As New PointHitTestParameters(mouseposition)
Dim rayparams As New RayHitTestParameters(testpoint3D, testdirection)

'test for a result in the Viewport3D


VisualTreeHelper.HitTest(myViewport, Nothing, AddressOf HTResult, pointparams)

HitTestResultBehavior En el código siguiente se determina cómo se procesan los resultados de las pruebas de
posicionamiento. UpdateResultInfo y UpdateMaterial son métodos definidos localmente.

public HitTestResultBehavior HTResult(System.Windows.Media.HitTestResult rawresult)


{
//MessageBox.Show(rawresult.ToString());
RayHitTestResult rayResult = rawresult as RayHitTestResult;

if (rayResult != null)
{
RayMeshGeometry3DHitTestResult rayMeshResult = rayResult as RayMeshGeometry3DHitTestResult;

if (rayMeshResult != null)
{
GeometryModel3D hitgeo = rayMeshResult.ModelHit as GeometryModel3D;

UpdateResultInfo(rayMeshResult);
UpdateMaterial(hitgeo, (side1GeometryModel3D.Material as MaterialGroup));
}
}

return HitTestResultBehavior.Continue;
}
Public Function HTResult(ByVal rawresult As HitTestResult) As HitTestResultBehavior
Dim rayResult As RayHitTestResult = TryCast(rawresult, RayHitTestResult)

If rayResult IsNot Nothing Then


Dim rayMeshResult As RayMeshGeometry3DHitTestResult = TryCast(rayResult,
RayMeshGeometry3DHitTestResult)

If rayMeshResult IsNot Nothing Then


Dim hitgeo As GeometryModel3D = TryCast(rayMeshResult.ModelHit, GeometryModel3D)

UpdateResultInfo(rayMeshResult)
UpdateMaterial(hitgeo, (TryCast(side1GeometryModel3D.Material, MaterialGroup)))
End If
End If

Return HitTestResultBehavior.Continue
End Function
Procedimiento Comprobar la igualdad y la
desigualdad de estructuras Point4D
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo probar Point4D estructuras de igualdad y desigualdad.


El código siguiente muestra cómo probar Point4D estructuras de igualdad y desigualdad mediante el Point4D
métodos de igualdad. El Point4D estructuras se comprueban si son iguales mediante la igualdad sobrecargado ( ==
) operador, a continuación, para desigualdad utilizando la desigualdad sobrecargado ( != ) (operador) y, finalmente,
un Point3D estructura y un Point4D estructura se comprueban para la igualdad con estático Equals método.

Ejemplo
// instantiate Points
Point4D point4D1 = new Point4D();
Point4D point4D2 = new Point4D(15, 40, 60, 75);
Point3D point3D1 = new Point3D(15, 40, 60);

// result variables
Boolean areEqual;
Boolean areNotEqual;
String stringResult;

// defining x,y,z,w of point1


point4D1.X = 10;
point4D1.Y = 5;
point4D1.Z = 1;
point4D1.W = 4;

// checking if Points are equal


areEqual = point4D1 == point4D2;

// areEqual is False

// checking if Points are not equal


areNotEqual = point4D1 != point4D2;
// areNotEqual is True

if (Point4D.Equals(point4D1, point3D1))
{
// the if condition is not true, so this block will not execute
stringResult = "Both objects are Point4D structures and they are equal";
}

else
{
// the if condition is false, so this branch will execute
stringResult = "Parameters are not both Point4D strucutres, or they are but are not equal";
}

Vea también
Equality
Inequality
Equals
Información general sobre animaciones
20/02/2020 • 38 minutes to read • Edit Online

Windows Presentation Foundation (WPF ) proporciona un conjunto eficaz de características de


gráficos y diseño que permiten crear interfaces de usuario atractivas y documentos atractivos. Las
animaciones pueden hacer que una interfaz de usuario sea más vistosa y práctica. Simplemente
animar un color de fondo o aplicar un Transformanimado, puede crear transiciones de pantalla
espectaculares o proporcionar indicaciones visuales útiles.
Esta información general proporciona una introducción al sistema de control de tiempo y
animación de WPF. Se centra en la animación de WPF objetos mediante guiones gráficos.

Introducción a las animaciones


Una animación es una ilusión que se crea mediante el cambio rápido entre una serie de imágenes,
cada una de las cuales es ligeramente diferente de la anterior. El cerebro percibe el grupo de
imágenes como una sola escena cambiante. En las películas, este efecto se obtiene mediante el uso
de cámaras que graban muchas fotografías, o fotogramas, cada segundo. Cuando un proyector
reproduce estos fotogramas, los espectadores ven una imagen en movimiento.
La animación en un equipo es similar. Por ejemplo, un programa que hace que un dibujo de un
rectángulo se desvanezca hasta desaparecer de la vista podría funcionar de la siguiente manera.
El programa crea un temporizador.
El programa comprueba el temporizador en los intervalos establecidos para ver cuánto
tiempo ha transcurrido.
Cada vez que el programa comprueba el temporizador, calcula el valor de opacidad actual
del rectángulo en función del tiempo que ha transcurrido.
Después, el programa actualiza el rectángulo con el nuevo valor y lo redibuja.
Antes de WPF, los desarrolladores de Microsoft Windows tenían que crear y administrar sus
propios sistemas de control de tiempo o usar bibliotecas personalizadas especiales. WPF incluye un
sistema de control de tiempo eficaz que se expone a través del código administrado y Lenguaje
XAML (Extensible Application Markup Language) y que está profundamente integrado en el marco
de WPF. La animación WPF facilita la animación de controles y otros objetos gráficos.
WPF controla de forma eficiente todo el trabajo de administración del sistema de control de tiempo
y de actualización de la pantalla que se produce en segundo plano. Proporciona clases de control
de tiempo que permiten centrarse en los efectos que se desea crear, en lugar de la mecánica para
lograr esos efectos. WPF también facilita la creación de sus propias animaciones exponiendo clases
base de animación de las que se pueden heredar sus clases, para generar animaciones
personalizadas. Estas animaciones personalizadas se benefician de la mayoría de las ventajas de
rendimiento de las clases de animación estándar.

Sistema de animación de propiedades de WPF


Si comprende algunos conceptos importantes sobre el sistema de control de tiempo, WPF
animaciones pueden ser más fáciles de usar. Lo más importante es que, en WPF, anima objetos
aplicando animación a sus propiedades individuales. Por ejemplo, para aumentar el tamaño de un
elemento de marco, se animan las propiedades Width y Height. Para hacer que un objeto se atenúe
desde la vista, se anima su propiedad Opacity.
Para tener funcionalidad de animación, una propiedad debe cumplir los tres requisitos siguientes:
Debe ser una propiedad de dependencia.
Debe pertenecer a una clase que hereda de DependencyObject e implementa la interfaz
IAnimatable.
Debe haber un tipo de animación compatible disponible. (Si WPF no proporciona uno,
puede crear el suyo propio. Vea la información general sobre animaciones personalizadas).
WPF contiene muchos objetos que tienen IAnimatable propiedades. Los controles como Button y
TabControl, y también los objetos Panel y Shape heredan de DependencyObject. La mayoría de sus
propiedades son propiedades de dependencia.
Las animaciones pueden usarse casi en cualquier parte, lo que incluye estilos y plantillas de control.
Las animaciones no tienen que ser visuales; puede animar objetos que no formen parte de la
interfaz de usuario siempre y cuando cumplan los criterios que se describen en esta sección.

Ejemplo: Hacer que un elemento se intensifique y se atenúe


hasta desaparecer
En este ejemplo se muestra cómo usar una animación WPF para animar el valor de una propiedad
de dependencia. Utiliza un DoubleAnimation, que es un tipo de animación que genera valores
Double, para animar la propiedad Opacity de un Rectangle. Como resultado, el Rectangle atenúa y
sale de la vista.
En la primera parte del ejemplo se crea un elemento Rectangle. En los pasos siguientes se muestra
cómo crear una animación y aplicarla a la propiedad Opacity del rectángulo.
A continuación se muestra cómo crear un elemento de Rectangle en un StackPanel en XAML.

<StackPanel Margin="10">
<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
</Rectangle>
</StackPanel>

A continuación se muestra cómo crear un elemento de Rectangle en un StackPanel en el código.

var myPanel = new StackPanel();


myPanel.Margin = new Thickness(10);

var myRectangle = new Rectangle();


myRectangle.Name = "myRectangle";
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;
myPanel.Children.Add(myRectangle);
this.Content = myPanel;
Dim myPanel As New StackPanel()
myPanel.Margin = New Thickness(10)

Dim myRectangle As New Rectangle()


myRectangle.Name = "myRectangle"
Me.RegisterName(myRectangle.Name, myRectangle)
myRectangle.Width = 100
myRectangle.Height = 100
myRectangle.Fill = Brushes.Blue

myPanel.Children.Add(myRectangle)
Me.Content = myPanel

Parte 1: Crear una DoubleAnimation


Una manera de hacer que un elemento se atenúe y no está en la vista es animar su propiedad
Opacity. Dado que la propiedad Opacity es de tipo Double, necesita una animación que genere
valores double. Una DoubleAnimation es una animación de este tipo. Un DoubleAnimation crea
una transición entre dos valores double. Para especificar su valor inicial, establezca su propiedad
From. Para especificar su valor final, establezca su propiedad To.
1. Un valor de opacidad de 1.0 hace que el objeto sea completamente opaco y un valor de
opacidad de 0.0 hace que sea completamente invisible. Para que la transición de la
animación de 1.0 a 0.0 establezca su propiedad From en 1.0 y su propiedad To en 0.0 .
A continuación se muestra cómo crear un DoubleAnimation en XAML.

<DoubleAnimation From="1.0" To="0.0" />

A continuación se muestra cómo crear un DoubleAnimation en el código.

var myDoubleAnimation = new DoubleAnimation();


myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;

Dim myDoubleAnimation As New DoubleAnimation()


myDoubleAnimation.From = 1.0
myDoubleAnimation.To = 0.0

2. A continuación, debe especificar un Duration. El Duration de una animación especifica


cuánto tiempo se tarda en pasar de su valor inicial a su valor de destino. A continuación se
muestra cómo establecer el Duration en cinco segundos en XAML.

<DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" />

A continuación se muestra cómo establecer el Duration en cinco segundos en el código.

myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));

myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))

3. En el código anterior se mostró una animación que realiza la transición de 1.0 a 0.0 , lo
que hace que el elemento de destino se atenúe desde completamente opaco hasta
totalmente invisible. Para que el elemento se atenúe hacia la vista después de desaparecer,
establezca la propiedad AutoReverse de la animación en true . Para que la animación se
repita indefinidamente, establezca su propiedad RepeatBehavior en Forever. A continuación
se muestra cómo establecer las propiedades AutoReverse y RepeatBehavior en XAML.

<DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" AutoReverse="True"


RepeatBehavior="Forever"/>

A continuación se muestra cómo establecer las propiedades AutoReverse y RepeatBehavior


en el código.

myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

myDoubleAnimation.AutoReverse = True
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever

Parte 2: Crear un guion gráfico


Para aplicar una animación a un objeto, se crea un Storyboard y se usan las propiedades adjuntas
TargetName y TargetProperty para especificar el objeto y la propiedad que se va a animar.
1. Cree el Storyboard y agregue la animación como su elemento secundario. A continuación se
muestra cómo crear el Storyboard en XAML.

<Storyboard>
<DoubleAnimation
From="1.0" To="0.0" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>

Para crear el Storyboard en el código, declare una variable de Storyboard en el nivel de clase.

public partial class MainWindow : Window


{
private Storyboard myStoryboard;

Class MainWindow

Private myStoryboard As Storyboard

A continuación, inicialice el Storyboard y agregue la animación como su elemento


secundario.

myStoryboard = new Storyboard();


myStoryboard.Children.Add(myDoubleAnimation);

myStoryboard = New Storyboard()


myStoryboard.Children.Add(myDoubleAnimation)

2. El Storyboard tiene que saber dónde aplicar la animación. Utilice la propiedad adjunta
Storyboard.TargetName para especificar el objeto que se va a animar. A continuación se
muestra cómo establecer el nombre de destino del DoubleAnimation en MyRectangle en
XAML.

<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
From="1.0" To="0.0" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>

A continuación se muestra cómo establecer el nombre de destino del DoubleAnimation en


MyRectangle en el código.

Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);

Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name)

3. Utilice la propiedad adjunta TargetProperty para especificar la propiedad que se va a animar.


A continuación se muestra cómo se configura la animación para tener como destino la
propiedad Opacity del Rectangle en XAML.

<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>

A continuación se muestra cómo se configura la animación para tener como destino la


propiedad Opacity del Rectangle en el código.

Storyboard.SetTargetProperty(myDoubleAnimation, new
PropertyPath(Rectangle.OpacityProperty));

Storyboard.SetTargetProperty(myDoubleAnimation, New
PropertyPath(Rectangle.OpacityProperty))

Para obtener más información sobre la sintaxis de TargetProperty y para obtener ejemplos
adicionales, vea la información general sobre los guiones gráficos.
Parte 3 (XAML ): Asociar el guion gráfico a un desencadenador
La manera más fácil de aplicar e iniciar un Storyboard en XAML es usar un desencadenador de
eventos. En esta sección se muestra cómo asociar el Storyboard con un desencadenador en XAML.
1. Cree un objeto de BeginStoryboard y asocie su guion gráfico. Un BeginStoryboard es un
tipo de TriggerAction que se aplica e inicia una Storyboard.
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>

2. Cree un EventTrigger y agregue el BeginStoryboard a su colección Actions. Establezca la


propiedad RoutedEvent del EventTrigger en el evento enrutado en el que desea iniciar el
Storyboard. (Para obtener más información sobre los eventos enrutados, vea información
general sobre eventos enrutados).

<!-- Animates the rectangle's opacity. -->


<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>

3. Agregue el EventTrigger a la colección de Triggers del rectángulo.

<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

Parte 3 (código ): Asociar el guion gráfico a un controlador de eventos


La forma más fácil de aplicar e iniciar un Storyboard en el código es usar un controlador de
eventos. En esta sección se muestra cómo asociar el Storyboard con un controlador de eventos en
el código.
1. Regístrese para el evento Loaded del rectángulo.

myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);


AddHandler myRectangle.Loaded, AddressOf myRectangleLoaded

2. Declare el controlador de eventos. En el controlador de eventos, use el método Begin para


aplicar el guión gráfico.

private void myRectangleLoaded(object sender, RoutedEventArgs e)


{
myStoryboard.Begin(this);
}

Private Sub myRectangleLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)


myStoryboard.Begin(Me)
End Sub

Ejemplo completo
A continuación se muestra cómo crear un rectángulo que se intensifica y se atenúa en la vista en
XAML.

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Margin="10">
<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
</Grid>
</Window>

A continuación se muestra cómo crear un rectángulo que se intensifica y se atenúa hasta


desaparecer en el código.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace WpfApplication1
{
public partial class MainWindow : Window
{
private Storyboard myStoryboard;

public MainWindow()
{
InitializeComponent();

StackPanel myPanel = new StackPanel();


myPanel.Margin = new Thickness(10);

Rectangle myRectangle = new Rectangle();


myRectangle.Name = "myRectangle";
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;

DoubleAnimation myDoubleAnimation = new DoubleAnimation();


myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

myStoryboard = new Storyboard();


myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new
PropertyPath(Rectangle.OpacityProperty));

// Use the Loaded event to start the Storyboard.


myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);
myPanel.Children.Add(myRectangle);
this.Content = myPanel;
}

private void myRectangleLoaded(object sender, RoutedEventArgs e)


{
myStoryboard.Begin(this);
}
}
}
Imports System.Windows.Media.Animation

Class MainWindow

Private myStoryboard As Storyboard

Public Sub New()


InitializeComponent()

Dim myPanel As New StackPanel()


myPanel.Margin = New Thickness(10)

Dim myRectangle As New Rectangle()


myRectangle.Name = "myRectangle"
Me.RegisterName(myRectangle.Name, myRectangle)
myRectangle.Width = 100
myRectangle.Height = 100
myRectangle.Fill = Brushes.Blue

Dim myDoubleAnimation As New DoubleAnimation()


myDoubleAnimation.From = 1.0
myDoubleAnimation.To = 0.0
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))
myDoubleAnimation.AutoReverse = True
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever

myStoryboard = New Storyboard()


myStoryboard.Children.Add(myDoubleAnimation)
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name)
Storyboard.SetTargetProperty(myDoubleAnimation, New
PropertyPath(Rectangle.OpacityProperty))

' Use the Loaded event to start the Storyboard.


AddHandler myRectangle.Loaded, AddressOf myRectangleLoaded

myPanel.Children.Add(myRectangle)
Me.Content = myPanel
End Sub

Private Sub myRectangleLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)


myStoryboard.Begin(Me)
End Sub

End Class

Tipos de animación
Dado que las animaciones generan valores de propiedad, existen distintos tipos de animaciones
para los diversos tipos de propiedades. Para animar una propiedad que toma un Double, como la
propiedad Width de un elemento, utilice una animación que genere valores Double. Para animar
una propiedad que toma un Point, utilice una animación que genere valores de Point, etc. Debido al
número de tipos de propiedad diferentes, hay varias clases de animación en el espacio de nombres
System.Windows.Media.Animation. Afortunadamente se rigen por una convención de
nomenclatura estricta que hace que sea fácil diferenciarlas:
<Tipo>Animation
Conocidas como animaciones "From/To/By" o "basic", generan una animación entre un
valor inicial y de destino o agregan un valor de desplazamiento al valor inicial.
Para especificar un valor inicial, establezca la propiedad From de la animación.
Para especificar un valor final, establezca la propiedad To de la animación.
Para especificar un valor de desplazamiento, establezca la propiedad By de la
animación.
En los ejemplos de este tema se incluyen estas animaciones porque son las más fáciles de
usar. Las animaciones From/to/by se describen en detalle en la información general de las
animaciones From/to/by.
<Tipo>AnimationUsingKeyFrames
Las animaciones de fotogramas clave son más eficaces que las animaciones From/To/By
porque se puede especificar cualquier número de valores de destino e incluso controlar su
método de interpolación. Algunos tipos solo se pueden animar con animaciones de
fotogramas clave. Las animaciones de fotogramas clave se describen en detalle en
información general sobre animaciones de fotogramas clave.
<Tipo>AnimationUsingPath
Las animaciones de trazado permiten usar un trazado geométrico para generar valores
animados.
<Tipo>AnimationBase
Clase abstracta que, cuando se implementa, anima un valor de <Tipo>. Esta clase actúa
como clase base para las clases <Tipo>Animation y <Tipo>AnimationUsingKeyFrames.
Tiene que tratar directamente con estas clases solo si desea crear sus propias animaciones
personalizadas. En caso contrario, use <Tipo>Animation o KeyFrame<Tipo>Animation.
En la mayoría de los casos, querrá usar el tipode <> clases de animación, como DoubleAnimation y
ColorAnimation.
En la tabla siguiente se muestran varios tipos de animación comunes y algunas propiedades con las
que se usan.

ANIMACIÓN DE
ANIMACIÓN BÁSICA FOTOGRAMAS ANIMACIÓN DE
TIPO DE CORRESPONDIENTE CLAVE TRAZADO
PROPIEDAD (FROM/TO/BY) CORRESPONDIENTE CORRESPONDIENTE EJEMPLO DE USO

Color ColorAnimation ColorAnimationUsi None Animar el Color de


ngKeyFrames un
SolidColorBrush o
un GradientStop.

Double DoubleAnimation DoubleAnimation DoubleAnimation Animar el Width


UsingKeyFrames UsingPath de un DockPanel o
Height de un
Button.

Point PointAnimation PointAnimationUsi PointAnimationUsi Animar la posición


ngKeyFrames ngPath Center de un
EllipseGeometry.

String None StringAnimationUs None Animar el Text de


ingKeyFrames un TextBlock o
Content de un
Button.

Las animaciones son escalas de tiempo


Todos los tipos de animación heredan de la clase Timeline; por lo tanto, todas las animaciones son
tipos especializados de escalas de tiempo. Un Timeline define un segmento de tiempo. Puede
especificar los comportamientos de control de tiempo de una escala de tiempo: su Duration,
cuántas veces se repiten e incluso cuánto tiempo progresa.
Dado que una animación es un Timeline, también representa un segmento de tiempo. Una
animación también calcula los valores de salida a medida que progresa a través de su segmento de
tiempo especificado (o Duration). A medida que la animación avanza, o se "reproduce", actualiza la
propiedad a la que está asociada.
Tres propiedades de temporización usadas con frecuencia son Duration, AutoReversey
RepeatBehavior.
Propiedad Duration
Como se ha mencionado previamente, una escala de tiempo representa un segmento de tiempo. La
longitud de ese segmento viene determinada por el Duration de la escala de tiempo, que
normalmente se especifica mediante un valor de TimeSpan. Cuando una escala de tiempo llega al
final de su duración, ha completado una iteración.
Una animación utiliza su propiedad Duration para determinar su valor actual. Si no se especifica un
valor de Duration para una animación, se usa 1 segundo, que es el valor predeterminado.
La sintaxis siguiente muestra una versión simplificada de la sintaxis de atributo de Lenguaje XAML
(Extensible Application Markup Language) para la propiedad Duration.
horas : minutos : segundos
En la tabla siguiente se muestran varias configuraciones de Duration y sus valores resultantes.

CONFIGURACIÓN VALOR RESULTANTE

0:0:5.5 5,5 segundos.

0:30:5.5 30 minutos y 5,5 segundos.

1:30:5.5 1 hora, 30 minutos y 5,5 segundos.

Una manera de especificar un Duration en el código es usar el método FromSeconds para crear un
TimeSpany, a continuación, declarar una nueva estructura de Duration usando esa TimeSpan.
Para obtener más información sobre los valores de Duration y la sintaxis de Lenguaje XAML
(Extensible Application Markup Language) completa, vea la estructura Duration.
AutoReverse
La propiedad AutoReverse especifica si una escala de tiempo se reproduce hacia atrás una vez que
llega al final de su Duration. Si establece esta propiedad de animación en true , una animación
invierte una vez que llega al final de su Durationy reproduce desde su valor final hasta su valor
inicial. De forma predeterminada, esta propiedad es false .
RepeatBehavior
La propiedad RepeatBehavior especifica el número de veces que se reproduce una escala de
tiempo. De forma predeterminada, las escalas de tiempo tienen un recuento de iteraciones de 1.0 ,
lo que significa que se reproducen una vez y no se repiten.
Para obtener más información acerca de estas propiedades y otras, consulte la información general
sobre los comportamientos de control de tiempo.

Aplicar una animación a una propiedad


En las secciones anteriores se han descrito los distintos tipos de animaciones y sus propiedades de
control de tiempo. En esta sección se muestra cómo aplicar la animación a la propiedad que se
desea animar. Storyboard objetos proporcionan una manera de aplicar animaciones a propiedades.
Un Storyboard es una escala de tiempo contenedora que proporciona información de destino para
las animaciones que contiene.
Objetos y propiedades de destino
La clase Storyboard proporciona las propiedades adjuntas TargetName y TargetProperty. Al
establecer estas propiedades en una animación, se indica a la animación qué debe animar. Sin
embargo, para que una animación pueda tener un objeto como destino, normalmente se debe dar
un nombre al objeto.
Asignar un nombre a un FrameworkElement difiere de asignar un nombre a un objeto Freezable.
La mayoría de los controles y paneles son elementos de marco, pero los objetos gráficos más
puros, como los pinceles, las transformaciones y las formas geométricas, son objetos
inmovilizables. Si no está seguro de si un tipo es un FrameworkElement o un Freezable, consulte la
sección jerarquía de herencia de su documentación de referencia.
Para convertir un FrameworkElement en un destino de animación, asígnele un nombre
estableciendo su propiedad Name. En el código, también debe usar el método
RegisterName para registrar el nombre del elemento con la página a la que pertenece.
Para convertir un objeto de Freezable en un destino de animación en XAML, se usa la
Directiva x:Name para asignarle un nombre. En el código, solo se usa el método
RegisterName para registrar el objeto con la página a la que pertenece.
En las secciones siguientes se proporciona un ejemplo de cómo asignar un nombre a un elemento
en XAML y en el código. Para obtener información más detallada sobre la asignación de nombres y
destinos, vea la información general sobre los guiones gráficos.
Aplicar e iniciar guiones gráficos
Para iniciar un guion gráfico en XAML, debe asociarlo a un EventTrigger. Un EventTrigger es un
objeto que describe qué acciones se deben llevar a cabo cuando se produce un evento especificado.
Una de esas acciones puede ser una acción BeginStoryboard, que se usa para iniciar el guion
gráfico. Los desencadenadores de eventos son similares en concepto a los controladores de
eventos, porque permiten especificar cómo responde una aplicación a un evento determinado. A
diferencia de los controladores de eventos, los desencadenadores de eventos se pueden describir
totalmente en XAML; no se requiere ningún otro código.
Para iniciar un Storyboard en el código, puede usar un EventTrigger o utilizar el método Begin de la
clase Storyboard.

Control interactivo de guiones gráficos


En el ejemplo anterior se mostró cómo iniciar un Storyboard cuando se produce un evento.
También puede controlar interactivamente un Storyboard una vez que se inicia: puede pausar,
reanudar, detener, avanzar a su período de relleno, buscar y quitar el Storyboard. Para obtener más
información y un ejemplo en el que se muestra cómo controlar interactivamente un Storyboard,
vea la información general sobre los guiones gráficos.

Comportamiento tras la finalización de una animación


La propiedad FillBehavior especifica cómo se comporta una escala de tiempo cuando finaliza. De
forma predeterminada, una escala de tiempo comienza Filling cuando finaliza. Una animación que
se Filling contiene su valor de salida final.
El DoubleAnimation del ejemplo anterior no finaliza porque su propiedad RepeatBehavior está
establecida en Forever. En el ejemplo siguiente se anima un rectángulo mediante el uso de una
animación similar. A diferencia del ejemplo anterior, las propiedades RepeatBehavior y AutoReverse
de esta animación se dejan en sus valores predeterminados. Por consiguiente, la animación
progresa de 1 a 0 en cinco segundos y luego se detiene.

<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>

<!-- Animates the rectangle's opacity. -->


<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

DoubleAnimation myDoubleAnimation = new DoubleAnimation();


myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));

Dim myDoubleAnimation As New DoubleAnimation()


myDoubleAnimation.From = 1.0
myDoubleAnimation.To = 0.0
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))

Dado que su FillBehavior no se ha cambiado con respecto a su valor predeterminado, que es


HoldEnd, la animación contiene su valor final, 0, cuando finaliza. Por lo tanto, el Opacity del
rectángulo permanece en 0 una vez finalizada la animación. Si establece el Opacity del rectángulo
en otro valor, el código parece que no tiene ningún efecto, ya que la animación todavía está
afectando a la propiedad Opacity.
Una manera de recuperar el control de una propiedad animada en el código es usar el método
BeginAnimation y especificar null para el parámetro AnimationTimeline. Para obtener más
información y un ejemplo, vea establecer una propiedad después de animarla con un guion gráfico.
Tenga en cuenta que, aunque el valor de una propiedad que tiene una animación Active o Filling
parece no tener ningún efecto, el valor de la propiedad cambia. Para obtener más información, vea
información general sobre el sistema de control de tiempo y animación.

Animaciones con enlace de datos y animaciones animadas


La mayoría de las propiedades de animación pueden estar enlazadas a datos o animarse; por
ejemplo, puede animar la propiedad Duration de una DoubleAnimation. Sin embargo, debido a la
manera en que funciona el sistema de control de tiempo, las animaciones enlazadas a datos o
animadas no se comportan como los demás objetos enlazados a datos o animados. Para entender
su comportamiento, le será útil comprender el significado de aplicar una animación a una
propiedad.
Consulte el ejemplo de la sección anterior que mostraba cómo animar el Opacity de un rectángulo.
Cuando se carga el rectángulo en el ejemplo anterior, su desencadenador de eventos aplica el
Storyboard. El sistema de control de tiempo crea una copia de la Storyboard y su animación. Estas
copias se inmovilizan (se convierten en de solo lectura) y se crean objetos Clock a partir de ellas.
Estos relojes son los que realmente se encargan de animar las propiedades de destino.
El sistema de control de tiempo crea un reloj para el DoubleAnimation y lo aplica al objeto y la
propiedad especificados por el TargetName y TargetProperty del DoubleAnimation. En este caso, el
sistema de control de tiempo aplica el reloj a la propiedad Opacity del objeto denominado
"microrectangle".
Aunque también se crea un reloj para el Storyboard, el reloj no se aplica a ninguna propiedad. Su
finalidad es controlar su reloj secundario, el reloj que se crea para el DoubleAnimation.
Para que una animación refleje cambios de enlace de datos o de animación, su reloj se debe
regenerar. Los relojes no se regeneran automáticamente. Para que una animación refleje los
cambios, vuelva a aplicar su guion gráfico mediante una BeginStoryboard o el método Begin. Al
usar cualquiera de estos métodos, la animación se reinicia. En el código, puede utilizar el método
Seek para volver a desplazar el guion gráfico a su posición anterior.
Para ver un ejemplo de una animación enlazada a datos, vea ejemplo de animación de curva spline
clave. Para obtener más información sobre cómo funciona la animación y el sistema de control de
tiempo, vea información general sobre el sistema de control de tiempo y animación.

Otras maneras de crear animaciones


Los ejemplos de este tema muestran cómo aplicar animaciones mediante guiones gráficos. En el
código se pueden aplicar animaciones de otras maneras. Para obtener más información, vea
información general sobre técnicas de animación de propiedades.

Ejemplos de animaciones
Los ejemplos siguientes pueden ayudarle a familiarizarse con la forma de agregar animaciones a
sus aplicaciones.
Ejemplo de valores de destino de animación From, To y By
Muestra distintas configuraciones From/To/By.
Ejemplo del comportamiento del control de tiempo de la animación
Muestra las distintas maneras de controlar el comportamiento de control de tiempo de una
animación. Este ejemplo también muestra cómo enlazar a datos el valor de destino de una
animación.

Temas relacionados
TÍTULO DESCRIPCIÓN

Información general sobre sistemas de control de Describe cómo el sistema de control de tiempo utiliza
tiempo y animación las clases Timeline y Clock, que permiten crear
animaciones.
TÍTULO DESCRIPCIÓN

Sugerencias y trucos para animaciones Enumera las sugerencias útiles para solucionar
problemas con animaciones, como el rendimiento.

Información general sobre animaciones Describe cómo extender el sistema de animación con
personalizadas fotogramas clave, clases de animación o devoluciones
de llamada por fotograma.

Información general sobre animaciones From/To/By Describe cómo crear una animación que realiza la
transición entre dos valores.

Información general sobre animaciones de Describe cómo crear una animación con varios
fotogramas clave valores de destino, incluida la capacidad de controlar
el método de interpolación.

Funciones de aceleración Explica cómo aplicar fórmulas matemáticas a las


animaciones para obtener un comportamiento
realista, como el rebote.

Información general sobre animaciones en trazados Describe cómo mover o girar un objeto a lo largo de
un trazado complejo.

Información general sobre técnicas de animación de Describe las animaciones de propiedades mediante
propiedades guiones gráficos, animaciones locales, relojes y
animaciones por fotograma.

Información general sobre objetos Storyboard Describe cómo utilizar guiones gráficos con varias
escalas de tiempo para crear animaciones complejas.

Información general sobre comportamientos de Describe los tipos de Timeline y las propiedades que
control de tiempo se usan en las animaciones.

Información general sobre eventos de control de Describe los eventos disponibles en los objetos
tiempo Timeline y Clock para ejecutar el código en los puntos
de la escala de tiempo, como iniciar, pausar, reanudar,
omitir o detener.

Temas "Cómo..." Contiene ejemplos de código para usar animaciones y


escalas de tiempo en una aplicación.

Temas de procedimientos de relojes Contiene ejemplos de código para usar el objeto


Clock en la aplicación.

Temas de procedimientos de fotogramas clave Contiene ejemplos de código para usar animaciones
de fotogramas clave en una aplicación.

Temas de procedimientos de animación de trazado Contiene ejemplos de código para usar animaciones
de trazado en una aplicación.

Referencia
Timeline
Storyboard
BeginStoryboard
Clock
Información general sobre sistemas de
temporización y animación
23/10/2019 • 11 minutes to read • Edit Online

Este tema describe cómo utiliza la animación, el sistema de temporización Timeline, y Clock clases para animar
propiedades.

Requisitos previos
Para entender este tema, debe poder utilizar animaciones WPF para animar propiedades, como se describe en
Información general sobre animaciones. También ayuda conocer las propiedades de dependencia; para más
información, vea Información general sobre las propiedades de dependencia.

Escalas de tiempo y relojes


El información general sobre animaciones se describe cómo un Timeline representa un segmento de tiempo y
una animación es un tipo de Timeline que genera valores de salida. Por sí mismo, un Timeline, no hace nada
más que describir un segmento de tiempo. Es la escala de tiempo Clock objeto que hace el trabajo real. Del
mismo modo, animación realmente no anima las propiedades: una clase de animación describe cómo se deben
calcular los valores de salida, pero es el Clock que se creó para la animación que impulsa la salida de animación
y se aplica a las propiedades.
Un Clock es un tipo especial de objeto que mantiene el estado de tiempo de ejecución relacionados con la
sincronización para el Timeline. Proporciona tres bits de información que son esenciales para el sistema de
temporización y animación: CurrentTime, CurrentProgress, y CurrentState. Un Clock determina su estado, el
progreso y la hora actual utilizando los comportamientos de control de tiempo descritos por sus Timeline:
Duration, RepeatBehavior, AutoReverse, y así sucesivamente.
En la mayoría de los casos, un Clock se crea automáticamente para la escala de tiempo. Al animar utilizando un
Storyboard o BeginAnimation método, relojes automáticamente se crean para sus escalas de tiempo y las
animaciones y se aplican a sus propiedades concretas. También puede crear un Clock explícitamente mediante
el CreateClock método de su Timeline. El MediaTimeline.CreateClock método crea un reloj del tipo adecuado
para el Timeline en que se llama. Si el Timeline contiene escalas de tiempo secundarias, crea Clock objetos
también para ellos. Resultante Clock objetos se organizan en árboles que coinciden con la estructura de la
Timeline desde la que se crean objetos de árbol.
Hay diferentes tipos de relojes para diferentes tipos de escalas de tiempo. La tabla siguiente muestra la Clock
tipos que corresponden a algunos de los diferentes Timeline tipos.

TIPOS DE OBJETOS TIMELINE TIPO DE RELOJ PROPÓSITO DEL RELOJ

Animación (hereda de AnimationClock Genera valores de salida para una


AnimationTimeline) propiedad de dependencia.

MediaTimeline MediaClock Procesa un archivo multimedia.

ParallelTimeline ClockGroup Agrupa y controla su elemento


secundario Clock objetos
TIPOS DE OBJETOS TIMELINE TIPO DE RELOJ PROPÓSITO DEL RELOJ

Storyboard ClockGroup Agrupa y controla su elemento


secundario Clock objetos

Puede aplicar cualquiera AnimationClock objetos crea para las propiedades de dependencia compatibles
utilizando el ApplyAnimationClock método.
En escenarios de rendimiento intensivo, tales como la animación de grandes cantidades de objetos similares,
administrar su propio Clock uso puede proporcionar ventajas de rendimiento.

Los relojes y el administrador de tiempo


Al animar objetos en WPF, es el Administrador de tiempo que administra el Clock objetos creados para las
escalas de tiempo. El administrador de tiempo es la raíz de un árbol de objetos Clock y controla el flujo de
tiempo en ese árbol. El administrador de tiempo se crea automáticamente para cada aplicación WPF y no es
visible para el desarrollador de aplicaciones. El administrador de tiempo "marca pasos" muchas veces por
segundo; el número real de pasos que se producen cada segundo varía, en función de los recursos disponibles
en el sistema. Durante cada uno de estos pasos, el Administrador de tiempo calcula el estado de todos los
Active Clock objetos en el árbol de control de tiempo.
La siguiente ilustración muestra la relación entre el Administrador de tiempo, y AnimationClocky una
propiedad de dependencia animada.

Animación de una propiedad


Cuando el Administrador de tiempo tics, actualiza el tiempo de cada Active Clock en la aplicación. Si el Clock es
un AnimationClock, usa el GetCurrentValue método de la AnimationTimeline desde que se creó calcular su
actual valor de salida. El AnimationClock proporciona el AnimationTimeline con la hora local actual, un valor de
entrada, que normalmente es el valor de la propiedad base y un valor de destino predeterminado. Cuando se
recupera el valor de un elemento animado por propiedad utilizando el GetValue método o su descriptor de
acceso CLR, obtendrá el resultado de su AnimationClock.
Grupos de relojes
La sección anterior describió cómo hay diferentes tipos de Clock objetos para los distintos tipos de escalas de
tiempo. La siguiente ilustración muestra la relación entre el Administrador de tiempo, un ClockGroup, un
AnimationClocky una propiedad de dependencia animada. Un ClockGroup se crea para las escalas de tiempo
que agrupan otras escalas de tiempo, como el Storyboard (clase), que agrupa animaciones y otras escalas de
tiempo.

Un objeto ClockGroup
Composición
Es posible asociar varios relojes a una única propiedad, en cuyo caso cada reloj utiliza el valor de salida del reloj
anterior como su valor base. La siguiente ilustración muestra tres AnimationClock objetos que se aplica a la
misma propiedad. El reloj1 utiliza el valor base de la propiedad animada como entrada y lo utiliza para generar
la salida. El reloj2 toma la salida del reloj1 como entrada y lo utiliza para generar la salida. El reloj3 toma la
salida del reloj2 como entrada y lo utiliza para generar la salida. Cuando varios relojes afectan simultáneamente
a la misma propiedad, se dice que están en una cadena de composición.

Una cadena de composición


Tenga en cuenta que aunque se crea una relación entre la entrada y salida de la AnimationClock objetos en la
cadena de composición, sus comportamientos de control de tiempo no se ven afectados; Clock objetos
(incluidos AnimationClock objetos) tiene una dependencia jerárquica de sus principales Clock objetos.
Para aplicar varios relojes a la misma propiedad, utilice el Compose HandoffBehavior al aplicar un Storyboard,
animación, o AnimationClock.
Pasos y consolidación de eventos
Además de calcular valores de salida, el administrador de tiempo hace otras cosas a cada paso que marca:
determina el estado de cada reloj y genera los eventos adecuados.
Aunque los ciclos se producen con frecuencia, pueden ocurrir muchas cosas entre ellos. Por ejemplo, un Clock
podría detenido, iniciar y detener de nuevo, en cuyo caso su CurrentState valor habrá cambiado tres veces. En
teoría, el CurrentStateInvalidated evento podría generarse varias veces en un único paso; sin embargo, el motor
de tiempo consolida los eventos, para que el CurrentStateInvalidated evento puede generarse como máximo
una vez por tic-tac. Esto es cierto para todos los eventos de control de tiempo: a lo sumo un evento de cada tipo
se genera para un determinado Clock objeto.
Cuando un Clock cambia de estado y devuelve a su estado original entre pasos (como el cambio de Active a
Stopped y volver a Active), el evento asociado continúa produciéndose.
Para más información acerca de los eventos de control de tiempo, vea Información general sobre eventos de
control de tiempo.

Valores actuales y valores base de propiedades


Una propiedad que se pueda animar puede tener dos valores: un valor base y un valor actual. Al establecer la
propiedad mediante su descriptor de acceso CLR o SetValue método, establezca su valor base. Cuando no se
anima una propiedad, su valor base y su valor actual son el mismo.
Al animar una propiedad, el AnimationClock establece la propiedad actual valor. Recuperar el valor de
propiedad a través de su descriptor de acceso CLR o el GetValue método devuelve el resultado de la
AnimationClock cuando el AnimationClock es Active o Filling. Puede recuperar el valor de la propiedad base
mediante el GetAnimationBaseValue método.

Vea también
Información general sobre animaciones
Información general sobre eventos de control de tiempo
Información general sobre comportamientos de control de tiempo
Sugerencias y trucos para animaciones
08/01/2020 • 15 minutes to read • Edit Online

Al trabajar con animaciones en WPF, hay una serie de sugerencias y trucos que pueden hacer que las animaciones
funcionen mejor y ahorren frustraciones.

Problemas generales
Al animar la posición de una barra de desplazamiento o de un control deslizante, se inmoviliza
Si anima la posición de una barra de desplazamiento o un control deslizante mediante una animación que tiene
una FillBehavior de HoldEnd (el valor predeterminado), el usuario ya no podrá mover la barra de desplazamiento o
el control deslizante. Esto se debe a que, aunque la animación finaliza, continúa invalidando el valor base de la
propiedad de destino. Para que la animación deje de invalidar el valor actual de la propiedad, quítelo o asígnele un
FillBehavior de Stop. Para obtener más información y un ejemplo, vea establecer una propiedad después de
animarla con un guion gráfico.
Animar la salida de una animación no surte ningún efecto
No se puede animar ningún objeto que sea la salida de otra animación. Por ejemplo, si usa un
ObjectAnimationUsingKeyFrames para animar el Fill de una Rectangle de una RadialGradientBrush a una
SolidColorBrush, no puede animar las propiedades de la RadialGradientBrush o SolidColorBrush.
No se puede cambiar el valor de una propiedad después de animarla
En algunos casos, puede parecer que no es posible cambiar el valor de una propiedad después de animarla, incluso
después de que la animación haya finalizado. Esto se debe a que, aunque la animación finaliza, continúa
invalidando el valor base de la propiedad. Para que la animación deje de invalidar el valor actual de la propiedad,
quítelo o asígnele un FillBehavior de Stop. Para obtener más información y un ejemplo, vea establecer una
propiedad después de animarla con un guion gráfico.
Cambiar una escala de tiempo no surte ningún efecto
Aunque la mayoría de las propiedades de Timeline se pueden animar y enlazar a datos, el cambio de los valores de
propiedad de una Timeline activa parece no tener ningún efecto. Esto se debe a que, cuando se inicia un Timeline,
el sistema de control de tiempo realiza una copia del Timeline y lo usa para crear un objeto Clock. Modificar el
original no surte ningún efecto en la copia del sistema.
Para que un Timeline refleje los cambios, su reloj se debe volver a generar y usar para reemplazar el reloj creado
previamente. Los relojes no se regeneran automáticamente. A continuación se muestran distintas maneras de
aplicar cambios a las escalas de tiempo:
Si la escala de tiempo es o pertenece a un Storyboard, puede hacer que refleje los cambios reaplicando su
guion gráfico mediante un BeginStoryboard o el método Begin. El efecto secundario de esta acción es que
también se reinicia la animación. En el código, puede utilizar el método Seek para hacer avanzar el guión
gráfico hasta su posición anterior.
Si aplicó una animación directamente a una propiedad mediante el método BeginAnimation, llame de
nuevo al método BeginAnimation y pásele la animación que se ha modificado.
Si está trabajando directamente en el nivel de relojes, cree y aplique un nuevo conjunto de relojes y
utilícelos para reemplazar el conjunto anterior de relojes generados.
Para obtener más información acerca de las escalas de tiempo y los relojes, consulte información general sobre
sistemas de control de tiempo y animación.
FillBehavior.Stop no funciona como se espera
Hay ocasiones en las que el establecimiento de la propiedad FillBehavior en Stop parece no tener ningún efecto,
como cuando una animación "se entrega" a otra porque tiene un valor HandoffBehavior de SnapshotAndReplace.
En el ejemplo siguiente se crea un Canvas, un Rectangle y un TranslateTransform. El TranslateTransform se animará
para mover el Rectangle alrededor de la Canvas.

<Canvas Width="600" Height="200">


<Rectangle
Canvas.Top="50" Canvas.Left="0"
Width="50" Height="50" Fill="Red">
<Rectangle.RenderTransform>
<TranslateTransform
x:Name="MyTranslateTransform"
X="0" Y="0" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>

En los ejemplos de esta sección se usan los objetos anteriores para mostrar varios casos en los que la propiedad
FillBehavior no se comporte como cabría esperar.
FillBehavior="Stop" y HandoffBehavior con varias animaciones
A veces parece que una animación omite su FillBehavior propiedad cuando se reemplaza por una segunda
animación. Tome el ejemplo siguiente, que crea dos objetos Storyboard y los usa para animar la misma
TranslateTransform que se muestra en el ejemplo anterior.
La primera Storyboard, B1 , anima la propiedad X de la TranslateTransform de 0 a 350, que mueve el rectángulo
350 píxeles a la derecha. Cuando la animación alcanza el final de su duración y deja de reproducirse, la propiedad
X vuelve a su valor original, 0. Como resultado, el rectángulo se mueve 350 píxeles a la derecha y luego salta para
situarse en su posición original.

<Button Content="Start Storyboard B1">


<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard x:Name="B1">
<DoubleAnimation
Storyboard.TargetName="MyTranslateTransform"
Storyboard.TargetProperty="X"
From="0" To="350" Duration="0:0:5"
FillBehavior="Stop"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

La segunda Storyboard, B2 , también anima la propiedad X de la misma TranslateTransform. Dado que solo se
establece la propiedad To de la animación de este Storyboard, la animación utiliza el valor actual de la propiedad
que anima como su valor de inicio.
<!-- Animates the same object and property as the preceding
Storyboard. -->
<Button Content="Start Storyboard B2">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard x:Name="B2">
<DoubleAnimation
Storyboard.TargetName="MyTranslateTransform"
Storyboard.TargetProperty="X"
To="500" Duration="0:0:5"
FillBehavior="Stop" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

Si hace clic en el segundo botón mientras se reproduce el primer Storyboard, es posible que espere el siguiente
comportamiento:
1. El primer guion gráfico finaliza y devuelve el rectángulo a su posición original, porque la animación tiene
una FillBehavior de Stop.
2. El segundo guion gráfico se lleva a efecto y anima el objeto a partir de la posición actual, que ahora es 0,
hasta 500.
Pero esto no es lo que sucede. En lugar de ello, el rectángulo no salta a su posición original, sino que continúa
moviéndose a la derecha. Esto se debe a que la segunda animación utiliza el valor actual de la primera animación
como su valor inicial y anima desde ese valor hasta 500. Cuando la segunda animación reemplaza la primera
porque se usa el HandoffBehavior SnapshotAndReplace, el FillBehavior de la primera animación no importa.
FillBehavior y el evento Completed
En los siguientes ejemplos se muestra otro escenario en el que parece que el FillBehavior de Stopno tiene ningún
efecto. De nuevo, en el ejemplo se usa un guion gráfico para animar la propiedad X de la TranslateTransform de 0 a
350. Sin embargo, esta vez el ejemplo se registra para el evento Completed.

<Button Content="Start Storyboard C">


<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard Completed="StoryboardC_Completed">
<DoubleAnimation
Storyboard.TargetName="MyTranslateTransform"
Storyboard.TargetProperty="X"
From="0" To="350" Duration="0:0:5"
FillBehavior="Stop" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

El controlador de eventos Completed inicia otro Storyboard que anima la misma propiedad desde su valor actual
hasta 500.
private void StoryboardC_Completed(object sender, EventArgs e)
{

Storyboard translationAnimationStoryboard =
(Storyboard)this.Resources["TranslationAnimationStoryboardResource"];
translationAnimationStoryboard.Begin(this);
}

Private Sub StoryboardC_Completed(ByVal sender As Object, ByVal e As EventArgs)

Dim translationAnimationStoryboard As Storyboard =


CType(Me.Resources("TranslationAnimationStoryboardResource"), Storyboard)
translationAnimationStoryboard.Begin(Me)
End Sub

A continuación se indica el marcado que define el segundo Storyboard como un recurso.

<Page.Resources>
<Storyboard x:Key="TranslationAnimationStoryboardResource">
<DoubleAnimation
Storyboard.TargetName="MyTranslateTransform"
Storyboard.TargetProperty="X"
To="500" Duration="0:0:5" />
</Storyboard>
</Page.Resources>

Al ejecutar el Storyboard, puede esperar que la propiedad X de la TranslateTransform se anime de 0 a 350 y, a


continuación, vuelva a 0 después de completarse (porque tiene un valor FillBehavior de Stop) y, a continuación, se
anima desde 0 hasta 500. En su lugar, el TranslateTransform anima de 0 a 350 y, a continuación, a 500.
Esto se debe a que el orden en que WPF genera eventos y porque los valores de propiedad se almacenan en caché
y no se recalculan a menos que se invalide la propiedad. El evento Completed se procesa en primer lugar porque
lo desencadenó la escala de tiempo raíz (la primera Storyboard). En este momento, la propiedad X todavía
devuelve su valor animado porque todavía no se ha invalidado. En el segundo Storyboard se utiliza el valor
almacenado en caché como su valor inicial y comienza la animación.

Rendimiento
Las animaciones siguen ejecutándose después de salir de una página
Cuando sale de una Page que contiene animaciones en ejecución, esas animaciones seguirán reproduciéndose
hasta que el Page se recopile como elemento no utilizado. Según el sistema de navegación que se utilice, la página
de la que ha salido al navegar podría permanecer en memoria por tiempo indefinido, durante el cual seguiría
consumiendo recursos con sus animaciones. Esto resulta especialmente patente cuando una página contiene
animaciones de ejecución continua ("ambiente").
Por esta razón, se recomienda usar el evento Unloaded para quitar animaciones cuando se sale de una página.
Hay diferentes maneras de quitar una animación. Las técnicas siguientes se pueden usar para quitar animaciones
que pertenecen a un Storyboard.
Para quitar una Storyboard inicia con un desencadenador de eventos, vea Cómo: quitar un guion gráfico.
Para usar código con el fin de quitar un Storyboard, vea el método Remove.
La técnica siguiente se puede utilizar sin tener en cuenta cómo se inició la animación.
Para quitar animaciones de una propiedad concreta, use el método BeginAnimation(DependencyProperty,
AnimationTimeline). Especifique la propiedad que se anima como primer parámetro y null como segundo. De
este modo, se quitarán todos los relojes de animación de la propiedad.
Para obtener más información sobre las distintas formas de animar propiedades, vea información general sobre
técnicas de animación de propiedades.
Utilizar el valor Compose de HandoffBehavior consume recursos del sistema
Cuando se aplica un Storyboard, AnimationTimelineo AnimationClock a una propiedad mediante el
HandoffBehaviorCompose, los objetos Clock asociados previamente a esa propiedad continúan consumiendo
recursos del sistema; el sistema de control de tiempo no quitará estos relojes automáticamente.
Para evitar problemas de rendimiento al aplicar un gran número de relojes mediante Compose, debe quitar los
relojes de composición de la propiedad animada una vez completados. Hay varias formas de quitar un reloj.
Para quitar todos los relojes de una propiedad, use el método ApplyAnimationClock(DependencyProperty,
AnimationClock) o BeginAnimation(DependencyProperty, AnimationTimeline) del objeto animado.
Especifique la propiedad que se anima como primer parámetro y null como segundo. De este modo, se
quitarán todos los relojes de animación de la propiedad.
Para quitar una AnimationClock específica de una lista de relojes, utilice la propiedad Controller de la
AnimationClock para recuperar una ClockControllery, a continuación, llame al método Remove de la
ClockController. Esto se hace normalmente en el controlador de eventos Completed para un reloj. Tenga en
cuenta que solo los relojes de raíz pueden controlarse mediante un ClockController; la propiedad Controller
de un reloj secundario devolverá null . Tenga en cuenta también que no se llamará al evento Completed si
la duración efectiva del reloj es indefinidamente. En ese caso, el usuario deberá determinar cuándo llamar a
Remove.
Este problema se produce principalmente en las animaciones de objetos que tienen un período de duración
prolongado. Cuando un objeto se recolecta como elemento no utilizado, sus relojes también se desconectan y se
recolectan como elementos no utilizados.
Para obtener más información sobre los objetos de reloj, consulte información general sobre sistemas de control
de tiempo y animación.

Vea también
Información general sobre animaciones
Información general sobre animaciones
personalizadas
20/02/2020 • 14 minutes to read • Edit Online

En este tema se describe cómo y cuándo extender el sistema de animación de WPF creando fotogramas clave
personalizados o clases de animación, o utilizando la devolución de llamada por fotograma para omitirlo.

Prerequisites
Para entender este tema, debe estar familiarizado con los distintos tipos de animación proporcionados por WPF.
Para más información, consulte From/To/By Animations Overview (Información general sobre animaciones
From/To/By), Key-Frame Animations Overview (Información general sobre animaciones de fotogramas clave) e
Información general sobre animaciones en trazados.
Dado que las clases de animación heredan de la clase Freezable, debería estar familiarizado con Freezable objetos
y con la herencia de Freezable. Para más información, consulte Freezable Objects Overview (Información general
sobre objetos Freezable).

Extender el sistema de animación


Hay varias maneras de extender el sistema de animación WPF, dependiendo del nivel de funcionalidad integrada
que se desee utilizar. Existen tres puntos principales de extensibilidad en el motor de animación WPF:
Cree un objeto de fotograma clave personalizado heredando de uno de los <tipo > clases de fotogramas
clave, como DoubleKeyFrame. En este enfoque se utiliza la mayoría de la funcionalidad integrada del motor
de animación de WPF.
Cree su propia clase de animación heredando de AnimationTimeline o de una de las clases de <tipo >
AnimationBase.
Utilizar la devolución de llamada por fotograma para generar animaciones fotograma a fotograma. En este
enfoque se omite completamente el sistema de animación y control de tiempo.
En la tabla siguiente se describen algunos de los escenarios para extender el sistema de animación.

SI DESEA... UTILICE ESTE ENFOQUE

Personalizar la interpolación entre valores de un tipo que Crear un fotograma clave personalizado. Para más
tiene un <Tipo > AnimationUsingKeyFrames correspondiente información, consulte la sección Crear un fotograma clave
personalizado.

Personalizar algo más que la interpolación entre valores de un Crear una clase de animación personalizada que herede de la
tipo que tiene una clase <Tipo> Animation correspondiente. clase <Tipo > AnimationBase correspondiente al tipo que
desee animar. Para más información, consulte la sección Crear
una clase de animación personalizada.

Animar un tipo que no tenga una animación de WPF Use una ObjectAnimationUsingKeyFrames o cree una clase
correspondiente que herede de AnimationTimeline. Para más información,
consulte la sección Crear una clase de animación
personalizada.
SI DESEA... UTILICE ESTE ENFOQUE

Animar varios objetos con valores que se calculan para cada Utilizar la devolución de llamada por fotograma. Para más
fotograma y se basan en el último conjunto de interacciones información, consulte la sección Crear una devolución de
de objeto llamada por fotograma.

Crear un fotograma clave personalizado


Crear una clase de fotograma clave personalizado es la manera más simple de extender el sistema de animación.
Utilice este enfoque cuando desee utilizar un método de interpolación diferente para una animación de fotograma
clave. Como se describe en Key-Frame Animations Overview (Información general sobre animaciones de
fotogramas clave ), una animación de fotograma clave usa objetos de fotograma clave para generar sus valores de
salida. Cada objeto de fotograma clave realiza tres funciones:
Especifica un valor de destino mediante su propiedad Value.
Especifica la hora a la que se debe alcanzar ese valor mediante su KeyTime propiedad.
Interpola entre el valor del fotograma clave anterior y su propio valor implementando el método
InterpolateValueCore.
Instrucciones de implementación
Derive de la clase abstracta <Tipo> Keyframe e implemente el método InterpolateValueCore. El método
InterpolateValueCore devuelve el valor actual del fotograma clave. Acepta dos parámetros: el valor del fotograma
clave anterior y un valor de progreso que oscila de 0 a 1. Un progreso de 0 indica que el fotograma clave se acaba
de iniciar y un valor de 1 indica que el fotograma clave se acaba de completar y debe devolver el valor
especificado por su propiedad Value.
Dado que las clases de <tipo > fotogramas clave heredan de la clase Freezable, también debe invalidar
CreateInstanceCore Core para devolver una nueva instancia de la clase. Si la clase no utiliza propiedades de
dependencia para almacenar sus datos o requiere que se inicialice otra vez después de haberse creado, es posible
que tenga que invalidar otros métodos; consulte Freezable Objects Overview (Información general sobre objetos
Freezable).
Después de haber creado la animación personalizada <Tipo> Keyframe, puede usarla con la clase <Tipo>
AnimationUsingKeyFrames correspondiente a ese tipo.

Crear una clase de animación personalizada


Crear su propio tipo de animación le ofrece más control sobre cómo se anima un objeto. Hay dos maneras
recomendadas de crear su propio tipo de animación: puede derivar de la clase AnimationTimeline o del tipo de<>
clase AnimationBase. No se recomienda derivar de las clases <Tipo> Animation o <Tipo>
AnimationUsingKeyFrames.
Derivar de <Tipo>AnimationBase
Derivar de una clase <Tipo> AnimationBase es la manera más sencilla de crear un nuevo tipo de animación.
Utilice este enfoque cuando desee crear una nueva animación para un tipo que ya tiene una clase <Tipo>
AnimationBase correspondiente.
Instrucciones de implementación
Derive de una clase <Tipo> Animación e implemente el método GetCurrentValueCore. El método
GetCurrentValueCore devuelve el valor actual de la animación. Toma tres parámetros: un valor de inicio sugerido,
un valor final sugerido y un AnimationClock, que se usa para determinar el progreso de la animación.
Dado que el tipo de<> clases AnimationBase heredan de la clase Freezable, también debe invalidar
CreateInstanceCore Core para devolver una nueva instancia de la clase. Si la clase no utiliza propiedades de
dependencia para almacenar sus datos o requiere que se inicialice otra vez después de haberse creado, es posible
que tenga que invalidar otros métodos; consulte Freezable Objects Overview (Información general sobre objetos
Freezable).
Para más información, consulte la documentación del método GetCurrentValueCore para la clase <Tipo>
AnimationBase para el tipo que desee animar. Para ver un ejemplo, consulte el ejemplo de animación
personalizada
Enfoques alternativos
Si simplemente desea cambiar la forma en que se interpolan los valores de animación, puede que sea conveniente
derivar de una de las clases <Tipo> KeyFrame. El fotograma clave que se cree puede usarse con las clases <Tipo>
AnimationUsingKeyFrames correspondientes proporcionadas por WPF.
Derivar de AnimationTimeline
Derive de la clase AnimationTimeline cuando desee crear una animación para un tipo que no tenga ya una
animación WPF o que desee crear una animación que no esté fuertemente tipada.
Instrucciones de implementación
Derive de la clase AnimationTimeline e invalide los miembros siguientes:
CreateInstanceCore: Si la nueva clase es concreta, debe invalidar CreateInstanceCore para devolver una
nueva instancia de la clase.
GetCurrentValue: Invalide este método para devolver el valor actual de la animación. Toma tres
parámetros: un valor de origen predeterminado, un valor de destino predeterminado y un AnimationClock.
Utilice la AnimationClock para obtener la hora actual o el progreso de la animación. Puede elegir si desea
usar los valores de origen y destino predeterminados.
IsDestinationDefault: invalide esta propiedad para indicar si la animación utiliza el valor de destino
predeterminado especificado por el método GetCurrentValue.
TargetPropertyType: invalide esta propiedad para indicar el Type de salida que produce la animación.
Si la clase no utiliza propiedades de dependencia para almacenar sus datos o requiere que se inicialice otra vez
después de haberse creado, es posible que tenga que invalidar otros métodos; consulte Freezable Objects
Overview (Información general sobre objetos Freezable).
El paradigma recomendado (utilizado por las animaciones de WPF ) es usar dos niveles de herencia:
1. Cree un tipo de< abstracto > clase AnimationBase que derive de AnimationTimeline. Esta clase debe
invalidar el método TargetPropertyType. También debe introducir un nuevo método abstracto,
GetCurrentValueCore e invalidar GetCurrentValue para que valide los tipos del valor de origen
predeterminado y los parámetros de valor de destino predeterminados, y, a continuación, llame a
GetCurrentValueCore.
2. Cree otra clase que herede de su nuevo tipo de<> clase AnimationBase e invalide el método
CreateInstanceCore, el método GetCurrentValueCore que ha introducido y la propiedad
IsDestinationDefault.
Enfoques alternativos
Si desea animar un tipo que no tiene ninguna animación from/to/by o animación de fotogramas clave
correspondiente, considere la posibilidad de usar un ObjectAnimationUsingKeyFrames. Dado que está
débilmente tipado, una ObjectAnimationUsingKeyFrames puede animar cualquier tipo de valor. El inconveniente
de este enfoque es que ObjectAnimationUsingKeyFrames solo admite la interpolación discreta.
Utilizar la devolución de llamada por fotograma
Utilice este enfoque cuando necesite omitir completamente el sistema de animación de WPF. Un escenario para
este enfoque son las animaciones físicas, en las cuales es preciso volver a calcular una nueva dirección o posición
de los objetos animados en cada paso de la animación de acuerdo con el último conjunto de interacciones de
objeto.
Instrucciones de implementación
Al contrario que los demás enfoques descritos en esta información general, para utilizar la devolución de llamada
por fotograma no se necesita crear una clase personalizada de animación o de fotograma clave.
En su lugar, se registra para el evento Rendering del objeto que contiene los objetos que desea animar. Se llama a
este método de control de eventos una vez por cada fotograma. Cada vez que WPF serializa los datos de
representación conservados en el árbol visual hasta el árbol de composición, se llama a este método de control de
eventos.
En el controlador de eventos, realice los cálculos necesarios para el efecto de animación y establezca las
propiedades de los objetos que desea animar con estos valores.
Para obtener el tiempo de presentación del fotograma actual, el EventArgs asociado a este evento se puede
convertir en RenderingEventArgs, que proporcionan una propiedad RenderingTime que se puede usar para
obtener el tiempo de representación del fotograma actual.
Para obtener más información, vea la página Rendering.

Consulte también
AnimationTimeline
IKeyFrame
Información general sobre técnicas de animación de propiedades
Información general sobre objetos Freezable
Información general sobre animaciones de fotogramas clave
Información general sobre animaciones en trazados
Información general sobre animaciones
Información general sobre sistemas de control de tiempo y animación
Ejemplo de animación personalizada
Información general sobre animaciones From/To/By
20/02/2020 • 19 minutes to read • Edit Online

En este tema se describe cómo usar animaciones From/To/By para animar propiedades de dependencia. Una
animación From/To/By crea una transición entre dos valores.

Prerequisites
Para entender este tema, debe estar familiarizado con las características de animaciones de WPF. Para ver una
introducción a las características de animación, consulte información general sobre animaciones.

¿Qué es una animación From/To/By?


Una animación from/to/by es un tipo de AnimationTimeline que crea una transición entre un valor inicial y un
valor final. La Duration de esa animación determina la cantidad de tiempo que tarda en completarse la transición.
Puede aplicar una animación from/to/by a una propiedad mediante un Storyboard en el marcado y el código, o
mediante el método BeginAnimation en el código. También puede usar una animación from/to/by para crear una
AnimationClock y aplicarla a una o más propiedades. Para más información sobre los distintos métodos para
aplicar animaciones, consulte la Información general sobre técnicas de animación de propiedades.
Las animaciones From/To/By no pueden tener más de dos valores de destino. Si necesita una animación que tenga
más de dos valores de destino, use una animación de fotogramas clave. Las animaciones de fotogramas clave se
describen en información general sobre animaciones de fotogramas clave.

Tipos de animaciones From/To/By


Dado que las animaciones generan valores de propiedad, existen distintos tipos de animaciones para los diversos
tipos de propiedades. Para animar una propiedad que toma un Double, como la propiedad Width de un elemento,
utilice una animación que genere valores Double. Para animar una propiedad que toma un Point, utilice una
animación que genere valores de Point, etc.
Las clases de animación from/to/by pertenecen al espacio de nombres System.Windows.Media.Animation y usan
la siguiente Convención de nomenclatura:
<tipo > Animation

Donde <Tipo> es el tipo de valor que la clase anima.


WPF proporciona las siguientes clases de animación From/To/By.

TIPO DE PROPIEDAD CLASE DE ANIMACIÓN FROM/TO/BY CORRESPONDIENTE

Byte ByteAnimation

Color ColorAnimation

Decimal DecimalAnimation

Double DoubleAnimation
TIPO DE PROPIEDAD CLASE DE ANIMACIÓN FROM/TO/BY CORRESPONDIENTE

Int16 Int16Animation

Int32 Int32Animation

Int64 Int64Animation

Point PointAnimation

Quaternion QuaternionAnimation

Rect RectAnimation

Rotation3D Rotation3DAnimation

Single SingleAnimation

Size SizeAnimation

Thickness ThicknessAnimation

Vector3D Vector3DAnimation

Vector VectorAnimation

Valores de destino
Una animación From/To/By crea una transición entre dos valores de destino. Es habitual especificar un valor inicial
(establézcalo mediante la propiedad From) y un valor final (establézcalo mediante la propiedad To). Pero también
se puede especificar solo un valor inicial, un valor de destino o un valor de desplazamiento. En estos casos, la
animación obtiene el valor de destino que falta de la propiedad que se anima. La lista siguiente describe las
diferentes maneras de especificar los valores de destino de una animación.
Valor inicial
Utilice la propiedad From cuando desee especificar explícitamente el valor inicial de una animación. Puede
usar la propiedad From por sí sola o con la propiedad To o By. Si solo especifica la propiedad From, la
animación realiza la transición desde ese valor al valor base de la propiedad animada.
Valor final
Para especificar un valor final de una animación, use su propiedad To. Si usa la propiedad To por sí misma,
la animación obtiene su valor inicial de la propiedad que se anima o desde la salida de otra animación que
se aplica a la misma propiedad. Puede usar la propiedad To junto con la propiedad From para especificar
explícitamente los valores inicial y final de la animación.
Valor de desplazamiento
La propiedad By permite especificar un desplazamiento en lugar de un valor de inicio o finalización explícito
para la animación. La propiedad By de una animación especifica en qué parte la animación cambia un valor
a lo largo de su duración. Puede usar la propiedad By por sí sola o con la propiedad From. Si solo especifica
la propiedad By, la animación agrega el valor de desplazamiento al valor base de la propiedad o a la salida
de otra animación.
Usar valores From/To/By
En las secciones siguientes se describe cómo usar las propiedades From, Toy By juntas o por separado.
En los ejemplos de esta sección se usa un DoubleAnimation, que es un tipo de animación from/to/by, para animar
la propiedad Width de una Rectangle que es 10 píxeles independientes del dispositivo de alto y 100 píxeles
independientes del dispositivo de ancho.
Aunque en cada ejemplo se usa un DoubleAnimation, las propiedades from, to y by de todas las animaciones
From/to/by se comportan exactamente igual. Aunque cada uno de estos ejemplos usa una Storyboard, puede usar
animaciones From/to/by de otras maneras. Para obtener más información, vea información general sobre técnicas
de animación de propiedades.
De/Para
Al establecer los valores From y To juntos, la animación progresa desde el valor especificado por la propiedad
From hasta el valor especificado por la propiedad To.
En el ejemplo siguiente se establece la propiedad From del DoubleAnimation en 50 y su propiedad To en 300.
Como resultado, el Width del Rectangle se anima desde 50 a 300.

// Demonstrates the From and To properties used together.

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"fromToAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.Black;

// Demonstrates the From and To properties used together.


// Animates the rectangle's Width property from 50 to 300 over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 50;
myDoubleAnimation.To = 300;
myDoubleAnimation.Duration =
new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "fromToAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation


// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
{
myStoryboard.Begin(myRectangle);
};
' Demonstrates the From and To properties used together.

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myRectangle As New Rectangle()

' Assign the Rectangle a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("fromToAnimatedRectangle", myRectangle)
myRectangle.Height = 10
myRectangle.Width = 100
myRectangle.HorizontalAlignment = HorizontalAlignment.Left
myRectangle.Fill = Brushes.Black

' Demonstrates the From and To properties used together.


' Animates the rectangle's Width property from 50 to 300 over 10 seconds.
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 50
myDoubleAnimation.To = 300
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(10))

Storyboard.SetTargetName(myDoubleAnimation, "fromToAnimatedRectangle")
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.WidthProperty))
Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)

' Use an anonymous event handler to begin the animation


' when the rectangle is clicked.
AddHandler myRectangle.MouseLeftButtonDown, Sub(sender As Object, args As MouseButtonEventArgs)
myStoryboard.Begin(myRectangle)

A
Cuando se establece solo la propiedad To, la animación progresa desde el valor base de la propiedad animada o
desde la salida de una animación compuesta que se aplicó previamente a la misma propiedad, hasta el valor
especificado por la propiedad To.
("Composición de animación" hace referencia a una animación Active o Filling que se aplicó previamente a la
misma propiedad que todavía está en vigor cuando se aplicó la animación actual mediante el comportamiento de
entrega de Compose).
En el ejemplo siguiente se establece solo la propiedad To del DoubleAnimation en 300. Dado que no se especificó
ningún valor de inicio, el DoubleAnimation usa el valor base (100) de la propiedad Width como su valor de inicio.
El Width del Rectangle se anima desde 100 hasta el valor de destino de la animación de 300.
// Demonstrates the use of the To property.

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"toAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.Gray;

// Demonstrates the To property used by itself. Animates


// the Rectangle's Width property from its base value
// (100) to 300 over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.To = 300;
myDoubleAnimation.Duration =
new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "toAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation


// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
{
myStoryboard.Begin(myRectangle);
};
' Demonstrates the use of the To property.

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myRectangle As New Rectangle()

' Assign the Rectangle a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("toAnimatedRectangle", myRectangle)
myRectangle.Height = 10
myRectangle.Width = 100
myRectangle.HorizontalAlignment = HorizontalAlignment.Left
myRectangle.Fill = Brushes.Gray

' Demonstrates the To property used by itself. Animates


' the Rectangle's Width property from its base value
' (100) to 300 over 10 seconds.
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.To = 300
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(10))

Storyboard.SetTargetName(myDoubleAnimation, "toAnimatedRectangle")
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.WidthProperty))
Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)

' Use an anonymous event handler to begin the animation


' when the rectangle is clicked.
AddHandler myRectangle.MouseLeftButtonDown, Sub(sender As Object, args As MouseButtonEventArgs)
myStoryboard.Begin(myRectangle)

Por
Cuando se establece solo la propiedad By de una animación, la animación progresa desde el valor base de la
propiedad que se está animando, o desde la salida de una animación compuesta hasta la suma de ese valor y el
valor especificado por la propiedad By.
En el ejemplo siguiente se establece solo la propiedad By del DoubleAnimation en 300. Dado que el ejemplo no
especifica un valor de inicio, el DoubleAnimation usa el valor base de la propiedad Width, 100, como su valor de
inicio. El valor final se determina agregando el valor By de la animación, 300, a su valor inicial, 100:400. Como
resultado, el Width del Rectangle se anima desde 100 a 400.
// Demonstrates the use of the By property.

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"byAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.RoyalBlue;

// Demonstrates the By property used by itself.


// Increments the Rectangle's Width property by 300 over 10 seconds.
// As a result, the Width property is animated from its base value
// (100) to 400 (100 + 300) over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.By = 300;
myDoubleAnimation.Duration =
new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "byAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation


// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
{
myStoryboard.Begin(myRectangle);
};
' Demonstrates the use of the By property.

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myRectangle As New Rectangle()

' Assign the Rectangle a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("byAnimatedRectangle", myRectangle)
myRectangle.Height = 10
myRectangle.Width = 100
myRectangle.HorizontalAlignment = HorizontalAlignment.Left
myRectangle.Fill = Brushes.RoyalBlue

' Demonstrates the By property used by itself.


' Increments the Rectangle's Width property by 300 over 10 seconds.
' As a result, the Width property is animated from its base value
' (100) to 400 (100 + 300) over 10 seconds.
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.By = 300
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(10))

Storyboard.SetTargetName(myDoubleAnimation, "byAnimatedRectangle")
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.WidthProperty))
Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)

' Use an anonymous event handler to begin the animation


' when the rectangle is clicked.
AddHandler myRectangle.MouseLeftButtonDown, Sub(sender As Object, args As MouseButtonEventArgs)
myStoryboard.Begin(myRectangle)

From/By
Al establecer las propiedades From y By de una animación, la animación progresa desde el valor especificado por
la propiedad From hasta el valor especificado por la suma de las propiedades From y By.
En el ejemplo siguiente se establece la propiedad From del DoubleAnimation en 50 y su propiedad By en 300. El
valor final se determina agregando el valor By de la animación, 300, a su valor inicial, 50:350. Como resultado, el
Width del Rectangle se anima desde 50 a 350.
// Demonstrates the use of the From and By properties.

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"byAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.BlueViolet;

// Demonstrates the From and By properties used together.


// Increments the Rectangle's Width property by 300 over 10 seconds.
// As a result, the Width property is animated from 50
// to 350 (50 + 300) over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 50;
myDoubleAnimation.By = 300;
myDoubleAnimation.Duration =
new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "byAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation


// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
{
myStoryboard.Begin(myRectangle);
};
' Demonstrates the use of the From and By properties.

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myRectangle As New Rectangle()

' Assign the Rectangle a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("byAnimatedRectangle", myRectangle)
myRectangle.Height = 10
myRectangle.Width = 100
myRectangle.HorizontalAlignment = HorizontalAlignment.Left
myRectangle.Fill = Brushes.BlueViolet

' Demonstrates the From and By properties used together.


' Increments the Rectangle's Width property by 300 over 10 seconds.
' As a result, the Width property is animated from 50
' to 350 (50 + 300) over 10 seconds.
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 50
myDoubleAnimation.By = 300
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(10))

Storyboard.SetTargetName(myDoubleAnimation, "byAnimatedRectangle")
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.WidthProperty))
Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)

' Use an anonymous event handler to begin the animation


' when the rectangle is clicked.
AddHandler myRectangle.MouseLeftButtonDown, Sub(sender As Object, args As MouseButtonEventArgs)
myStoryboard.Begin(myRectangle)

De
Cuando se especifica únicamente el valor de From de una animación, la animación progresa desde el valor
especificado por la propiedad From, hasta el valor base de la propiedad que se anima o hasta la salida de una
animación compuesta.
En el ejemplo siguiente se establece solo la propiedad From del DoubleAnimation en 50. Dado que no se
especificó ningún valor final, el DoubleAnimation usa el valor base de la propiedad Width, 100, como su valor final.
El Width del Rectangle se anima desde 50 hasta el valor base de la propiedad Width, 100.
// Demonstrates the use of the From property.

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

Rectangle myRectangle = new Rectangle();

// Assign the Rectangle a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"fromAnimatedRectangle", myRectangle);
myRectangle.Height = 10;
myRectangle.Width = 100;
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.Fill = Brushes.Purple;

// Demonstrates the From property used by itself. Animates the


// rectangle's Width property from 50 to its base value (100)
// over 10 seconds.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 50;
myDoubleAnimation.Duration =
new Duration(TimeSpan.FromSeconds(10));

Storyboard.SetTargetName(myDoubleAnimation, "fromAnimatedRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

// Use an anonymous event handler to begin the animation


// when the rectangle is clicked.
myRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs args)
{
myStoryboard.Begin(myRectangle);
};
' Demonstrates the use of the From property.

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myRectangle As New Rectangle()

' Assign the Rectangle a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("fromAnimatedRectangle", myRectangle)
myRectangle.Height = 10
myRectangle.Width = 100
myRectangle.HorizontalAlignment = HorizontalAlignment.Left
myRectangle.Fill = Brushes.Purple

' Demonstrates the From property used by itself. Animates the


' rectangle's Width property from 50 to its base value (100)
' over 10 seconds.
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 50
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(10))

Storyboard.SetTargetName(myDoubleAnimation, "fromAnimatedRectangle")
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.WidthProperty))
Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)

' Use an anonymous event handler to begin the animation


' when the rectangle is clicked.
AddHandler myRectangle.MouseLeftButtonDown, Sub(sender As Object, args As MouseButtonEventArgs)
myStoryboard.Begin(myRectangle)

To/By
Si establece las propiedades To y By de una animación, se omite la propiedad By.

Otros tipos de animación


Las animaciones From/to/by no son el único tipo de animaciones que proporciona WPF: también proporciona
animaciones de fotogramas clave y animaciones de trazados.
Una animación de fotogramas clave se anima a lo largo de cualquier cantidad de valores de destino, que se
describen mediante fotogramas clave. Para obtener más información, consulte la información General sobre
animaciones de fotogramas clave.
Una animación de trazado genera valores de salida de un PathGeometry. Para obtener más información,
vea información general sobre animaciones de trazados.
WPF también le permite crear sus propios tipos de animaciones personalizadas. Para obtener más información,
vea información general sobre animaciones personalizadas.

Consulte también
Timeline
Storyboard
Información general sobre animaciones
Información general sobre objetos Storyboard
Información general sobre animaciones de fotogramas clave
Información general sobre animaciones en trazados
Información general sobre animaciones personalizadas
Ejemplo de valores de destino de animación From, To y By
Información general sobre animaciones de
fotogramas clave
23/10/2019 • 35 minutes to read • Edit Online

Este tema es una introducción a las animaciones de fotogramas clave. Las animaciones de fotogramas clave
le permiten realizar animaciones con más de dos valores de destino y controlan el método de interpolación
de una animación.

Requisitos previos
Para entender esta introducción, debe conocer las animaciones y escalas de tiempo de Windows
Presentation Foundation (WPF ). Consulte Información general sobre animaciones para ver una
introducción a las animaciones. También resulta útil conocer las animaciones From/To/By. Para más
información, consulte la información general sobre animaciones From/To/By.

¿Qué es una animación de fotogramas clave?


Al igual que una animación From/To/By, una animación de fotogramas clave anima el valor de una
propiedad de destino. Crea una transición entre sus valores de destino a través de su Duration. Sin
embargo, mientras que una animación From/To/By crea una transición entre dos valores, una animación de
fotogramas clave única puede crear transiciones entre cualquier número de valores de destino. A diferencia
de una animación From/To/By, una animación de fotogramas clave no tiene propiedades From, To o By con
las cuales establecer sus valores de destino. Los valores de destino de una animación de fotogramas clave
se describen con objetos de fotogramas clave (de ahí surge el término "animación de fotogramas clave").
Para especificar los valores de destino de la animación, puede crear objetos de fotograma clave y
agregarlos a la animación KeyFrames colección. Cuando se ejecuta la animación, transiciona entre los
fotogramas que especificó.
Además de admitir varios valores de destino, algunos métodos de fotogramas clave incluso admiten varios
métodos de interpolación. El método de interpolación de una animación define cómo transiciona de un
valor al siguiente. Hay tres tipos de interpolaciones: discreta, lineal y spline.
Para animar con una animación de fotogramas clave, debe completar los pasos siguientes.
Declare la animación y especifique su Duration, tal como lo haría para una animación from/to/by.
Para cada valor de destino, cree un fotograma clave del tipo adecuado, establezca su valor y
KeyTimey su incorporación a la animación KeyFrames colección.
Asocie la animación a una propiedad, tal como lo haría con una animación From/To/By. Para más
información sobre cómo aplicar una animación a una propiedad a través de un guión gráfico,
consulte Información sobre objetos Storyboard.
En el ejemplo siguiente se usa un DoubleAnimationUsingKeyFrames para animar un Rectangle elemento a
cuatro ubicaciones diferentes.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.KeyFrameAnimations.KeyFramesIntroduction"
WindowTitle="KeyFrame Animations">

<Border Width="400" BorderBrush="Black">

<Rectangle Fill="Blue"
Width="50" Height="50"
HorizontalAlignment="Left">
<Rectangle.RenderTransform>
<TranslateTransform
x:Name="MyAnimatedTranslateTransform"
X="0" Y="0" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>

<!-- Animate the TranslateTransform's X property


from 0 to 350, then 50,
then 200 over 10 seconds. -->

<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="MyAnimatedTranslateTransform"
Storyboard.TargetProperty="X"
Duration="0:0:10">
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
<LinearDoubleKeyFrame Value="350" KeyTime="0:0:2" />
<LinearDoubleKeyFrame Value="50" KeyTime="0:0:7" />
<LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Border>
</Page>

Al igual que un From/To/By animación, una animación de fotogramas clave se puede aplicar a una
propiedad mediante el uso de un Storyboard en marcado y código o mediante el BeginAnimation método
en el código. También puede usar una animación de fotogramas clave para crear un AnimationClock y
aplicarla a una o varias propiedades. Para más información sobre los distintos métodos para aplicar
animaciones, consulte la Información general sobre técnicas de animación de propiedades.

Tipos de animación de fotogramas clave


Dado que las animaciones generan valores de propiedad, existen distintos tipos de animaciones para los
diversos tipos de propiedades. Para animar una propiedad que acepta un Double (por ejemplo, un
elemento Width propiedad), se usa una animación que genera Double valores. Para animar una propiedad
que acepta un Point, use una animación que genera Point valores y así sucesivamente.
Las clases de animación de fotogramas clave pertenecen a la System.Windows.Media.Animation espacio de
nombres y cumplen con la convención de nomenclatura siguiente:
<Tipo> AnimationUsingKeyFrames

Donde <Tipo> es el tipo de valor que la clase anima.


WPF proporciona las siguientes clases de animación de fotogramas clave.
CLASE DE ANIMACIÓN FROM/TO/BY MÉTODOS DE INTERPOLACIÓN
TIPO DE PROPIEDAD CORRESPONDIENTE ADMITIDOS

Boolean BooleanAnimationUsingKeyFrames Discreta

Byte ByteAnimationUsingKeyFrames Discreta, lineal, spline

Color ColorAnimationUsingKeyFrames Discreta, lineal, spline

Decimal DecimalAnimationUsingKeyFrames Discreta, lineal, spline

Double DoubleAnimationUsingKeyFrames Discreta, lineal, spline

Int16 Int16AnimationUsingKeyFrames Discreta, lineal, spline

Int32 Int32AnimationUsingKeyFrames Discreta, lineal, spline

Int64 Int64AnimationUsingKeyFrames Discreta, lineal, spline

Matrix MatrixAnimationUsingKeyFrames Discreta

Object ObjectAnimationUsingKeyFrames Discreta

Point PointAnimationUsingKeyFrames Discreta, lineal, spline

Quaternion QuaternionAnimationUsingKeyFrame Discreta, lineal, spline


s

Rect RectAnimationUsingKeyFrames Discreta, lineal, spline

Rotation3D Rotation3DAnimationUsingKeyFrame Discreta, lineal, spline


s

Single SingleAnimationUsingKeyFrames Discreta, lineal, spline

String StringAnimationUsingKeyFrames Discreta

Size SizeAnimationUsingKeyFrames Discreta, lineal, spline

Thickness ThicknessAnimationUsingKeyFrames Discreta, lineal, spline

Vector3D Vector3DAnimationUsingKeyFrames Discreta, lineal, spline

Vector VectorAnimationUsingKeyFrames Discreta, lineal, spline

Valores de destino (fotogramas clave) y valores KeyTime


Del mismo modo que hay distintos tipos de animaciones de fotogramas clave para animar diferentes tipos
de propiedades, también hay distintos tipos de objetos de fotogramas clave: uno para cada tipo de valor
animado y método de interpolación admitido. Los tipos de fotogramas clave cumplen con la convención de
nomenclatura siguiente:
<MétodoInterpolación><Tipo> KeyFrame
Donde <MétodoInterpolación> es el método de interpolación que el fotograma clave usa y <Tipo> es el
tipo de valor que la clase anima. Una animación de fotogramas clave que admite los tres métodos de
interpolación tendrá tres tipos de fotogramas clave que se pueden usar. Por ejemplo, puede usar tres tipos
de fotogramas clave con un DoubleAnimationUsingKeyFrames: DiscreteDoubleKeyFrame,
LinearDoubleKeyFrame, y SplineDoubleKeyFrame. (Los métodos de interpolación se describen
detalladamente en una sección posterior).
El propósito principal de un fotograma clave es especificar un KeyTime y un Value. Cada tipo de fotograma
clave proporciona estas dos propiedades.
El Value propiedad especifica el valor de destino para ese fotograma clave.
El KeyTime propiedad especifica cuándo (dentro de la animación Duration) un fotograma clave Value
se alcanza.
Cuando se inicia una animación de fotogramas clave, itera a través de los fotogramas clave en el orden
definido por sus KeyTime propiedades.
Si no hay ningún fotograma clave en tiempo de 0, la animación crea una transición entre el valor
actual de la propiedad de destino y el Value del primer fotograma clave; en caso contrario, la
animación de salida de valor se convierte en el valor del primer fotograma clave.
La animación crea una transición entre el Value de los fotogramas clave de primeros y segundo
mediante el método de interpolación especificado por el segundo fotograma clave. La transición
comienza en el primer fotograma clave KeyTime y cuando finaliza el segundo fotograma clave
KeyTime se alcanza.
La animación continúa y crea transiciones entre cada fotograma clave subsiguiente y el fotograma
clave precedente.
Por último, las transiciones de animación en el valor del fotograma clave con el mayor tiempo clave
que es igual o menor que la animación Duration.
Si la animación Duration es Automatic o su Duration es igual a la hora del último fotograma clave, los
extremos de la animación. De lo contrario, si la animación Duration es mayor que el tiempo clave del último
fotograma clave, las suspensiones de animación, el valor del fotograma clave hasta que llega al final de su
Duration. Al igual que todas las animaciones, se usa una animación de fotogramas clave su FillBehavior
propiedad para determinar si retiene el valor final cuando llega al final de su período activo. Para más
información, consulte Información general sobre comportamientos de control de tiempo.
En el ejemplo siguiente se usa el DoubleAnimationUsingKeyFrames objeto definido en el ejemplo anterior
para demostrar cómo el Value y KeyTime las propiedades.
El primer fotograma clave establece inmediatamente el valor de salida de la animación en 0.
El segundo fotograma clave anima desde 0 a 350. Se inicia cuando finaliza el primer fotograma clave
(a los 0 segundos) y se reproduce durante 2 segundos, finalizando en 0:0:2.
El tercer fotograma clave anima desde 350 a 50. Se inicia cuando finaliza el segundo fotograma
clave (a los 2 segundos) y se reproduce durante 5 segundos, finalizando en 0:0:7.
El cuarto fotograma clave anima desde 50 a 200. Se inicia cuando finaliza el tercer fotograma clave
(a los 7 segundos) y se reproduce durante 1 segundo, finalizando en 0:0:8.
Dado que el Duration propiedad de la animación se estableció en 10 segundos, la animación retiene
su valor final durante dos segundos antes de finalizar en el tiempo = 0:0:10.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.KeyFrameAnimations.KeyFramesIntroduction"
WindowTitle="KeyFrame Animations">

<Border Width="400" BorderBrush="Black">

<Rectangle Fill="Blue"
Width="50" Height="50"
HorizontalAlignment="Left">
<Rectangle.RenderTransform>
<TranslateTransform
x:Name="MyAnimatedTranslateTransform"
X="0" Y="0" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>

<!-- Animate the TranslateTransform's X property


from 0 to 350, then 50,
then 200 over 10 seconds. -->

<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="MyAnimatedTranslateTransform"
Storyboard.TargetProperty="X"
Duration="0:0:10">
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
<LinearDoubleKeyFrame Value="350" KeyTime="0:0:2" />
<LinearDoubleKeyFrame Value="50" KeyTime="0:0:7" />
<LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Border>
</Page>

Métodos de interpolación
En las secciones anteriores se mencionó que algunas animaciones de fotogramas clave admiten varios
métodos de interpolación. La interpolación de una animación describe cómo una animación transiciona
entre los valores a lo largo de su duración. Si selecciona el tipo de fotograma clave usar con la animación,
puede definir el método de interpolación para ese segmento de fotogramas clave. Hay tres tipos de
métodos de interpolación distintos: lineal, discreta y spline.
Interpolación lineal
Con la interpolación lineal, la animación avanza a una velocidad constante de la duración del segmento. Por
ejemplo, si un segmento de fotogramas clave transiciona desde 0 a 10 durante 5 segundos, la animación
generará los valores siguientes en los momentos especificados:

TIEMPO VALOR DE SALIDA

0 0

1 2
TIEMPO VALOR DE SALIDA

2 4

3 6

4 8

4.25 8.5

4.5 9

5 10

Interpolación discreta
Con la interpolación discreta, la función de animación pasa de un valor al siguiente sin interpolación. Si un
segmento de fotogramas clave transiciona desde 0 a 10 durante 5 segundos, la animación generará los
valores siguientes en los momentos especificados:

HORA VALOR DE SALIDA

0 0

1 0

2 0

3 0

4 0

4.25 0

4.5 0

5 10

Tenga en cuenta que la animación no cambia su valor de salida hasta el final mismo de la duración del
segmento.
La interpolación spline es más compleja. Esta interpolación se describe en la sección siguiente.
Interpolación spline
La interpolación spline se puede usar para lograr efectos de control de tiempo más realistas. Debido a que
las animaciones se usan a menudo para imitar los efectos que ocurren en el mundo real, es posible que los
desarrolladores necesiten un control detallado de la aceleración y la desaceleración de objetos y una
manipulación cercana de los segmentos de tiempo. Los fotogramas clave de spline le permiten animar con
la interpolación spline. Con otros fotogramas clave, especifica un Value y KeyTime. Con un fotograma clave
spline, también se especifica un KeySpline. El ejemplo siguiente muestra un fotograma clave de spline único
para un DoubleAnimationUsingKeyFrames. Tenga en cuenta el KeySpline propiedad; que es lo que hace un
fotograma clave spline difieren de los otros tipos de fotogramas clave.
<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

Un punto inicial, un punto final y dos puntos de control definen una curva Bézier cúbica. El KeySpline
propiedad de un fotograma clave de spline define los dos puntos de control de una curva de Bézier que se
extiende desde (0,0) a (1,1). El primer punto de control controla el factor de curva de la primera mitad de la
curva Bézier, mientras que el segundo punto de control, el factor de curva de la segunda mitad. La curva
resultante describe la tasa de cambio de ese fotograma clave de spline. Cuanto más inclinada sea la curva,
el fotograma clave cambia sus valores más rápidamente. A medida que la curva es cada vez más plana, el
fotograma clave cambia sus valores más lentamente.
Puede usar KeySpline para simular trayectorias físicas como pertenecientes a agua o que las bolas que o
aplique otros efectos de "salida lenta" y "lenta" a las animaciones de movimiento. Para obtener efectos de
interacción con el usuario, como el fundido en el fondo o el rebote del botón de control, podría aplicar la
interpolación spline para acelerar o ralentizar la tasa de cambio de una animación de una forma específica.
En el ejemplo siguiente se especifica un KeySpline de 0,1 1,0, lo que crea la siguiente curva Bézier.

Una curva spline clave con los puntos de control (0.0, 1.0) y (1.0, 0.0)

<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

Este fotograma clave se anima rápidamente cuando comienza, disminuye la velocidad y vuelve a acelerarla
antes de finalizar.
En el ejemplo siguiente se especifica un KeySpline de 0.5,0.25 0.75,1.0, que crea la siguiente curva Bézier.

Una curva spline clave con los puntos de control (0.25, 0.5) y (0.75, 1.0)

<SplineDoubleKeyFrame Value="350" KeyTime="0:0:15" KeySpline="0.25,0.5 0.75,1" />


Debido a que la curvatura de la curva Bézier cambia muy poco, este fotograma clave se anima a una
velocidad casi constante; disminuye la velocidad cerca del final.
En el ejemplo siguiente se usa un DoubleAnimationUsingKeyFrames para animar la posición del
rectángulo. Dado que el DoubleAnimationUsingKeyFrames usa SplineDoubleKeyFrame objetos, la
transición entre cada valor del fotograma clave usa la interpolación spline.

<!-- This rectangle is animated using a key frame animation


with splined interpolation. -->
<Rectangle
Width="50"
Height="50"
Fill="Purple">
<Rectangle.RenderTransform>
<TranslateTransform
x:Name="SplineAnimatedTranslateTransform"
X="0" Y="0" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- Animate the TranslateTransform's X property


from its base value (0) to 500, then 200,
then 350 over 15 seconds. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="SplineAnimatedTranslateTransform"
Storyboard.TargetProperty="X"
Duration="0:0:15"
RepeatBehavior="Forever">
<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

<SplineDoubleKeyFrame Value="200" KeyTime="0:0:10" KeySpline="0.0,0.0 1.0,0.0" />

<SplineDoubleKeyFrame Value="350" KeyTime="0:0:15" KeySpline="0.25,0.5 0.75,1" />


</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

La interpolación spline puede ser difícil de entender, por lo que puede resultar útil experimentar distintas
configuraciones. El ejemplo de animación de curva spline clave le permite cambiar los valores de curva
spline clave y ver el resultado que esto tiene en una animación.
Combinación de métodos de interpolación
Puede usar fotogramas clave con distintos tipos de interpolación en una animación de fotogramas clave
única. Cuando se encuentran dos animaciones de fotogramas clave con distintas interpolaciones, el método
de interpolación del segundo fotograma clave se usa para crear la transición desde el primer valor al
segundo.
En el ejemplo siguiente, un DoubleAnimationUsingKeyFrames se crea que usa la interpolación lineal, spline
y discreta.
<!-- This rectangle is animated using a key frame animation
with a combination of interpolation methods. -->
<Rectangle
Width="50"
Height="50"
Fill="Orange">
<Rectangle.RenderTransform>
<TranslateTransform
x:Name="ComboAnimatedTranslateTransform"
X="0" Y="0" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- Animate the TranslateTransform's X property


from its base value (0) to 500, then 200,
then 350 over 15 seconds. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="ComboAnimatedTranslateTransform"
Storyboard.TargetProperty="X"
Duration="0:0:15"
RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="500" KeyTime="0:0:7" />
<LinearDoubleKeyFrame Value="200" KeyTime="0:0:10" />
<SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"
KeySpline="0.25,0.5 0.75,1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

Más información sobre Duration y KeyTimes


Al igual que otras animaciones, animaciones de fotogramas clave tienen una Duration propiedad. Además
de especificar la animación Duration, deberá especificar qué parte de esa duración se asigna a cada
fotograma clave. Para ello, que describe un KeyTime para cada uno de fotogramas clave la animación de.
Cada fotograma clave KeyTime especifica cuándo finaliza ese fotograma clave.
El KeyTime propiedad no especifica cuánto tiempo se reproduce el tiempo clave. La cantidad de tiempo
durante el cual se reproduce un fotograma clave se determina en virtud del momento en que finaliza el
fotograma clave, cuándo finaliza el fotograma clave anterior y la duración de la animación. Se pueden
especificar tiempos clave como un valor de tiempo, un porcentaje, o como los valores especiales Uniform o
Paced.
En la lista siguiente se describen las distintas formas de especificar los tiempos clave.
Valores TimeSpan
Puede usar TimeSpan valores para especificar un KeyTime. El valor debe ser mayor o igual que 0 y menor
o igual que la duración de la animación. En el ejemplo siguiente se muestra una animación con una
duración de 10 segundos y 4 fotogramas clave cuyos tiempos clave están especificados como valores de
tiempo.
El primer fotograma clave anima desde el valor base a 100 durante los primeros 3 segundos y
finaliza en 0:0:03.
El segundo fotograma clave anima desde 100 a 200. Se inicia cuando finaliza el primer fotograma
clave (a los 3 segundos) y se reproduce durante 5 segundos, finalizando en 0:0:8.
El tercer fotograma clave anima desde 200 a 500. Se inicia cuando finaliza el segundo fotograma
clave (a los 8 segundos) y se reproduce durante 1 segundo, finalizando en 0:0:9.
El cuarto fotograma clave anima desde 500 a 600. Se inicia cuando finaliza el tercer fotograma clave
(a los 9 segundos) y se reproduce durante 1 segundo, finalizando en 0:0:10.

<!-- This rectangle is animated with KeyTimes using TimeSpan values.


Goes to 100 in the first 3 seconds, 100 to 200 in
the next 5 seconds, 300 to 500 in the next second,
and 500 to 600 in the final second. -->
<Rectangle Width="50" Height="50" Fill="Blue">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform01" X="10" Y="30" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform01"
Storyboard.TargetProperty="X"
Duration="0:0:10"
RepeatBehavior="Forever">

<!-- KeyTime properties are expressed as TimeSpan values


which are in the form of "hours:minutes:seconds". -->
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:3" />
<LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />
<LinearDoubleKeyFrame Value="500" KeyTime="0:0:9" />
<LinearDoubleKeyFrame Value="600" KeyTime="0:0:10" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

Valores de porcentaje
Un valor de porcentaje especifica que el fotograma clave finaliza en algún porcentaje de la animación
Duration. En XAML, especifica el porcentaje como un número, seguido del símbolo % . En el código, usa el
FromPercent método y pásele un Double que indica el porcentaje. El valor debe ser mayor o igual que 0 y
menor o igual que 100 por ciento. En el ejemplo siguiente se muestra una animación con una duración de
10 segundos y 4 fotogramas clave cuyos tiempos clave están especificados como porcentajes.
El primer fotograma clave anima desde el valor base a 100 durante los primeros 3 segundos y
finaliza en 0:0:3.
El segundo fotograma clave anima desde 100 a 200. Se inicia cuando finaliza el primer fotograma
clave (a los 3 segundos) y se reproduce durante 5 segundos, finalizando en 0:0:8 (0.8 * 10 = 8).
El tercer fotograma clave anima desde 200 a 500. Se inicia cuando finaliza el segundo fotograma
clave (a los 8 segundos) y se reproduce durante 1 segundo, finalizando en 0:0:9 (0.9 * 10 = 9).
El cuarto fotograma clave anima desde 500 a 600. Se inicia cuando finaliza el tercer fotograma clave
(a los 9 segundos) y se reproduce durante 1 segundo, finalizando en 0:0:10 (1 * 10 = 10).
<!-- Identical animation behavior to the previous rectangle
but using percentage values for KeyTimes rather then TimeSpan. -->
<Rectangle Height="50" Width="50" Fill="Purple">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform02" X="10" Y="110" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform02"
Storyboard.TargetProperty="X"
Duration="0:0:10"
RepeatBehavior="Forever">

<!-- KeyTime properties are expressed as Percentages. -->


<LinearDoubleKeyFrame Value="100" KeyTime="30%" />
<LinearDoubleKeyFrame Value="200" KeyTime="80%" />
<LinearDoubleKeyFrame Value="500" KeyTime="90%" />
<LinearDoubleKeyFrame Value="600" KeyTime="100%" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

Valor especial, Uniform


Use Uniform cuando desee que cada fotograma clave a la misma cantidad de tiempo de control de tiempo.
Un Uniform tiempo clave divide el tiempo disponible por igual por el número de fotogramas clave para
determinar la hora de finalización de cada fotograma clave. El ejemplo siguiente muestra una animación
con una duración de 10 segundos y fotogramas clave cuatro veces cuya clave se especifican como Uniform.
El primer fotograma clave anima desde el valor base a 100 durante los primeros 2.5 segundos y
finaliza en 0:0:2.5.
El segundo fotograma clave anima desde 100 a 200. Se inicia cuando finaliza el primer fotograma
clave (a los 2.5 segundos) y se reproduce aproximadamente durante 2.5 segundos, finalizando en
0:0:5.
El tercer fotograma clave anima desde 200 a 500. Se inicia cuando finaliza el segundo fotograma
clave (a los 5 segundos) y se reproduce durante 2.5 segundos, finalizando en 0:0:7.5.
El cuarto fotograma clave anima desde 500 a 600. Se inicia cuando finaliza el segundo fotograma
clave (a los 7.5 segundos) y se reproduce durante 2.5 segundos, finalizando en 0:0:1.
<!-- This rectangle is animated with KeyTimes using Uniform values. -->
<Rectangle Height="50" Width="50" Fill="Red">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform03" X="10" Y="190" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform03"
Storyboard.TargetProperty="X"
Duration="0:0:10"
RepeatBehavior="Forever">

<!-- KeyTime properties are expressed with values of Uniform.


When a key time is set to "Uniform" the total allotted
time of the animation is divided evenly between key frames.
In this example, the total duration of the animation is
ten seconds and there are four key frames each of which
are set to "Uniform", therefore, the duration of each key frame
is 3.3 seconds (10/3). -->
<LinearDoubleKeyFrame Value="100" KeyTime="Uniform" />
<LinearDoubleKeyFrame Value="200" KeyTime="Uniform" />
<LinearDoubleKeyFrame Value="500" KeyTime="Uniform" />
<LinearDoubleKeyFrame Value="600" KeyTime="Uniform" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

Valor especial, Paced


Use Paced agota el tiempo cuando desea animar a una velocidad constante.
Un Paced tiempo clave asigna el tiempo disponible según la longitud de cada uno de los fotogramas clave
para determinar la duración de cada fotograma. Esto proporcionará el comportamiento de que la velocidad
o el ritmo de la animación siga constante. El ejemplo siguiente muestra una animación con una duración de
10 segundos y fotogramas clave tres veces cuya clave se especifican como Paced.
<!-- Using Paced Values. Rectangle moves between key frames at
uniform rate except for first key frame
because using a Paced value on the first KeyFrame in a
collection of frames gives a time of zero. -->
<Rectangle Height="50" Width="50" Fill="Orange">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform04" X="10" Y="270" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform04"
Storyboard.TargetProperty="X"
Duration="0:0:10"
RepeatBehavior="Forever">

<!-- KeyTime properties are expressed with values of Paced.


Paced values are used when a constant rate is desired.
The time allocated to a key frame with a KeyTime of "Paced"
is determined by the time allocated to the other key
frames of the animation. This time is calculated to
attempt to give a "paced" or "constant velocity"
for the animation. -->
<LinearDoubleKeyFrame Value="100" KeyTime="Paced" />
<LinearDoubleKeyFrame Value="200" KeyTime="Paced" />
<LinearDoubleKeyFrame Value="500" KeyTime="Paced" />
<LinearDoubleKeyFrame Value="600" KeyTime="Paced" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

Tenga en cuenta que, si el tiempo clave del último fotograma clave es Paced o Uniform, el tiempo clave
resuelto se establecerá en 100 por ciento. Si el primer fotograma clave de una animación de varios
fotogramas es Paced, el tiempo clave resuelto se establecerá en 0. (Si la colección de fotogramas clave solo
contiene un fotograma clave y es un fotograma clave Paced, el tiempo clave resuelto se establecerá en 100
por ciento).
Los distintos fotogramas clave dentro de una animación de fotogramas clave pueden usar distintos tipos de
tiempo clave.

Combinación de tiempos clave y fotogramas clave desordenados


Puede usar fotogramas clave con diferentes KeyTime tipos en la misma animación de valor. Además, si bien
se recomienda agregar fotogramas clave en el orden en que se deben reproducir, no es necesario hacerlo.
El sistema de control de tiempo y animación es capaz de resolver los fotogramas clave desordenados. Se
omiten los fotogramas con tiempos clave no válidos.
En la lista siguiente se describe el procedimiento mediante el cual se resuelven los tiempos clave para los
fotogramas clave de una animación de fotogramas clave.
1. Resolver TimeSpan KeyTime valores.
2. Determine el tiempo de interpolación total, que es el tiempo total que la animación de fotogramas
clave tarda en completar una iteración de avance.
a. Si la animación Duration no Automatic o Forever, el tiempo de interpolación total es el valor
de la animación Duration propiedad.
b. En caso contrario, es el mayor tiempo de interpolación total TimeSpan KeyTime valor
especificado entre sus fotogramas clave, si existe alguno.
c. De lo contrario, el tiempo de interpolación total es de 1 segundo.
3. Utilice el valor de tiempo de interpolación total para resolver Percent KeyTime valores.
4. Resuelva el último fotograma clave, si no se resolvió ya en los pasos anteriores. Si el KeyTime del
último fotograma clave es Uniform o Paced, su tiempo de resolución será igual que el tiempo de
interpolación total.
Si el KeyTime del primer fotograma clave es Paced y esta animación con más de en fotogramas
clave, resuelva su KeyTime valor en cero; si hay solo un fotograma clave y sus KeyTime valor es
Paced, se resuelve como el total tiempo de interpolación, tal como se describe en el paso anterior.
5. Resolver restantes Uniform KeyTime valores: cada una tiene una cuota similar del tiempo disponible.
Durante este proceso, sin resolver Paced KeyTime los valores se tratan temporalmente Uniform
KeyTime valores y get hora de resolución de un archivo temporal.
6. Resolver la KeyTime valores de fotogramas clave con tiempos clave no especificados mediante el
uso de los fotogramas clave declarados más cercanos que se han resuelto KeyTime valores.
7. Resolver restantes Paced KeyTime valores. Paced KeyTime Utilice el KeyTime fotogramas para
determinar el tiempo de resolución de clave de los valores de los vecinos. El objetivo es garantizar
que la velocidad de la animación sea constante alrededor del tiempo de resolución de este
fotograma clave.
8. Ordene los fotogramas clave en tiempo de resolución (clave principal) y el orden de declaración
(clave secundaria), es decir, utilice un orden estable basado en el fotograma clave resueltos KeyTime
valores.

Vea también
KeyTime
KeySpline
Timeline
Ejemplo de animación de curva Spline clave
Ejemplo de animación de fotogramas clave
Información general sobre animaciones
Información general sobre objetos Storyboard
Temas de procedimientos de fotogramas clave
Información general sobre comportamientos de control de tiempo
Funciones de aceleración
23/10/2019 • 6 minutes to read • Edit Online

Las funciones de aceleración le permiten aplicar fórmulas matemáticas personalizadas a las animaciones. Por
ejemplo, puede que quiera que un objeto rebote de forma realista o se comporte como si estuviera sobre un
muelle. Podría usar animaciones de fotogramas clave o incluso animaciones From/To/By para aproximarse a estos
efectos pero supondría bastante trabajo y la animación sería menos precisa que si usa un fórmula matemática.
Además de crear su propia función de aceleración personalizada heredando EasingFunctionBasede, puede usar
una de las diversas funciones de aceleración proporcionadas por el motor en tiempo de ejecución para crear
efectos comunes.
BackEase: Retira ligeramente el movimiento de una animación antes de que empiece a animarse en la ruta
de acceso indicada.
BounceEase: Crea un efecto de rebote.
CircleEase: Crea una animación que acelera y/o desacelera mediante una función circular.
CubicEase: Crea una animación que acelera y/o desacelera mediante la fórmula f(t) = t3.
ElasticEase: Crea una animación que se parece a un muelle que oscila hacia atrás y hacia delante hasta que
llegue al resto.
ExponentialEase: Crea una animación que acelera y/o desacelera mediante una fórmula exponencial.
PowerEase: Crea una animación que acelera y/o desacelera mediante la fórmula f(t) = tp , donde p es igual a
la Power propiedad.
QuadraticEase: Crea una animación que acelera y/o desacelera mediante la fórmula f(t) = t2.
QuarticEase: Crea una animación que acelera y/o desacelera mediante la fórmula f(t) = t4.
QuinticEase: Cree una animación que acelere y/o desacelera mediante la fórmula f(t) = t5.
SineEase: Crea una animación que acelera y/o desacelera mediante una fórmula de seno.
Para aplicar una función de aceleración a una animación, use EasingFunction la propiedad de la animación
especifique la función de aceleración que se va a aplicar a la animación. En el ejemplo siguiente se BounceEase
aplica una función de DoubleAnimation aceleración a un para crear un efecto de rebote.
<Rectangle Name="myRectangle" Width="200" Height="30" Fill="Blue">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseDown">
<BeginStoryboard>
<Storyboard>
<Storyboard x:Name="myStoryboard">
<DoubleAnimation From="30" To="200" Duration="00:00:3"
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="Height">
<DoubleAnimation.EasingFunction>
<BounceEase Bounces="2" EasingMode="EaseOut"
Bounciness="2" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

En el ejemplo anterior, la función de aceleración se aplicó a una animación From/To/By. También puede aplicar
estas funciones de aceleración a animaciones de fotogramas clave. En el ejemplo siguiente se muestra cómo usar
fotogramas clave con funciones de aceleración asociadas a ellos para crear una animación de un rectángulo que se
contrae hacia arriba, se ralentiza, se expande hacia abajo (como si cayera) y luego rebota hasta detenerse.

<Rectangle Name="myRectangle" Width="200" Height="200" Fill="Blue">


<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="Height"
Storyboard.TargetName="myRectangle">

<!-- This keyframe animates the ellipse up to the crest


where it slows down and stops. -->
<EasingDoubleKeyFrame Value="30" KeyTime="00:00:02">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>

<!-- This keyframe animates the ellipse back down and makes
it bounce. -->
<EasingDoubleKeyFrame Value="200" KeyTime="00:00:06">
<EasingDoubleKeyFrame.EasingFunction>
<BounceEase Bounces="5" EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>

</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>

</Rectangle>

Puede usar la EasingMode propiedad para modificar el comportamiento de la función de aceleración, es decir,
cambiar el modo en que se interpola la animación. Hay tres posibles valores que puede proporcionar para
EasingMode:
EaseIn: La interpolación sigue la fórmula matemática asociada a la función de aceleración.
EaseOut: La interpolación sigue la interpolación del 100% menos el resultado de la fórmula asociada con la
función de aceleración.
EaseInOut: La interpolación EaseIn utiliza para la primera mitad de la animación EaseOut y para la segunda
mitad.
Los gráficos siguientes muestran los distintos valores de donde EasingMode f(x) representa el progreso de la
animación y t representa el tiempo.
BackEase

BounceEase

CircleEase

CubicEase

ElasticEase

ExponentialEase

PowerEase
QuadraticEase

QuarticEase

QuinticEase

SineEase

NOTE
Puede usar PowerEase para crear el mismo comportamiento que CubicEase, QuadraticEase, QuarticEasey QuinticEase
mediante la Power propiedad. Por ejemplo, si desea usar PowerEase para sustituir por CubicEase, especifique un Power valor
de 3.

Además de usar las funciones de aceleración que se incluyen en el tiempo de ejecución, puede crear sus propias
funciones personalizadas de aceleración heredando EasingFunctionBasede. En el ejemplo siguiente se muestra
cómo crear una función de aceleración simple personalizada. Puede agregar su propia lógica matemática para el
comportamiento de la función de aceleración invalidando el EaseInCore método.
namespace CustomEasingFunction
{
public class CustomSeventhPowerEasingFunction : EasingFunctionBase
{
public CustomSeventhPowerEasingFunction()
: base()
{
}

// Specify your own logic for the easing function by overriding


// the EaseInCore method. Note that this logic applies to the "EaseIn"
// mode of interpolation.
protected override double EaseInCore(double normalizedTime)
{
// applies the formula of time to the seventh power.
return Math.Pow(normalizedTime, 7);
}

// Typical implementation of CreateInstanceCore


protected override Freezable CreateInstanceCore()
{

return new CustomSeventhPowerEasingFunction();


}
}
}

Namespace CustomEasingFunction
Public Class CustomSeventhPowerEasingFunction
Inherits EasingFunctionBase
Public Sub New()
MyBase.New()
End Sub

' Specify your own logic for the easing function by overriding
' the EaseInCore method. Note that this logic applies to the "EaseIn"
' mode of interpolation.
Protected Overrides Function EaseInCore(ByVal normalizedTime As Double) As Double
' applies the formula of time to the seventh power.
Return Math.Pow(normalizedTime, 7)
End Function

' Typical implementation of CreateInstanceCore


Protected Overrides Function CreateInstanceCore() As Freezable

Return New CustomSeventhPowerEasingFunction()


End Function

End Class
End Namespace
<Window x:Class="CustomEasingFunction.Window1"
xmlns:CustomEase="clr-namespace:CustomEasingFunction"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="500" Width="300">
<StackPanel>
<TextBlock Margin="10" TextWrapping="Wrap">Click on the rectangle to start the animation</TextBlock>
<StackPanel x:Name="LayoutRoot" Background="White">

<Rectangle Name="myRectangle" Width="200" Height="30" Fill="Blue">


<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="30" To="300" Duration="00:00:3"
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="Height">
<DoubleAnimation.EasingFunction>

<!-- You get the EasingMode property for free on your custom
easing function.-->
<CustomEase:CustomSeventhPowerEasingFunction EasingMode="EaseIn"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>

</Rectangle>

</StackPanel>
</StackPanel>

</Window>
Información general sobre animaciones en trazados
23/10/2019 • 13 minutes to read • Edit Online

En este tema se presentan las animaciones de trazado, que permiten usar un trazado geométrico para generar
valores de salida. Las animaciones de trazado son útiles para mover y girar objetos a lo largo de trazados
complejos.

Requisitos previos
Para entender este tema, debe estar familiarizado con WPF las características de animaciones. Para obtener una
introducción a las características de animación, vea el información general sobre animaciones.
Debido a que usa un PathGeometry objeto para definir una animación de trazado, también debe estar
familiarizado con PathGeometry y los diferentes tipos de PathSegment objetos. Para obtener más información,
consulte el información general sobre geometría.

¿Qué es una animación de trazado?


Una animación de trazado es un tipo de AnimationTimeline que usa un PathGeometry como entrada. En lugar de
establecer un From a, o mediante la propiedad (como lo haría para un From/To/By animación) o mediante
fotogramas clave (tal y como se usa para una animación de fotogramas clave), define un trazado geométrico y
usarlo para establecer el PathGeometry propiedad de la animación de trazado. A medida que la animación de
trazado avanza, lee la información de x, de y y del ángulo del trazado y usa esa información para generar la salida.
Las animaciones de trazado son muy útiles para animar un objeto a lo largo de un trazado complejo. Una manera
de mover un objeto a lo largo de una ruta de acceso consiste en usar un MatrixTransform y un
MatrixAnimationUsingPath para transformar un objeto a lo largo de un trazado complejo. En el ejemplo
siguiente se muestra esta técnica mediante el uso de la MatrixAnimationUsingPath objeto que se va a animar el
Matrix propiedad de un MatrixTransform. El MatrixTransform se aplica a un botón y hace que se mueva a lo largo
de un trazado curvo. Dado que el DoesRotateWithTangent propiedad está establecida en true , el rectángulo
gira a lo largo de la tangente de la ruta de acceso.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions" Margin="20">
<Canvas Width="400" Height="400">

<!-- The Button that is animated across the screen by animating


the MatrixTransform applied to the button. -->
<Button MinWidth="100" Content="A Button">
<Button.RenderTransform>
<MatrixTransform x:Name="ButtonMatrixTransform">
<MatrixTransform.Matrix >
<Matrix />
</MatrixTransform.Matrix>
</MatrixTransform>
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard>
<MatrixAnimationUsingPath
Storyboard.TargetName="ButtonMatrixTransform"
Storyboard.TargetProperty="Matrix"
DoesRotateWithTangent="True"
Duration="0:0:5"
RepeatBehavior="Forever" >
<MatrixAnimationUsingPath.PathGeometry>
<PathGeometry
Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"
PresentationOptions:Freeze="True" />
</MatrixAnimationUsingPath.PathGeometry>
</MatrixAnimationUsingPath>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
</Page>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SDKSample
{

/// <summary>
/// Shows how to animate an object along
/// a geometric path.
/// </summary>
public class MatrixAnimationUsingPathDoesRotateWithTangentExample : Page
{

public MatrixAnimationUsingPathDoesRotateWithTangentExample()
{
this.Margin = new Thickness(20);

// Create a NameScope for the page so that


// we can use Storyboards.
NameScope.SetNameScope(this, new NameScope());

// Create a button.
Button aButton = new Button();
aButton.MinWidth = 100;
aButton.Content = "A Button";

// Create a MatrixTransform. This transform


// will be used to move the button.
MatrixTransform buttonMatrixTransform = new MatrixTransform();
aButton.RenderTransform = buttonMatrixTransform;

// Register the transform's name with the page


// so that it can be targeted by a Storyboard.
this.RegisterName("ButtonMatrixTransform", buttonMatrixTransform);

// Create a Canvas to contain the button


// and add it to the page.
// Although this example uses a Canvas,
// any type of panel will work.
Canvas mainPanel = new Canvas();
mainPanel.Width = 400;
mainPanel.Height = 400;
mainPanel.Children.Add(aButton);
this.Content = mainPanel;

// Create the animation path.


PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = new Point(10, 100);
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(new Point(35, 0));
pBezierSegment.Points.Add(new Point(135, 0));
pBezierSegment.Points.Add(new Point(160, 100));
pBezierSegment.Points.Add(new Point(180, 190));
pBezierSegment.Points.Add(new Point(285, 200));
pBezierSegment.Points.Add(new Point(310, 100));
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);

// Freeze the PathGeometry for performance benefits.


animationPath.Freeze();

// Create a MatrixAnimationUsingPath to move the


// button along the path by animating
// its MatrixTransform.
MatrixAnimationUsingPath matrixAnimation =
new MatrixAnimationUsingPath();
matrixAnimation.PathGeometry = animationPath;
matrixAnimation.Duration = TimeSpan.FromSeconds(5);
matrixAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the animation's DoesRotateWithTangent property


// to true so that rotates the rectangle in addition
// to moving it.
matrixAnimation.DoesRotateWithTangent = true;

// Set the animation to target the Matrix property


// of the MatrixTransform named "ButtonMatrixTransform".
Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform");
Storyboard.SetTargetProperty(matrixAnimation,
new PropertyPath(MatrixTransform.MatrixProperty));

// Create a Storyboard to contain and apply the animation.


Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.Children.Add(matrixAnimation);

// Start the storyboard when the button is loaded.


aButton.Loaded += delegate(object sender, RoutedEventArgs e)
{
// Start the storyboard.
pathAnimationStoryboard.Begin(this);
};
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Namespace SDKSample

''' <summary>
''' Shows how to animate an object along
''' a geometric path.
''' </summary>
Public Class MatrixAnimationUsingPathDoesRotateWithTangentExample
Inherits Page

Public Sub New()


Me.Margin = New Thickness(20)

' Create a NameScope for the page so that


' we can use Storyboards.
NameScope.SetNameScope(Me, New NameScope())

' Create a button.


Dim aButton As New Button()
aButton.MinWidth = 100
aButton.Content = "A Button"

' Create a MatrixTransform. This transform


' will be used to move the button.
Dim buttonMatrixTransform As New MatrixTransform()
aButton.RenderTransform = buttonMatrixTransform

' Register the transform's name with the page


' so that it can be targeted by a Storyboard.
Me.RegisterName("ButtonMatrixTransform", buttonMatrixTransform)

' Create a Canvas to contain the button


' and add it to the page.
' Although this example uses a Canvas,
' any type of panel will work.
Dim mainPanel As New Canvas()
mainPanel.Width = 400
mainPanel.Height = 400
mainPanel.Children.Add(aButton)
Me.Content = mainPanel

' Create the animation path.


Dim animationPath As New PathGeometry()
Dim pFigure As New PathFigure()
pFigure.StartPoint = New Point(10, 100)
Dim pBezierSegment As New PolyBezierSegment()
pBezierSegment.Points.Add(New Point(35, 0))
pBezierSegment.Points.Add(New Point(135, 0))
pBezierSegment.Points.Add(New Point(160, 100))
pBezierSegment.Points.Add(New Point(180, 190))
pBezierSegment.Points.Add(New Point(285, 200))
pBezierSegment.Points.Add(New Point(310, 100))
pFigure.Segments.Add(pBezierSegment)
animationPath.Figures.Add(pFigure)

' Freeze the PathGeometry for performance benefits.


animationPath.Freeze()

' Create a MatrixAnimationUsingPath to move the


' button along the path by animating
' its MatrixTransform.
Dim matrixAnimation As New MatrixAnimationUsingPath()
matrixAnimation.PathGeometry = animationPath
matrixAnimation.Duration = TimeSpan.FromSeconds(5)
matrixAnimation.RepeatBehavior = RepeatBehavior.Forever

' Set the animation's DoesRotateWithTangent property


' to true so that rotates the rectangle in addition
' to moving it.
matrixAnimation.DoesRotateWithTangent = True

' Set the animation to target the Matrix property


' of the MatrixTransform named "ButtonMatrixTransform".
Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform")
Storyboard.SetTargetProperty(matrixAnimation, New PropertyPath(MatrixTransform.MatrixProperty))

' Create a Storyboard to contain and apply the animation.


Dim pathAnimationStoryboard As New Storyboard()
pathAnimationStoryboard.Children.Add(matrixAnimation)

' Start the storyboard when the button is loaded.


AddHandler aButton.Loaded, Sub(sender As Object, e As RoutedEventArgs)
pathAnimationStoryboard.Begin(Me)

End Sub
End Class
End Namespace

Para obtener más información sobre la sintaxis de ruta de acceso que se usa en el XAML ejemplo, consulte el
sintaxis de marcado de trazados información general. Para obtener un ejemplo completo, vea ejemplo de
animación de trazado.
Puede aplicar una animación de trazado a una propiedad utilizando un Storyboard en XAML y el código o
mediante el BeginAnimation método en el código. También puede usar una animación de trazado para crear un
AnimationClock y aplicarla a una o varias propiedades. Para obtener más información sobre los distintos
métodos para aplicar animaciones, vea técnicas de animación de información general sobre propiedades.

Tipos de animación de trazado


Dado que las animaciones generan valores de propiedad, existen distintos tipos de animaciones para los diversos
tipos de propiedades. Para animar una propiedad que acepta un Double (como el X propiedad de un
TranslateTransform), se usa una animación que genera Double valores. Para animar una propiedad que acepta un
Point, use una animación que genera Point valores y así sucesivamente.
Clases de animación de trazado pertenecen a la System.Windows.Media.Animation espacio de nombres y use la
convención de nomenclatura siguiente:
<Tipo> AnimationUsingPath

Donde <Tipo> es el tipo de valor que la clase anima.


WPF proporciona las siguientes clases de animación de trazado.
CLASE DE ANIMACIÓN DE TRAZADO
TIPO DE PROPIEDAD CORRESPONDIENTE EJEMPLO

Double DoubleAnimationUsingPath Animación de un objeto a lo largo de


un trazado (animación doble)

Matrix MatrixAnimationUsingPath Animación de un objeto a lo largo de


un trazado (animación de matriz)

Point PointAnimationUsingPath Animación de un objeto a lo largo de


un trazado (animación en punto)

Un MatrixAnimationUsingPath genera Matrix los valores de sus PathGeometry. Cuando se usa con un
MatrixTransform, un MatrixAnimationUsingPath puede mover un objeto a lo largo de una ruta de acceso. Si
establece la DoesRotateWithTangent propiedad de la MatrixAnimationUsingPath a true , también gira el objeto
a lo largo de las curvas de la ruta de acceso.
Un PointAnimationUsingPath genera Point valores de las coordenadas x e y-de su PathGeometry. Mediante el
uso de un PointAnimationUsingPath para animar una propiedad que acepta Point valores, puede mover un
objeto a lo largo de una ruta de acceso. Un PointAnimationUsingPath no se puede girar objetos.
Un DoubleAnimationUsingPath genera Double los valores de sus PathGeometry. Estableciendo el Source
propiedad, puede especificar si el DoubleAnimationUsingPath usa la coordenada x, la coordenada y o el ángulo
de la ruta de acceso como salida. Puede usar un DoubleAnimationUsingPath para girar un objeto o moverlo a lo
largo del eje x o del eje y.

Entrada de animación de trazado


Cada clase de animación de trazado proporciona una PathGeometry propiedad para especificar su entrada. La
animación de trazado usa el PathGeometry para generar sus valores de salida. La PathGeometry clase le permite
describir varias figuras complejas que se componen de arcos, curvas y líneas.
En el corazón de un PathGeometry es una colección de PathFigure objetos; estos objetos, denominados así
porque cada figura describe una forma discreta del PathGeometry. Cada PathFigure consta de uno o varios
PathSegment objetos, cada uno de los cuales describe un segmento de la figura.
Hay muchos tipos de segmentos.

TIPO DE SEGMENTO DESCRIPCIÓN

ArcSegment Crea un arco elíptico entre dos puntos.

BezierSegment Crea una curva Bézier cúbica entre dos puntos.

LineSegment Crea una línea entre dos puntos.

PolyBezierSegment Crea una serie de curvas Bézier cúbicas.

PolyLineSegment Crea una serie de líneas.

PolyQuadraticBezierSegment Crea una serie de curvas Bézier cuadráticas.

QuadraticBezierSegment Crea una curva Bézier cuadrática.

Los segmentos en una PathFigure se combinan en una sola forma geométrica, que usa el punto final de un
segmento como el punto inicial del segmento siguiente. El StartPoint propiedad de un PathFigure especifica el
punto desde el que se dibuja el primer segmento. Cada segmento posterior comienza en el punto final del
segmento anterior. Por ejemplo, una línea vertical desde 10,50 a 10,150 pueden definirse mediante el
establecimiento la StartPoint propiedad 10,50 y la creación de un LineSegment con un Point configuración de la
propiedad de 10,150 .
Para obtener más información acerca de PathGeometry objetos, vea el información general sobre geometría.
En XAML, también puede usar una sintaxis abreviada especial para establecer el Figures propiedad de un
PathGeometry. Para obtener más información, consulte sintaxis de marcado de trazados información general.
Para obtener más información sobre la sintaxis de ruta de acceso que se usa en el XAML ejemplo, consulte el
sintaxis de marcado de trazados información general.

Vea también
Ejemplo de animación de trazado
Sintaxis de marcado de trazados
Temas de procedimientos de animación de trazado
Información general sobre animaciones
Información general sobre técnicas de animación de propiedades
Información general sobre técnicas de animación
de propiedades
23/10/2019 • 15 minutes to read • Edit Online

En este tema se describen los enfoques diferentes para animar propiedades: guiones gráficos, animaciones
locales, relojes y animaciones por fotograma.

Requisitos previos
Para entender este tema, debe estar familiarizado con las características de animación básicas descritas en
Información general sobre animaciones.

Diferentes maneras de animar


Dado que hay muchos escenarios diferentes para animar propiedades, WPF proporciona varios enfoques
para ello.
Para cada enfoque, en la tabla siguiente se indica si se puede utilizar por instancia, en estilos, en plantillas de
control o en plantillas de datos; si se puede utilizar en XAML; y si el enfoque permite controlar
interactivamente la animación. "Por instancia" se refiere a la técnica de aplicar directamente una animación o
guión gráfico a las instancias de un objeto, en lugar de en un estilo, una plantilla de control o una plantilla de
datos.

TÉCNICA DE ANIMACIÓN ESCENARIOS ADMITE XAML CONTROL INTERACTIVO

Animación de guión gráfico Por instancia, Style, Sí Sí


ControlTemplate,
DataTemplate

Animación local Por instancia No No

Animación de reloj Por instancia No Sí

Animación por fotograma Por instancia No N/D

Animaciones de guión gráfico


Use un Storyboard cuando desee definir y aplicar animaciones en XAMLde forma interactiva controlar las
animaciones después de iniciar, crear un árbol complejo de animaciones o animar en un Style,
ControlTemplate o DataTemplate. Animar un objeto un Storyboard, debe ser un FrameworkElement o
FrameworkContentElement, o se debe utilizar para establecer un FrameworkElement o
FrameworkContentElement. Para obtener más detalles, consulte Información general sobre objetos
Storyboard.
Un Storyboard es un tipo especial de contenedor Timeline que proporciona información de destino para las
animaciones que contiene. Para animar con un Storyboard, complete los tres pasos siguientes.
1. Declarar un Storyboard y animaciones de uno o más.
2. Use la TargetName y TargetProperty adjunta propiedades para especificar el objeto de destino y
propiedad de cada animación.
3. (Solo código) Definir un NameScope para un FrameworkElement o FrameworkContentElement.
Registrar los nombres de los objetos que se va a animar con ese FrameworkElement o
FrameworkContentElement.
4. Comenzar la Storyboard.
A partir de un Storyboard se aplican animaciones a las propiedades que animan y las inicia. Hay dos maneras
de comenzar un Storyboard: puede usar el Begin método proporcionado por el Storyboard clase, o bien puede
usar un BeginStoryboard acción. La única forma de animar en XAML consiste en usar un BeginStoryboard
acción. Un BeginStoryboard acción se puede usar en un EventTrigger, propiedad Trigger, o un DataTrigger.
La siguiente tabla muestra los diferentes lugares donde cada Storyboard comenzar es compatible con la
técnica: por instancia, estilo, plantilla de control y plantilla de datos.

EL GUIÓN
GRÁFICO SE
COMIENZA PLANTILLA DE PLANTILLA DE
UTILIZANDO... POR INSTANCIA ESTILO CONTROL DATOS EJEMPLO

BeginStoryboard Sí Sí Sí Sí Animar una


y una propiedad
EventTrigger utilizando un
guión gráfico

BeginStoryboard No Sí Sí Sí Activar una


y una propiedad animación al
Trigger cambiar el valor
de una
propiedad

BeginStoryboard No Sí Sí Sí Cómo: Activar


y un DataTrigger una animación
cuando cambian
los datos

Método Begin Sí No No No Animar una


propiedad
utilizando un
guión gráfico

Para obtener más información acerca de Storyboard objetos, vea el Storyboards Overview.

Animaciones locales
Las animaciones locales proporcionan una manera cómoda de animar una propiedad de dependencia de
cualquier Animatable objeto. Las animaciones locales se utilizan cuando se desea aplicar una sola animación a
una propiedad y no se necesita controlar interactivamente la animación después de iniciarse. A diferencia de
un Storyboard animación, una animación local puede animar un objeto que no está asociado con un
FrameworkElement o FrameworkContentElement. También no tiene que definir un NameScope para este tipo
de animación.
Las animaciones locales únicamente se pueden utilizar mediante código y no se pueden definir en estilos,
plantillas de control ni plantillas de datos. Una animación local no se puede controlar interactivamente una vez
iniciada.
Para animar mediante una animación local, complete los pasos siguientes.
1. Crear un AnimationTimeline objeto.
2. Use la BeginAnimation método del objeto que desea animar para aplicar el AnimationTimeline a la
propiedad que especifique.
El ejemplo siguiente muestra cómo animar el color de fondo y de ancho de un Button.

/*

This sample demonstrates how to apply non-storyboard animations to a property.


To animate in markup, you must use storyboards.

*/

using namespace System;


using namespace System::Windows;
using namespace System::Windows::Navigation;
using namespace System::Windows::Media;
using namespace System::Windows::Media::Animation;
using namespace System::Windows::Shapes;
using namespace System::Windows::Controls;

namespace Microsoft {
namespace Samples {
namespace Animation {
namespace LocalAnimations {
// Create the demonstration.
public ref class LocalAnimationExample : Page {

public:
LocalAnimationExample ()
{
WindowTitle = "Local Animation Example";
StackPanel^ myStackPanel = gcnew StackPanel();
myStackPanel->Margin = Thickness(20);

// Create and set the Button.


Button^ aButton = gcnew Button();
aButton->Content = "A Button";

// Animate the Button's Width.


DoubleAnimation^ myDoubleAnimation = gcnew DoubleAnimation();
myDoubleAnimation->From = 75;
myDoubleAnimation->To = 300;
myDoubleAnimation->Duration = Duration(TimeSpan::FromSeconds(5));
myDoubleAnimation->AutoReverse = true;
myDoubleAnimation->RepeatBehavior = RepeatBehavior::Forever;

// Apply the animation to the button's Width property.


aButton->BeginAnimation(Button::WidthProperty, myDoubleAnimation);

// Create and animate a Brush to set the button's Background.


SolidColorBrush^ myBrush = gcnew SolidColorBrush();
myBrush->Color = Colors::Blue;

ColorAnimation^ myColorAnimation = gcnew ColorAnimation();


myColorAnimation->From = Colors::Blue;
myColorAnimation->To = Colors::Red;
myColorAnimation->Duration = Duration(TimeSpan::FromMilliseconds(7000));
myColorAnimation->AutoReverse = true;
myColorAnimation->RepeatBehavior = RepeatBehavior::Forever;

// Apply the animation to the brush's Color property.


myBrush->BeginAnimation(SolidColorBrush::ColorProperty, myColorAnimation);
aButton->Background = myBrush;

// Add the Button to the panel.


// Add the Button to the panel.
myStackPanel->Children->Add(aButton);
this->Content = myStackPanel;
};
};
}
}
}
}
/*

This sample demonstrates how to apply non-storyboard animations to a property.


To animate in markup, you must use storyboards.

*/

using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls;

namespace Microsoft.Samples.Animation.LocalAnimations
{

// Create the demonstration.


public class LocalAnimationExample : Page
{

public LocalAnimationExample()
{

WindowTitle = "Local Animation Example";


StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(20);

// Create and set the Button.


Button aButton = new Button();
aButton.Content = "A Button";

// Animate the Button's Width.


DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 75;
myDoubleAnimation.To = 300;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Apply the animation to the button's Width property.


aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation);

// Create and animate a Brush to set the button's Background.


SolidColorBrush myBrush = new SolidColorBrush();
myBrush.Color = Colors.Blue;

ColorAnimation myColorAnimation = new ColorAnimation();


myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.Red;
myColorAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(7000));
myColorAnimation.AutoReverse = true;
myColorAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Apply the animation to the brush's Color property.


myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation);
aButton.Background = myBrush;

// Add the Button to the panel.


myStackPanel.Children.Add(aButton);
this.Content = myStackPanel;
}
}
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''This sample demonstrates how to apply non-storyboard animations to a property.
'''To animate in markup, you must use storyboards.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Imports System.Windows
Imports System.Windows.Navigation
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Imports System.Windows.Controls

Namespace Microsoft.Samples.Animation.LocalAnimations

' Create the demonstration.


Public Class LocalAnimationExample
Inherits Page

Public Sub New()

WindowTitle = "Animate Property Example"


Dim myStackPanel As New StackPanel()
myStackPanel.Margin = New Thickness(20)

' Create and set the Button.


Dim aButton As New Button()
aButton.Content = "A Button"

' Animate the Button's Width.


Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 75
myDoubleAnimation.To = 300
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))
myDoubleAnimation.AutoReverse = True
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever

' Apply the animation to the button's Width property.


aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation)

' Create and animate a Brush to set the button's Background.


Dim myBrush As New SolidColorBrush()
myBrush.Color = Colors.Blue

Dim myColorAnimation As New ColorAnimation()


myColorAnimation.From = Colors.Blue
myColorAnimation.To = Colors.Red
myColorAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(7000))
myColorAnimation.AutoReverse = True
myColorAnimation.RepeatBehavior = RepeatBehavior.Forever

' Apply the animation to the brush's Color property.


myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation)
aButton.Background = myBrush

' Add the Button to the panel.


myStackPanel.Children.Add(aButton)
Me.Content = myStackPanel
End Sub
End Class
End Namespace

Animaciones de reloj
Use Clock objetos cuando desea animar sin utilizar un Storyboard y desea crear árboles de control de tiempo
complejos o controlar interactivamente las animaciones después de iniciarse. Puede usar los objetos de reloj
para animar una propiedad de dependencia de cualquier Animatable objeto.
No puede usar Clock objetos controlan directamente a animar en estilos, plantillas o plantillas de datos. (Use
el sistema de animación y temporización realmente Clock objetos que se va a animar en estilos, plantillas de
control y plantillas de datos, pero deben crearlos Clock objetos para usted desde un Storyboard. Para obtener
más información sobre la relación entre Storyboard objetos y Clock objetos, vea el Animation and Timing
System Overview.)
Para aplicar una sola Clock a una propiedad, complete los pasos siguientes.
1. Crear un AnimationTimeline objeto.
2. Use la CreateClock método de la AnimationTimeline para crear un AnimationClock.
3. Use la ApplyAnimationClock método del objeto que desea animar para aplicar el AnimationClock a la
propiedad especificada.
El ejemplo siguiente muestra cómo crear un AnimationClock y aplicarlo a dos propiedades similares.

/*
This example shows how to create and apply
an AnimationClock.
*/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{
public class AnimationClockExample : Page
{

ScaleTransform myScaleTransform;

public AnimationClockExample()
{

this.WindowTitle = "Opacity Animation Example";


this.Background = Brushes.White;
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(20);

// Create a button that with a ScaleTransform.


// The ScaleTransform will animate when the
// button is clicked.
Button myButton = new Button();
myButton.Margin = new Thickness(50);
myButton.HorizontalAlignment = HorizontalAlignment.Left;
myButton.Content = "Click Me";
myScaleTransform = new ScaleTransform(1,1);
myButton.RenderTransform = myScaleTransform;

// Associate an event handler with the


// button's Click event.
myButton.Click += new RoutedEventHandler(myButton_Clicked);

myStackPanel.Children.Add(myButton);
this.Content = myStackPanel;
}

// Create and apply and animation when the button is clicked.


private void myButton_Clicked(object sender, RoutedEventArgs e)
private void myButton_Clicked(object sender, RoutedEventArgs e)
{

// Create a DoubleAnimation to animate the


// ScaleTransform.
DoubleAnimation myAnimation =
new DoubleAnimation(
1, // "From" value
5, // "To" value
new Duration(TimeSpan.FromSeconds(5))
);
myAnimation.AutoReverse = true;

// Create a clock the for the animation.


AnimationClock myClock = myAnimation.CreateClock();

// Associate the clock the ScaleX and


// ScaleY properties of the button's
// ScaleTransform.
myScaleTransform.ApplyAnimationClock(
ScaleTransform.ScaleXProperty, myClock);
myScaleTransform.ApplyAnimationClock(
ScaleTransform.ScaleYProperty, myClock);
}
}
}

'
' This example shows how to create and apply
' an AnimationClock.
'

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation

Namespace Microsoft.Samples.Animation.TimingBehaviors
Public Class AnimationClockExample
Inherits Page

Private ReadOnly myScaleTransform As ScaleTransform

Public Sub New()

WindowTitle = "Opacity Animation Example"


Background = Brushes.White
Dim myStackPanel As New StackPanel With {
.Margin = New Thickness(20)
}

' Create a button that with a ScaleTransform.


' The ScaleTransform will animate when the
' button is clicked.
Dim myButton As New Button With {
.Margin = New Thickness(50),
.HorizontalAlignment = HorizontalAlignment.Left,
.Content = "Click Me"
}
myScaleTransform = New ScaleTransform(1,1)
myButton.RenderTransform = myScaleTransform

' Associate an event handler with the


' button's Click event.
AddHandler myButton.Click, AddressOf myButton_Clicked

myStackPanel.Children.Add(myButton)
Content = myStackPanel
End Sub

' Create and apply and animation when the button is clicked.
Private Sub myButton_Clicked(sender As Object, e As RoutedEventArgs)

' Create a DoubleAnimation to animate the


' ScaleTransform.
Dim myAnimation As New DoubleAnimation(1, 5, New Duration(TimeSpan.FromSeconds(5))) With {
.AutoReverse = True
} ' "To" value - "From" value

' Create a clock the for the animation.


Dim myClock As AnimationClock = myAnimation.CreateClock()

' Associate the clock the ScaleX and


' ScaleY properties of the button's
' ScaleTransform.
myScaleTransform.ApplyAnimationClock(ScaleTransform.ScaleXProperty, myClock)
myScaleTransform.ApplyAnimationClock(ScaleTransform.ScaleYProperty, myClock)
End Sub
End Class
End Namespace

Para crear un árbol de control de tiempo y utilizarlo para animar propiedades, complete los pasos siguientes.
1. Use ParallelTimeline y AnimationTimeline objetos para crear el árbol de control de tiempo.
2. Use la CreateClock de la raíz ParallelTimeline para crear un ClockGroup.
3. Recorrer en iteración el Children de la ClockGroup y se aplican a su elemento secundario Clock objetos.
Para cada AnimationClock secundario, use la ApplyAnimationClock método del objeto que desea
animar para aplicar el AnimationClock a la propiedad especificada
Para más información acerca de los objetos de reloj, consulte Información general sobre sistemas de
temporización y animación.

Animación por fotograma: Omitir el sistema de temporización y


animación
Utilice este enfoque cuando necesite omitir completamente el sistema de animación de WPF. Un escenario
para este enfoque lo constituyen las animaciones físicas, donde a cada paso de la animación es preciso volver
a calcular los objetos basándose en el último conjunto de interacciones de objeto.
Las animaciones por fotograma no se pueden definir dentro de estilos, plantillas de control ni plantillas de
datos.
Para animar fotograma a fotograma, se registra para el Rendering eventos del objeto que contiene los objetos
que desee animar. Se llama a este método de control de eventos una vez por cada fotograma. Cada vez que
WPF serializa los datos de representación conservados en el árbol visual hasta el árbol de composición, se
llama a este método de control de eventos.
En el controlador de eventos, realice los cálculos necesarios para el efecto de animación y establezca las
propiedades de los objetos que desea animar con estos valores.
Para obtener el tiempo de presentación del fotograma actual, el EventArgs asociado a este evento se puede
convertir RenderingEventArgs, que proporcionan un RenderingTime el tiempo de representación de
propiedad que se puede utilizar para obtener el marco actual.
Para obtener más información, consulte la Rendering página.

Vea también
Información general sobre animaciones
Información general sobre objetos Storyboard
Información general sobre sistemas de control de tiempo y animación
Información general sobre las propiedades de dependencia
Información general sobre objetos Storyboard
08/01/2020 • 34 minutes to read • Edit Online

En este tema se muestra cómo usar objetos Storyboard para organizar y aplicar animaciones. Describe
cómo manipular interactivamente Storyboard objetos y describe la sintaxis de destinatarios de propiedades
indirectas.

Requisitos previos
Para entender este tema, debe estar familiarizado con los distintos tipos de animaciones y sus
características básicas. Para obtener una introducción a la animación, consulte Información general sobre
animaciones. También debe saber utilizar las propiedades asociadas. Para obtener más información sobre
las propiedades adjuntas, consulte Información general sobre propiedades asociadas.

¿Qué es un guión gráfico?


Las animaciones no son el único tipo útil de escala de tiempo. Se proporcionan otras clases de escalas de
tiempo para ayudarle a organizar conjuntos de escalas de tiempo y para aplicar las escalas de tiempo a las
propiedades. Las escalas de tiempo de contenedor derivan de la clase TimelineGroup e incluyen
ParallelTimeline y Storyboard.
Un Storyboard es un tipo de escala de tiempo de contenedor que proporciona información de destino para
las escalas de tiempo que contiene. Un guión gráfico puede contener cualquier tipo de Timeline, incluidas
otras escalas de tiempo y animaciones de contenedor. Storyboard objetos permiten combinar las escalas de
tiempo que afectan a una variedad de objetos y propiedades en un único árbol de escala de tiempo, lo que
facilita la organización y el control de los comportamientos complejos de temporización. Por ejemplo,
supongamos que desea un botón que haga estas tres cosas.
Aumentar de tamaño y cambiar de color cuando el usuario selecciona el botón.
Disminuir de tamaño y volver a su tamaño original cuando se hace clic en él.
Disminuir de tamaño y desvanecerse con un fundido al 50 % de opacidad al deshabilitarse.
En este caso, tenemos varios conjuntos de animaciones que se aplican al mismo objeto, y hay que
reproducirlas en distintos momentos, según cuál sea el estado del botón. Storyboard objetos permiten
organizar animaciones y aplicarlas en grupos a uno o varios objetos.

¿Dónde se puede utilizar un guión gráfico?


Un Storyboard se puede usar para animar propiedades de dependencia de clases que se pueden animar
(para obtener más información sobre lo que hace que una clase se pueda animar, vea información general
sobre animaciones). Sin embargo, dado que el guion gráfico es una característica de nivel de marco, el
objeto debe pertenecer al NameScope de un FrameworkElement o FrameworkContentElement.
Por ejemplo, puede usar un Storyboard para hacer lo siguiente:
Animar un SolidColorBrush (elemento que no es de marco) que pinta el fondo de un botón (un tipo
de FrameworkElement),
Animar un SolidColorBrush (elemento que no es de marco) que pinta el relleno de un
GeometryDrawing (elemento que no es de marco) mostrado mediante un Image
(FrameworkElement).
En el código, Anime una SolidColorBrush declarada por una clase que también contenga un
FrameworkElement, si el SolidColorBrush registró su nombre con ese FrameworkElement.
Sin embargo, no se puede usar un Storyboard para animar un SolidColorBrush que no haya registrado su
nombre con un FrameworkElement o FrameworkContentElement, o no se haya usado para establecer una
propiedad de un FrameworkElement o FrameworkContentElement.

Cómo aplicar animaciones mediante un guión gráfico


Para usar un Storyboard para organizar y aplicar animaciones, agregue las animaciones como escalas de
tiempo secundarias del Storyboard. La clase Storyboard proporciona las propiedades adjuntas
Storyboard.TargetName y Storyboard.TargetProperty. Se establecen estas propiedades de una animación
para especificar su objeto y propiedad de destino.
Para aplicar animaciones a sus destinos, comienza el Storyboard mediante una acción de desencadenador o
un método. En XAML, se usa un objeto BeginStoryboard con un EventTrigger, Triggero DataTrigger. En el
código, también puede utilizar el método Begin.
En la tabla siguiente se muestran los distintos lugares donde se admite cada Storyboard técnica de Inicio:
por instancia, estilo, plantilla de control y plantilla de datos. "Por instancia" se refiere a la técnica de aplicar
directamente una animación o guión gráfico a las instancias de un objeto, en lugar de en un estilo, una
plantilla de control o una plantilla de datos.

EL GUIÓN
GRÁFICO SE
COMIENZA PLANTILLA DE PLANTILLA DE
UTILIZANDO... POR INSTANCIA ESTILO CONTROL DATOS EJEMPLO

BeginStoryboar Sí Sí Sí Sí Animar una


d y un propiedad
EventTrigger utilizando un
guión gráfico

BeginStoryboar No Sí Sí Sí Activar una


d y una animación al
propiedad cambiar el valor
Trigger de una
propiedad

BeginStoryboar No Sí Sí Sí Cómo: Activar


d y un una animación
DataTrigger cuando se
cambian datos

Método Begin Sí No No No Animar una


propiedad
utilizando un
guión gráfico

En el ejemplo siguiente se usa un Storyboard para animar el Width de un elemento Rectangle y el Color de
una SolidColorBrush que se usa para pintar ese Rectangle.
<!-- This example shows how to animate with a storyboard.-->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.Animation.StoryboardsExample"
WindowTitle="Storyboards Example">
<StackPanel Margin="20">

<Rectangle Name="MyRectangle"
Width="100"
Height="100">
<Rectangle.Fill>
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Width"
From="100" To="200" Duration="0:0:1" />

<ColorAnimation
Storyboard.TargetName="MySolidColorBrush"
Storyboard.TargetProperty="Color"
From="Blue" To="Red" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Data;
using System.Windows.Shapes;
using System.Windows.Input;

namespace Microsoft.Samples.Animation
{
public class StoryboardsExample : Page
{
public StoryboardsExample()
{
this.WindowTitle = "Storyboards Example";
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(20);

Rectangle myRectangle = new Rectangle();


myRectangle.Name = "MyRectangle";

// Create a name scope for the page.


NameScope.SetNameScope(this, new NameScope());

this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
myRectangle.Fill = mySolidColorBrush;

DoubleAnimation myDoubleAnimation = new DoubleAnimation();


myDoubleAnimation.From = 100;
myDoubleAnimation.To = 200;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));

ColorAnimation myColorAnimation = new ColorAnimation();


myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.Red;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation,
new PropertyPath(SolidColorBrush.ColorProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
myStoryboard.Children.Add(myColorAnimation);

myRectangle.MouseEnter += delegate(object sender, MouseEventArgs e)


{
myStoryboard.Begin(this);
};

myStackPanel.Children.Add(myRectangle);
this.Content = myStackPanel;
}
}
}

En las secciones siguientes se describen con más detalle las propiedades adjuntas TargetName y
TargetProperty.
Establecer como destino elementos de marco, elementos de
contenido de marco y elementos inmovilizables
En la sección anterior se menciona que, para que una animación encuentre su destino, debe conocer el
nombre del mismo y la propiedad que debe animar. Especificar la propiedad que se va a animar es sencillo:
simplemente establezca Storyboard.TargetProperty con el nombre de la propiedad que se va a animar. Para
especificar el nombre del objeto cuya propiedad desea animar, establezca la propiedad
Storyboard.TargetName en la animación.
Para que la propiedad TargetName funcione, el objeto de destino debe tener un nombre. Asignar un
nombre a un FrameworkElement o un FrameworkContentElement en XAML es diferente de asignar un
nombre a un objeto de Freezable.
Los elementos de marco son las clases que heredan de la clase FrameworkElement. Entre los ejemplos de
elementos de marco se incluyen Window, DockPanel, Buttony Rectangle. En esencia, todas las ventanas, los
paneles y los controles son elementos. Los elementos de contenido de marco son las clases que heredan de
la clase FrameworkContentElement. Algunos ejemplos de elementos de contenido de marco son
FlowDocument y Paragraph. Si no está seguro de si un tipo es un elemento de marco o un elemento de
contenido de marco, compruebe si tiene una propiedad Name. Si la tiene, probablemente sea un elemento
de marco o un elemento de contenido de marco. Para estar seguro, compruebe la sección de jerarquía de
herencia de su página de tipo.
Para habilitar el destino de un elemento de marco o un elemento de contenido de marco de trabajo en
XAML, establezca su propiedad Name. En el código, también debe usar el método RegisterName para
registrar el nombre del elemento con el elemento para el que ha creado un NameScope.
En el ejemplo siguiente, tomado del ejemplo anterior, se asigna el nombre MyRectangle un Rectangle, un
tipo de FrameworkElement.

<Rectangle Name="MyRectangle"
Width="100"
Height="100">

Rectangle myRectangle = new Rectangle();


myRectangle.Name = "MyRectangle";

// Create a name scope for the page.


NameScope.SetNameScope(this, new NameScope());

this.RegisterName(myRectangle.Name, myRectangle);

Una vez que tenga un nombre, puede animar una propiedad de ese elemento.

<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Width"
From="100" To="200" Duration="0:0:1" />

Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));

Freezable tipos son las clases que heredan de la clase Freezable. Entre los ejemplos de Freezable se
incluyen SolidColorBrush, RotateTransformy GradientStop.
Para habilitar el destino de un Freezable por una animación en XAML, utilice la Directiva x:Name para
asignarle un nombre. En el código, se usa el método RegisterName para registrar su nombre en el
elemento para el que se ha creado un NameScope.
En el ejemplo siguiente se asigna un nombre a un objeto Freezable.

<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />

SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);


this.RegisterName("MySolidColorBrush", mySolidColorBrush);

A continuación, ya se puede establecer el objeto como destino de una animación.

<ColorAnimation
Storyboard.TargetName="MySolidColorBrush"
Storyboard.TargetProperty="Color"
From="Blue" To="Red" Duration="0:0:1" />

Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation,
new PropertyPath(SolidColorBrush.ColorProperty));

Storyboard objetos utilizan ámbitos de nombres para resolver la propiedad TargetName. Para obtener más
información sobre los ámbitos de nombres de WPF, consulte Ámbitos de nombres XAML de WPF. Si se
omite la propiedad TargetName, la animación tiene como destino el elemento en el que se define o, en el
caso de los estilos, el elemento con estilo.
A veces no se puede asignar un nombre a un objeto Freezable. Por ejemplo, si un Freezable se declara
como recurso o se utiliza para establecer un valor de propiedad en un estilo, no se le puede asignar un
nombre. Al no tener nombre, no se puede establecer como destino directamente, pero sí de manera
indirecta. En las secciones siguientes se describe cómo utilizar el establecimiento indirecto de destinos.

Establecimiento indirecto de destinos


Hay veces que una animación no puede destinar un Freezable directamente, como cuando el Freezable se
declara como recurso o se utiliza para establecer un valor de propiedad en un estilo. En estos casos, aunque
no pueda dirigirse directamente a él, todavía puede animar el objeto de Freezable. En lugar de establecer la
propiedad TargetName con el nombre del Freezable, se le asigna el nombre del elemento al que pertenece
el Freezable ". Por ejemplo, un SolidColorBrush que se usa para establecer el Fill de un elemento de
rectángulo pertenece a ese rectángulo. Para animar el pincel, debe establecer la TargetProperty de la
animación con una cadena de propiedades que comienza en la propiedad del elemento de marco o
elemento de contenido de marco de trabajo que el Freezable se usó para establecer y termina con la
propiedad Freezable que se va a animar.

<ColorAnimation
Storyboard.TargetName="Rectangle01"
Storyboard.TargetProperty="Fill.Color"
From="Blue" To="AliceBlue" Duration="0:0:1" />
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);

Tenga en cuenta que, si la Freezable está inmovilizada, se realizará un clon y se animará el clon. Cuando
esto sucede, la propiedad HasAnimatedProperties del objeto original continúa devolviendo false , porque
el objeto original no se anima realmente. Para obtener más información sobre la clonación, vea información
general sobre objetos Freezable.
Además, tenga en cuenta que, al utilizar el establecimiento indirecto de propiedades de destino, es posible
establecer como destino objetos que no existen. Por ejemplo, puede suponer que el Background de un
botón determinado se ha establecido con un SolidColorBrush e intenta animar su color, cuando en realidad
se ha usado un LinearGradientBrush para establecer el fondo del botón. En estos casos, no se produce
ninguna excepción; la animación no tiene ningún efecto visible porque LinearGradientBrush no reacciona a
los cambios en la propiedad Color.
En las secciones siguientes se describe con mayor detalle la sintaxis de establecimiento indirecto de
propiedades de destino.
Establecer de manera indirecta una propiedad de destino de un objeto inmovilizable en XAML
Para establecer como destino una propiedad de un Freezable en XAML, use la sintaxis siguiente.

ElementPropertyName . FreezablePropertyName

Dónde
ElementPropertyName es la propiedad de la FrameworkElement la que se usa el Freezable que se
va a establecer y
FreezablePropertyName es la propiedad del Freezable que se va a animar.
En el código siguiente se muestra cómo animar el Color de una SolidColorBrush utilizada para establecer el
Fill de un elemento de rectángulo.

<Rectangle
Name="Rectangle01"
Height="100"
Width="100"
Fill="{StaticResource MySolidColorBrushResource}">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Rectangle01"
Storyboard.TargetProperty="Fill.Color"
From="Blue" To="AliceBlue" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

En ocasiones, es preciso establecer como destino un objeto inmovilizable contenido en una colección o
matriz.
Para establecer como destino un objeto inmovilizable contenido en una colección, se utiliza la sintaxis de
ruta de acceso siguiente.

ElementPropertyName .Children[ CollectionIndex ]. FreezablePropertyName

Donde CollectionIndex es el índice del objeto en su matriz o colección.


Por ejemplo, supongamos que un rectángulo tiene un recurso TransformGroup aplicado a su propiedad
RenderTransform y desea animar una de las transformaciones que contiene.

<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>

En el código siguiente se muestra cómo animar la propiedad Angle de la RotateTransform que se muestra
en el ejemplo anterior.

<Rectangle
Name="Rectangle02"
Height="100"
Width="100"
Fill="Blue"
RenderTransform="{StaticResource MyTransformGroupResource}">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Rectangle02"
Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
From="0" To="360" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

Establecer de manera indirecta una propiedad de destino de un objeto inmovilizable mediante código
En el código, se crea un objeto PropertyPath. Al crear el PropertyPath, especifique un Path y
PathParameters.
Para crear PathParameters, cree una matriz de tipo DependencyProperty que contenga una lista de campos
de identificador de propiedad de dependencia. El primer campo de identificador es para la propiedad del
FrameworkElement o FrameworkContentElement que el Freezable se usa para establecer. El siguiente
campo de identificador representa la propiedad del Freezable de destino. Considérelo como una cadena de
propiedades que conecta el Freezable con el objeto FrameworkElement.
El siguiente es un ejemplo de una cadena de propiedades de dependencia que tiene como destino el Color
de una SolidColorBrush que se usa para establecer el Fill de un elemento de rectángulo.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};

También debe especificar una Path. Una Path es una String que indica al Path cómo interpretar su
PathParameters. Se usa la siguiente sintaxis:

( OwnerPropertyArrayIndex ).( FreezablePropertyArrayIndex )

Dónde
OwnerPropertyArrayIndex es el índice de la matriz DependencyProperty que contiene el
identificador de la propiedad del objeto FrameworkElement que el Freezable se usa para establecer y
FreezablePropertyArrayIndex es el índice de la matriz DependencyProperty que contiene el
identificador de la propiedad que se va a usar como destino.
En el ejemplo siguiente se muestra el Path que acompañaría al PathParameters definido en el ejemplo
anterior.

DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";

En el ejemplo siguiente se combina el código de los ejemplos anteriores para animar el Color de una
SolidColorBrush que se usa para establecer el Fill de un elemento de rectángulo.
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());

Rectangle rectangle01 = new Rectangle();


rectangle01.Name = "Rectangle01";
this.RegisterName(rectangle01.Name, rectangle01);
rectangle01.Width = 100;
rectangle01.Height = 100;
rectangle01.Fill =
(SolidColorBrush)this.Resources["MySolidColorBrushResource"];

ColorAnimation myColorAnimation = new ColorAnimation();


myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.AliceBlue;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myColorAnimation, rectangle01.Name);

DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);

Storyboard myStoryboard = new Storyboard();


myStoryboard.Children.Add(myColorAnimation);
BeginStoryboard myBeginStoryboard = new BeginStoryboard();
myBeginStoryboard.Storyboard = myStoryboard;
EventTrigger myMouseEnterTrigger = new EventTrigger();
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent;
myMouseEnterTrigger.Actions.Add(myBeginStoryboard);
rectangle01.Triggers.Add(myMouseEnterTrigger);

En ocasiones, es preciso establecer como destino un objeto inmovilizable contenido en una colección o
matriz. Por ejemplo, supongamos que un rectángulo tiene un recurso TransformGroup aplicado a su
propiedad RenderTransform y desea animar una de las transformaciones que contiene.

<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>

Para establecer como destino una Freezable incluida en una colección, use la sintaxis de ruta de acceso
siguiente.

( OwnerPropertyArrayIndex ).( CollectionChildrenPropertyArrayIndex ) [ CollectionIndex ].(


FreezablePropertyArrayIndex )

Donde CollectionIndex es el índice del objeto en su matriz o colección.


Para establecer como destino la propiedad Angle del RotateTransform, la segunda transformación de la
TransformGroup, usaría los siguientes Path y PathParameters.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{
Rectangle.RenderTransformProperty,
TransformGroup.ChildrenProperty,
RotateTransform.AngleProperty
};
string thePath = "(0).(1)[1].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath);

En el ejemplo siguiente se muestra el código completo para animar el Angle de un RotateTransform


contenido dentro de un TransformGroup.

Rectangle rectangle02 = new Rectangle();


rectangle02.Name = "Rectangle02";
this.RegisterName(rectangle02.Name, rectangle02);
rectangle02.Width = 100;
rectangle02.Height = 100;
rectangle02.Fill = Brushes.Blue;
rectangle02.RenderTransform =
(TransformGroup)this.Resources["MyTransformGroupResource"];

DoubleAnimation myDoubleAnimation = new DoubleAnimation();


myDoubleAnimation.From = 0;
myDoubleAnimation.To = 360;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myDoubleAnimation, rectangle02.Name);

DependencyProperty[] propertyChain =
new DependencyProperty[]
{
Rectangle.RenderTransformProperty,
TransformGroup.ChildrenProperty,
RotateTransform.AngleProperty
};
string thePath = "(0).(1)[1].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath);

Storyboard myStoryboard = new Storyboard();


myStoryboard.Children.Add(myDoubleAnimation);
BeginStoryboard myBeginStoryboard = new BeginStoryboard();
myBeginStoryboard.Storyboard = myStoryboard;
EventTrigger myMouseEnterTrigger = new EventTrigger();
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent;
myMouseEnterTrigger.Actions.Add(myBeginStoryboard);
rectangle02.Triggers.Add(myMouseEnterTrigger);

Establecimiento indirecto de destinos con un objeto inmovilizable como punto de partida


En las secciones anteriores se describe cómo destinar indirectamente un Freezable a partir de un
FrameworkElement o FrameworkContentElement y crear una cadena de propiedades a una subpropiedad
Freezable. También puede usar un Freezable como punto de partida y destinar indirectamente una de sus
subpropiedades de Freezable. Cuando se usa un Freezable como punto de partida para el establecimiento
indirecto de destinos, se aplica una restricción adicional: la Freezable inicial y cada Freezable entre ella y la
subpropiedad de destino indirectamente no se deben inmovilizar.

Controlar guiones gráficos de forma interactiva en XAML


Para iniciar un guion gráfico en Lenguaje XAML (Extensible Application Markup Language), se usa una
acción de desencadenador BeginStoryboard. BeginStoryboard distribuye las animaciones a los objetos y
propiedades que animan e inicia el guion gráfico. (Para obtener más información acerca de este proceso,
consulte información general sobre el sistema de control de tiempo y animación). Si asigna al
BeginStoryboard un nombre especificando su propiedad Name, lo convierte en un guión gráfico
controlable. A continuación, podrá controlar interactivamente el guión gráfico una vez iniciado. Esta es una
lista de acciones de guión gráfico controlables que se utiliza con desencadenadores de eventos para
controlar un guión gráfico.
PauseStoryboard: pausa el guion gráfico.
ResumeStoryboard: reanuda un guion gráfico en pausa.
SetStoryboardSpeedRatio: cambia la velocidad del guión gráfico.
SkipStoryboardToFill: hace avanzar un guión gráfico hasta el final de su período de relleno, si tiene
uno.
StopStoryboard: detiene el guion gráfico.
RemoveStoryboard: quita el guion gráfico.
En el ejemplo siguiente se utilizan acciones para controlar interactivamente un guión gráfico.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.SDK.Animation.ControllableStoryboardExample"
WindowTitle="Fading Rectangle Example">
<StackPanel Margin="10">

<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
</Rectangle>

<Button Name="BeginButton">Begin</Button>
<Button Name="PauseButton">Pause</Button>
<Button Name="ResumeButton">Resume</Button>
<Button Name="SkipToFillButton">Skip To Fill</Button>
<Button Name="StopButton">Stop</Button>

<StackPanel.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="(Rectangle.Opacity)"
From="1.0" To="0.0" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="PauseButton">
<PauseStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="ResumeButton">
<ResumeStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="SkipToFillButton">
<SkipStoryboardToFill BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
<StopStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>
</Page>

Controlar interactivamente un guión gráfico mediante código


En los ejemplos anteriores se muestra cómo animar mediante acciones de desencadenador. En el código,
también puede controlar un guión gráfico mediante métodos interactivos de la clase Storyboard. Para que
una Storyboard sea interactiva en el código, debe usar la sobrecarga adecuada del método Begin del guión
gráfico y especificar true para que se pueda controlar. Vea la página Begin(FrameworkElement, Boolean)
para obtener más información.
En la lista siguiente se muestran los métodos que se pueden utilizar para manipular una Storyboard una
vez que se ha iniciado:
Pause
Resume
Seek
SkipToFill
Stop
Remove
La ventaja de utilizar estos métodos es que no es necesario crear Trigger ni TriggerAction objetos; solo
necesita una referencia al Storyboard controlable que desee manipular.

NOTE
Todas las acciones interactivas realizadas en un Clocky, por tanto, también en un Storyboard se producirán en el
siguiente paso del motor de control de tiempo, que se producirá poco antes del siguiente procesamiento. Por
ejemplo, si usa el método Seek para saltar a otro punto de una animación, el valor de la propiedad no cambia al
instante, sino que el valor cambia en el siguiente paso del motor de control de tiempo.

En el ejemplo siguiente se muestra cómo aplicar y controlar animaciones mediante los métodos
interactivos de la clase Storyboard.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace SDKSample
{

public class ControllableStoryboardExample : Page


{
private Storyboard myStoryboard;

public ControllableStoryboardExample()
{

// Create a name scope for the page.

NameScope.SetNameScope(this, new NameScope());

this.WindowTitle = "Controllable Storyboard Example";


StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(10);

// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "myRectangle";

// Assign the rectangle a name by


// registering it with the page, so that
// it can be targeted by storyboard
// animations.
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;
myStackPanel.Children.Add(myRectangle);

//
// Create an animation and a storyboard to animate the
// rectangle.
//
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(5000));
myDoubleAnimation.AutoReverse = true;

// Create the storyboard.


myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new
PropertyPath(Rectangle.OpacityProperty));

//
// Create some buttons to control the storyboard
// and a panel to contain them.
//
StackPanel buttonPanel = new StackPanel();
buttonPanel.Orientation = Orientation.Horizontal;
Button beginButton = new Button();
beginButton.Content = "Begin";
beginButton.Click += new RoutedEventHandler(beginButton_Clicked);
buttonPanel.Children.Add(beginButton);
Button pauseButton = new Button();
pauseButton.Content = "Pause";
pauseButton.Click += new RoutedEventHandler(pauseButton_Clicked);
buttonPanel.Children.Add(pauseButton);
Button resumeButton = new Button();
resumeButton.Content = "Resume";
resumeButton.Click += new RoutedEventHandler(resumeButton_Clicked);
buttonPanel.Children.Add(resumeButton);
Button skipToFillButton = new Button();
skipToFillButton.Content = "Skip to Fill";
skipToFillButton.Click += new RoutedEventHandler(skipToFillButton_Clicked);
buttonPanel.Children.Add(skipToFillButton);
Button setSpeedRatioButton = new Button();
setSpeedRatioButton.Content = "Triple Speed";
setSpeedRatioButton.Click += new RoutedEventHandler(setSpeedRatioButton_Clicked);
buttonPanel.Children.Add(setSpeedRatioButton);
Button stopButton = new Button();
stopButton.Content = "Stop";
stopButton.Click += new RoutedEventHandler(stopButton_Clicked);
buttonPanel.Children.Add(stopButton);
myStackPanel.Children.Add(buttonPanel);
this.Content = myStackPanel;
}

// Begins the storyboard.


private void beginButton_Clicked(object sender, RoutedEventArgs args)
{
// Specifying "true" as the second Begin parameter
// makes this storyboard controllable.
myStoryboard.Begin(this, true);
}

// Pauses the storyboard.


private void pauseButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Pause(this);
}

// Resumes the storyboard.


private void resumeButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Resume(this);
}

// Advances the storyboard to its fill period.


private void skipToFillButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.SkipToFill(this);
}

// Updates the storyboard's speed.


private void setSpeedRatioButton_Clicked(object sender, RoutedEventArgs args)
{
// Makes the storyboard progress three times as fast as normal.
myStoryboard.SetSpeedRatio(this, 3);
}

// Stops the storyboard.


private void stopButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Stop(this);
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media
Imports System.Windows.Media.Animation

Namespace SDKSample

Public Class ControllableStoryboardExample


Inherits Page
Private myStoryboard As Storyboard

Public Sub New()

' Create a name scope for the page.

NameScope.SetNameScope(Me, New NameScope())

Me.WindowTitle = "Controllable Storyboard Example"


Dim myStackPanel As New StackPanel()
myStackPanel.Margin = New Thickness(10)

' Create a rectangle.


Dim myRectangle As New Rectangle()
myRectangle.Name = "myRectangle"

' Assign the rectangle a name by


' registering it with the page, so that
' it can be targeted by storyboard
' animations.
Me.RegisterName(myRectangle.Name, myRectangle)
myRectangle.Width = 100
myRectangle.Height = 100
myRectangle.Fill = Brushes.Blue
myStackPanel.Children.Add(myRectangle)

'
' Create an animation and a storyboard to animate the
' rectangle.
'
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 1.0
myDoubleAnimation.To = 0.0
myDoubleAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(5000))
myDoubleAnimation.AutoReverse = True

' Create the storyboard.


myStoryboard = New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name)
Storyboard.SetTargetProperty(myDoubleAnimation, New
PropertyPath(Rectangle.OpacityProperty))

'
' Create some buttons to control the storyboard
' and a panel to contain them.
'
Dim buttonPanel As New StackPanel()
buttonPanel.Orientation = Orientation.Horizontal
Dim beginButton As New Button()
beginButton.Content = "Begin"
AddHandler beginButton.Click, AddressOf beginButton_Clicked
buttonPanel.Children.Add(beginButton)
Dim pauseButton As New Button()
pauseButton.Content = "Pause"
AddHandler pauseButton.Click, AddressOf pauseButton_Clicked
buttonPanel.Children.Add(pauseButton)
Dim resumeButton As New Button()
resumeButton.Content = "Resume"
AddHandler resumeButton.Click, AddressOf resumeButton_Clicked
buttonPanel.Children.Add(resumeButton)
Dim skipToFillButton As New Button()
skipToFillButton.Content = "Skip to Fill"
AddHandler skipToFillButton.Click, AddressOf skipToFillButton_Clicked
buttonPanel.Children.Add(skipToFillButton)
Dim setSpeedRatioButton As New Button()
setSpeedRatioButton.Content = "Triple Speed"
AddHandler setSpeedRatioButton.Click, AddressOf setSpeedRatioButton_Clicked
buttonPanel.Children.Add(setSpeedRatioButton)
Dim stopButton As New Button()
stopButton.Content = "Stop"
AddHandler stopButton.Click, AddressOf stopButton_Clicked
buttonPanel.Children.Add(stopButton)
myStackPanel.Children.Add(buttonPanel)
Me.Content = myStackPanel

End Sub

' Begins the storyboard.


Private Sub beginButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
' Specifying "true" as the second Begin parameter
' makes this storyboard controllable.
myStoryboard.Begin(Me, True)

End Sub

' Pauses the storyboard.


Private Sub pauseButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myStoryboard.Pause(Me)

End Sub

' Resumes the storyboard.


Private Sub resumeButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myStoryboard.Resume(Me)

End Sub

' Advances the storyboard to its fill period.


Private Sub skipToFillButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myStoryboard.SkipToFill(Me)

End Sub

' Updates the storyboard's speed.


Private Sub setSpeedRatioButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
' Makes the storyboard progress three times as fast as normal.
myStoryboard.SetSpeedRatio(Me, 3)

End Sub

' Stops the storyboard.


Private Sub stopButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myStoryboard.Stop(Me)

End Sub

End Class

End Namespace

Animar en un estilo
Puede utilizar Storyboard objetos para definir animaciones en un Style. Animar con un Storyboard en un
Style es similar a usar un Storyboard en otro lugar, con las tres excepciones siguientes:
No se especifica un TargetName; el Storyboard siempre tiene como destino el elemento al que se
aplica el Style. Para tener como destino objetos Freezable, debe usar el establecimiento indirecto de
destinos. Para obtener más información sobre el establecimiento indirecto de destinos, consulte la
sección de destinatarios indirectos .
No se puede especificar un SourceName para un EventTrigger o un Trigger.
No se pueden usar referencias de recursos dinámicos o expresiones de enlace de datos para
establecer Storyboard o valores de propiedad de animación. Esto se debe a que todo lo que hay
dentro de un Style debe ser seguro para subprocesos y el sistema de control de tiempo debe
FreezeStoryboard objetos para que sean seguros para subprocesos. No se puede inmovilizar un
Storyboard si éste o sus escalas de tiempo secundarias contienen referencias de recursos dinámicos
o expresiones de enlace de datos. Para obtener más información sobre la inmovilización y otras
características de Freezable, consulte la información general sobre objetos Freezable.
En XAML, no se pueden declarar controladores de eventos para eventos de Storyboard o de
animación.
Para ver un ejemplo en el que se muestra cómo definir un guion gráfico en un estilo, vea el ejemplo de
animar en un estilo .

Animar en un ControlTemplate
Puede utilizar Storyboard objetos para definir animaciones en un ControlTemplate. Animar con un
Storyboard en un ControlTemplate es similar a usar un Storyboard en otro lugar, con las dos excepciones
siguientes:
El TargetName solo puede hacer referencia a objetos secundarios de la ControlTemplate. Si no se
especifica TargetName, la animación tiene como destino el elemento al que se aplica el
ControlTemplate.
El SourceName para un EventTrigger o un Trigger solo puede hacer referencia a objetos secundarios
del ControlTemplate.
No se pueden usar referencias de recursos dinámicos o expresiones de enlace de datos para
establecer Storyboard o valores de propiedad de animación. Esto se debe a que todo lo que hay
dentro de un ControlTemplate debe ser seguro para subprocesos y el sistema de control de tiempo
debe FreezeStoryboard objetos para que sean seguros para subprocesos. No se puede inmovilizar
un Storyboard si éste o sus escalas de tiempo secundarias contienen referencias de recursos
dinámicos o expresiones de enlace de datos. Para obtener más información sobre la inmovilización y
otras características de Freezable, consulte la información general sobre objetos Freezable.
En XAML, no se pueden declarar controladores de eventos para eventos de Storyboard o de
animación.
Para ver un ejemplo en el que se muestra cómo definir un guion gráfico en un ControlTemplate, vea el
ejemplo de animar en un ControlTemplate .

Animar cuando cambia el valor de una propiedad


En estilos y plantillas de control, puede utilizar objetos Trigger para iniciar un guión gráfico cuando cambia
una propiedad. Para obtener ejemplos, vea desencadenar una animación cuando cambia el valor de una
propiedad y animar en un ControlTemplate.
Las animaciones aplicadas por los objetos de Trigger de propiedades se comportan de manera más
compleja que EventTrigger animaciones o animaciones que se inician con los métodos de Storyboard. "Se
colocan" con animaciones definidas por otros objetos Trigger, pero se componen con EventTrigger y
animaciones desencadenadas por métodos.

Vea también
Información general sobre animaciones
Información general sobre técnicas de animación de propiedades
Información general sobre objetos Freezable
Información general sobre comportamientos de
control de tiempo
08/01/2020 • 15 minutes to read • Edit Online

En este tema se describen los comportamientos de control de tiempo de las animaciones y otros objetos de
Timeline.

Requisitos previos
Para entender este tema, debe estar familiarizado con las características de animación básicas. Para obtener más
información, vea información general sobre animaciones.

Tipos de objetos Timeline


Timeline representa un segmento de tiempo. Proporciona propiedades que permiten especificar la longitud de
ese segmento, cuándo debe iniciarse, cuántas veces se repetirá o la velocidad a la que progresará el tiempo en
ese segmento, entre otras.
Las clases que heredan de la clase Timeline proporcionan funcionalidades adicionales, como reproducción de
animaciones y multimedia. WPF proporciona los siguientes tipos de Timeline.

TIPOS DE OBJETOS TIMELINE DESCRIPCIÓN

AnimationTimeline Clase base abstracta para los objetos Timeline que generan
valores de salida para animar propiedades.

MediaTimeline Genera la salida de un archivo multimedia.

ParallelTimeline Tipo de TimelineGroup que agrupa y controla los objetos


Timeline secundarios.

Storyboard Tipo de ParallelTimeline que proporciona información de


destino para los objetos de la escala de tiempo que contiene.

Timeline Clase base abstracta que define los comportamientos de


control de tiempo.

TimelineGroup Clase abstracta para los objetos Timeline que pueden


contener otros objetos Timeline.

Propiedades que controlan la longitud de un objeto Timeline


Una Timeline representa un segmento de tiempo, y la longitud de una escala de tiempo se puede describir de
maneras diferentes. La siguiente tabla define varios términos para describir la longitud de un objeto Timeline.

TÉRMINO DESCRIPCIÓN PROPIEDADES


TÉRMINO DESCRIPCIÓN PROPIEDADES

Duración simple El intervalo de Duration


tiempo que un
objeto Timeline
tarda en realizar
una iteración de
avance.

Una repetición La cantidad de Duration,


tiempo que tarda AutoReverse
una escala de
tiempo en
reproducirse una
vez y, si la
propiedad
AutoReverse es
true, se
reproduce una
vez hacia atrás.

Período activo Período de Duration,


tiempo que tarda AutoReverse,
una escala de RepeatBehavior
tiempo en
completar todas
las repeticiones
especificadas por
su propiedad
RepeatBehavior.

Propiedad Duration
Como se ha mencionado previamente, un objeto Timeline representa un segmento de tiempo. La longitud de ese
segmento viene determinada por la Durationde la escala de tiempo. Cuando un objeto Timeline llega al final de
su duración, detiene la reproducción. Si el objeto Timeline tiene objetos Timeline secundarios, su reproducción
también se detiene. En el caso de una animación, el Duration especifica cuánto tiempo tarda la animación en
pasar de su valor inicial a su valor final. La duración de una escala de tiempo se denomina a veces su duración
simple, para distinguir entre la duración de una iteración única y la duración total de tiempo que se reproduce la
animación, incluidas las repeticiones. Puede especificar una duración mediante un valor de hora finito o los
valores especiales Automatic o Forever. La duración de una animación debe resolverse en un valor TimeSpan,
por lo que puede realizar la transición entre valores.
En el ejemplo siguiente se muestra un DoubleAnimation con un Duration de cinco segundos.

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5" />

Las escalas de tiempo de contenedor, como Storyboard y ParallelTimeline, tienen una duración predeterminada
de Automatic, lo que significa que finalizan automáticamente cuando su último elemento secundario deja de
reproducirse. En el ejemplo siguiente se muestra un Storyboard cuyo Duration se resuelve en cinco segundos, el
tiempo que se tardan todos sus objetos DoubleAnimation secundarios en completarse.
<Storyboard >

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5" />

<DoubleAnimation
Storyboard.TargetName="MyOtherRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:3" />

</Storyboard>

Al establecer el Duration de una escala de tiempo de contenedor en un valor de TimeSpan, puede forzar que se
reproduzca más o menos que sus objetos Timeline secundarios se reproduzcan. Si establece el Duration en un
valor menor que la longitud de los objetos Timeline secundarios de la escala de tiempo del contenedor, los
objetos secundarios Timeline dejarán de reproducirse cuando lo hace la escala de tiempo del contenedor. En el
ejemplo siguiente se establece el Duration de la Storyboard de los ejemplos anteriores en tres segundos. Como
resultado, la primera DoubleAnimation detiene el progreso transcurridos tres segundos, cuando ha animado el
ancho del rectángulo de destino hasta 60.

<Storyboard Duration="0:0:3">

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5" />

<DoubleAnimation
Storyboard.TargetName="MyOtherRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:3" />

</Storyboard>

Propiedad RepeatBehavior
La propiedad RepeatBehavior de una Timeline controla el número de veces que se repite su duración simple.
Con la propiedad RepeatBehavior, puede especificar el número de veces que se reproduce la escala de tiempo
(una iteración Count) o la duración total de tiempo que debe reproducirse (un Durationde repetición). En
cualquier caso, la animación pasa por tantas repeticiones de principio a fin como sean necesarias para completar
el recuento o la duración solicitados. De forma predeterminada, las escalas de tiempo tienen un recuento de
iteraciones de 1.0 , lo que significa que se reproducen una vez y no se repiten.
En el ejemplo siguiente se usa la propiedad RepeatBehavior para hacer que un DoubleAnimation se reproduzca
durante el doble de su duración simple mediante la especificación de un recuento de iteraciones.

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5"
RepeatBehavior="2x" />

En el ejemplo siguiente se usa la propiedad RepeatBehavior para hacer que el DoubleAnimation se reproduzca
durante la mitad de su duración simple.

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5"
RepeatBehavior="0.5x" />
Si establece la propiedad RepeatBehavior de una Timeline en Forever, la Timeline se repite hasta que se detiene
interactivamente o por el sistema de control de tiempo. En el ejemplo siguiente se usa la propiedad
RepeatBehavior para hacer que el DoubleAnimation se reproduzca indefinidamente.

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5"
RepeatBehavior="Forever" />

Para ver un ejemplo adicional, consulte repetir una animación.


Propiedad AutoReverse
La propiedad AutoReverse especifica si un Timeline se reproducirá hacia atrás al final de cada iteración de
avance. En el ejemplo siguiente se establece en la propiedad AutoReverse de una DoubleAnimation en true ;
como resultado, anima desde cero hasta 100 y, a continuación, de 100 a cero. Se reproduce durante un total de
10 segundos.

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5"
AutoReverse="True" />

Cuando se usa un valor Count para especificar el RepeatBehavior de un Timeline y la propiedad AutoReverse de
ese Timeline es true , una repetición única consta de una iteración de avance seguida de una iteración hacia
atrás. En el ejemplo siguiente se establece el RepeatBehavior del DoubleAnimation del ejemplo anterior en una
Count de dos. Como resultado, el DoubleAnimation se reproduce durante 20 segundos: avance durante cinco
segundos, hacia atrás durante cinco segundos, hacia adelante durante cinco segundos y, a continuación, hacia
atrás durante cinco segundos.

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5"
RepeatBehavior="2"
AutoReverse="True" />

Si una escala de tiempo de contenedor tiene objetos secundarios Timeline, se revierten cuando la escala de
tiempo del contenedor. Para obtener más ejemplos, vea especificar si una escala de tiempo se invierte
automáticamente.

Propiedad BeginTime
La propiedad BeginTime permite especificar Cuándo se inicia una escala de tiempo. El momento de inicio de un
objeto Timeline es relativo a su objeto Timeline primario. Un tiempo de inicio de cero segundos significa que el
objeto Timeline se inicia tan pronto lo hace su primario; cualquier otro valor crea un desfase entre el momento
en que se empieza a reproducir el Timeline primario y el momento en que lo hace el secundario. Por ejemplo, un
tiempo de inicio de dos segundos significa que el objeto Timeline empieza a reproducirse cuando su elemento
primario ha alcanzado un tiempo de dos segundos. De forma predeterminada, todos los objetos Timeline tienen
un tiempo de inicio de cero segundos. También puede establecer la hora de inicio de una escala de tiempo en
null , lo que impide que se inicie la escala de tiempo. En WPF, especifique NULL mediante la extensión de
marcado x:null.
Tenga en cuenta que la hora de inicio no se aplica cada vez que una escala de tiempo se repite debido a su
configuración RepeatBehavior. Si fuera a crear una animación con una BeginTime de 10 segundos y un
RepeatBehavior de Forever, se produciría un retraso de 10 segundos antes de que se reproduzca la animación
por primera vez, pero no para cada repetición sucesiva. Sin embargo, si se reinicia o repite el objeto Timeline
primario, se produciría el retraso de 10 segundos.
La propiedad BeginTime es útil para escalonar las escalas de tiempo. En el ejemplo siguiente se crea un
Storyboard que tiene dos objetos DoubleAnimation secundarios. La primera animación tiene una Duration de
cinco segundos y la segunda tiene una Duration de 3 segundos. En el ejemplo se establece el BeginTime del
segundo DoubleAnimation en 5 segundos, de modo que comience a reproducirse después de que finalice la
primera DoubleAnimation.

<Storyboard>

<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5"
BeginTime="0:0:0" />

<DoubleAnimation
Storyboard.TargetName="MyOtherRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:3"
BeginTime="0:0:5" />

</Storyboard>

Propiedad FillBehavior
Cuando un Timeline alcanza el final de su duración total activa, la propiedad FillBehavior especifica si se detiene
o contiene su último valor. Una animación con una FillBehavior de HoldEnd "contiene" su valor de salida: la
propiedad que se anima conserva el último valor de la animación. Un valor de Stop hace que la animación deje
de afectar a su propiedad de destino una vez finalizada.
En el ejemplo siguiente se crea un Storyboard que tiene dos objetos DoubleAnimation secundarios. Ambos
objetos DoubleAnimation animan el Width de una Rectangle de 0 a 100. Los elementos Rectangle tienen valores
de Width no animados de 500 [píxeles independientes del dispositivo].
La propiedad FillBehavior del primer DoubleAnimation está establecida en HoldEnd, el valor
predeterminado. Como resultado, el ancho del rectángulo permanece en 100 una vez finalizada la
DoubleAnimation.
La propiedad FillBehavior del segundo DoubleAnimation está establecida en Stop. Como resultado, el
Width del segundo Rectangle vuelve a 500 después de que finalice la DoubleAnimation.
<Rectangle Name="MyRectangle"
Width="500" Height="100"
Opacity="1" Fill="Red">
</Rectangle>

<Rectangle Name="MyOtherRectangle"
Width="500" Height="100"
Opacity="1" Fill="Orange">
</Rectangle>

<Button Content="Start FillBehavior Example">


<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5"
FillBehavior="HoldEnd" />
<DoubleAnimation
Storyboard.TargetName="MyOtherRectangle" Storyboard.TargetProperty="Width"
From="0" To="100" Duration="0:0:5"
FillBehavior="Stop" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

Propiedades que controlan la velocidad de un objeto Timeline


La clase Timeline proporciona tres propiedades para especificar su velocidad:
SpeedRatio: especifica la velocidad, en relación con su elemento primario, a la que progresa el tiempo
para un Timeline. Los valores mayores que uno aumentan la velocidad del Timeline y sus objetos Timeline
secundarios; los valores entre cero y uno lo ralentizan. Un valor de uno indica que Timeline progresa a la
misma velocidad que su elemento primario. La SpeedRatio configuración de una escala de tiempo de
contenedor afecta también a todos los objetos Timeline secundarios.
AccelerationRatio: especifica el porcentaje de la Duration de una escala de tiempo que se dedica a acelerar.
Para obtener un ejemplo, consulte Cómo: acelerar o reducir la velocidad de una animación.
DecelerationRatio: especifica el porcentaje de la Duration de una escala de tiempo empleada en
deceleración. Para obtener un ejemplo, consulte Cómo: acelerar o reducir la velocidad de una animación.

Vea también
Información general sobre animaciones
Información general sobre sistemas de control de tiempo y animación
Información general sobre eventos de control de tiempo
Temas "Cómo..."
Ejemplo del comportamiento del control de tiempo de la animación
Información general sobre eventos de control de
tiempo
23/10/2019 • 8 minutes to read • Edit Online

Este tema describe cómo utilizar los cinco eventos de control de tiempo disponible en Timeline y Clock objetos.

Requisitos previos
Para entender este tema, debe entender cómo crear y utilizar animaciones. Para empezar a trabajar con
animación, vea el información general sobre animaciones.
Hay varias maneras de animar propiedades en WPF:
Usar objetos storyboard (marcado y código): Puede usar Storyboard objetos para organizar y distribuir
animaciones a uno o varios objetos. Para obtener un ejemplo, vea animar una propiedad utilizando un
guión gráfico.
Mediante animaciones locales (solo código): Puede aplicar AnimationTimeline objetos directamente a
las propiedades que animan. Para obtener un ejemplo, vea Animar una propiedad sin utilizar un guión
gráfico.
Mediante relojes (solo código): Puede administrar la creación de un reloj explícitamente y distribuir los
relojes de animación personalmente. Para obtener un ejemplo, vea animar una propiedad usando un objeto
AnimationClock.
Dado que puede usar en la marcación y código, utilizan los ejemplos en esta introducción Storyboard objetos. Sin
embargo, los conceptos descritos pueden aplicarse a los otros métodos existentes para animar propiedades.
¿Qué es un reloj?
Un objeto Timeline, por sí mismo, realmente no hace nada más que describir un segmento de tiempo. Es la escala
de tiempo Clock objeto que hace el trabajo real: mantiene el estado de tiempo de ejecución relacionados con el
control de tiempo para la escala de tiempo. En la mayoría de los casos, como cuando se utilizan objetos
Storyboard, se crea automáticamente un reloj para dichos objetos. También puede crear un Clock explícitamente
mediante el CreateClock método. Para obtener más información acerca de Clock objetos, vea el Animation and
Timing System Overview.

¿Por qué usar eventos?


Con excepción de una operación, (operación de búsqueda alineada con el último ciclo), todas las operaciones de
control de tiempo interactivas son asincrónicas. No hay ninguna manera de saber exactamente cuándo se
ejecutarán. Esto puede ser un problema cuando hay otro código que depende de la operación de control de
tiempo. Suponga que desea detener un objeto Timeline que anima un rectángulo. Una vez detenido el objeto
Timeline, desea cambiar el color del rectángulo.

myStoryboard.Stop(myRectangle);

// This statement might execute


// before the storyboard has stopped.
myRectangle.Fill = Brushes.Blue;
myStoryboard.Stop(myRectangle)

' This statement might execute


' before the storyboard has stopped.
myRectangle.Fill = Brushes.Blue

En el ejemplo anterior, la segunda línea de código podría ejecutarse antes de que se detenga el objeto Storyboard.
Esto se debe a que la detención es una operación asincrónica. Al indicar a un objeto Timeline o Clock que se
detenga, se crea una "solicitud de detención" que no se procesa hasta el siguiente ciclo del motor de control de
tiempo.
Para ejecutar comandos una vez finalizada la reproducción de un objeto Timeline, utilice eventos de control de
tiempo. En el ejemplo siguiente, se utiliza un controlador de eventos para cambiar el color de un rectángulo al
detenerse el objeto Storyboard.

// Register for the CurrentStateInvalidated timing event.


myStoryboard.CurrentStateInvalidated += new EventHandler(myStoryboard_CurrentStateInvalidated);

' Register for the CurrentStateInvalidated timing event.


AddHandler myStoryboard.CurrentStateInvalidated, AddressOf myStoryboard_CurrentStateInvalidated

// Change the rectangle's color after the storyboard stops.


void myStoryboard_CurrentStateInvalidated(object sender, EventArgs e)
{
Clock myStoryboardClock = (Clock)sender;
if (myStoryboardClock.CurrentState == ClockState.Stopped)
{
myRectangle.Fill = Brushes.Blue;
}
}

' Change the rectangle's color after the storyboard stops.


Private Sub myStoryboard_CurrentStateInvalidated(ByVal sender As Object, ByVal e As EventArgs)
Dim myStoryboardClock As Clock = CType(sender, Clock)
If myStoryboardClock.CurrentState = ClockState.Stopped Then
myRectangle.Fill = Brushes.Blue
End If
End Sub

Para obtener un ejemplo más completo, vea los cambios de recibir notificación cuando un reloj de estado.

Eventos públicos
El Timeline y Clock clases proporcionan cinco eventos de temporización. En la tabla siguiente se enumeran estos
eventos y las condiciones que los desencadenan.

OPERACIÓN INTERACTIVA
EVENTO DESENCADENANTE OTROS DESENCADENADORES

Completed Omitir hasta completar El reloj se completa.

CurrentGlobalSpeedInvalidated Pausar, reanudar, buscar, establecer la El reloj se invierte, acelera, inicia o


relación de velocidad, omitir hasta detiene.
completar, detener
OPERACIÓN INTERACTIVA
EVENTO DESENCADENANTE OTROS DESENCADENADORES

CurrentStateInvalidated Comenzar, omitir hasta completar, El reloj se inicia, detiene o completa.


detener

CurrentTimeInvalidated Comenzar, buscar, omitir hasta El reloj progresa.


completar, detener

RemoveRequested Quitar

Ciclos y consolidación de eventos


Al animar objetos en WPF, es el motor de tiempo que administra las animaciones. El motor de control de tiempo
realiza el seguimiento de la progresión del tiempo y calcula el estado de cada animación. Realiza muchas de estos
pasos de evaluación en un segundo. Estos pasos de evaluación se denominan "ciclos".
Aunque los ciclos se producen con frecuencia, pueden ocurrir muchas cosas entre ellos. Por ejemplo, un objeto
Timeline se podría detener, iniciar y detener de nuevo, en cuyo caso su estado actual habría cambiado tres veces.
En teoría, el evento puede generarse varias veces en un único ciclo; sin embargo, el motor de control de tiempo
consolida los eventos, para que cada evento se pueda generar como máximo una vez por ciclo.

Registro para eventos


Hay dos formas de registrarse para eventos de control de tiempo: con el objeto Timeline o con un objeto Clock
creado a partir del objeto Timeline. Registrarse para un evento directamente con un reloj es bastante sencillo,
aunque solo puede realizarse desde el código. Puede registrarse para eventos con un objeto Timeline tanto en
marcado como en código. En la sección siguiente se describe cómo registrarse para eventos de reloj con un
objeto Timeline.

Registrarse para eventos de reloj con un objeto Timeline


Aunque una escala de tiempo Completed, CurrentGlobalSpeedInvalidated, CurrentStateInvalidated,
CurrentTimeInvalidated, y RemoveRequested parecen estar asociados con la escala de tiempo, registrar para
estos eventos realmente asocia un controlador de eventos con eventos el Clock creado para la escala de tiempo.
Cuando se registra para el Completed eventos en una escala de tiempo, por ejemplo, en realidad está indicando al
sistema que se registre para el Completed eventos de cada reloj que se crea para la escala de tiempo. En el
código, debe registrar para este evento antes de la Clock se crea para esta escala de tiempo; en caso contrario, no
recibirá la notificación. Esto sucede automáticamente en XAML; el analizador se registra automáticamente para el
evento antes de la Clock se crea.

Vea también
Información general sobre sistemas de control de tiempo y animación
Información general sobre animaciones
Información general sobre comportamientos de control de tiempo
Temas "Cómo..." de animación y control de tiempo
23/10/2019 • 2 minutes to read • Edit Online

Los temas siguientes muestran cómo usar el Windows Presentation Foundation (WPF ) sistema de animación y
temporización en sus aplicaciones.

En esta sección
Aumentar o reducir la velocidad de una animación
Acumular valores de animaciones durante la repetición de ciclos
Agregar un valor de salida de animación a un valor inicial de animación
Animar una propiedad utilizando un guión gráfico
Animar una propiedad sin utilizar un guión gráfico
Animar en un ControlTemplate
Animar en un estilo
Animar la opacidad de un elemento o pincel
Cambiar la velocidad de un reloj sin cambiar la velocidad de su escala de tiempo
Controlar un guión gráfico una vez iniciado usando métodos interactivos
Controlar una animación mediante From, To y By
Definir un ámbito de nombres
Recibir una notificación cuando cambia el estado de un reloj
Repetir una animación
Buscar un guión gráfico
Buscar guiones gráficos de forma sincrónica
Definir una duración para una animación
Establecer una propiedad después de animarla con un guión gráfico
Simplificar las animaciones mediante escalas de tiempo secundarias
Especificar HandoffBehavior entre animaciones de guión gráfico
Especificar el comportamiento de relleno de una escala de tiempo que ha llegado al final de su período de
actividad
Especificar si una escala de tiempo se invierte automáticamente
Activar una animación al cambiar el valor de una propiedad
Utilizar desencadenadores de eventos para controlar un guión gráfico después de su inicio

Referencia
Timeline
Storyboard
BeginStoryboard
Clock
System.Windows.Media.Animation

Secciones relacionadas
Gráficos y multimedia
Procedimiento Aumentar o reducir la velocidad de
una animación
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo realizar una animación acelerar y reducir la velocidad con el tiempo. En el
ejemplo siguiente, se animan los rectángulos varios por animaciones con diferentes AccelerationRatio y
DecelerationRatio configuración.

Ejemplo
<!-- This example shows how to use the AccelerationRatio and
DecelerationRatio properties of timelines
to make animations speed up or slow down as they progress. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SampleControls="SampleControls"
WindowTitle="Acceleration and Deceleration Example">
<StackPanel Margin="20">

<Rectangle Name="nonAcceleratedOrDeceleratedRectangle" Fill="#9933FF"


Width="10" Height="20" HorizontalAlignment="Left" />

<Rectangle Name="acceleratedRectangle" Fill="#3333FF"


Width="10" Height="20" HorizontalAlignment="Left" />

<Rectangle Name="deceleratedRectangle" Fill="#33FF66"


Width="10" Height="20" HorizontalAlignment="Left" />

<Rectangle Name="acceleratedAndDeceleratedRectangle" Fill="#CCFF33"


Width="10" Height="20" HorizontalAlignment="Left" />

<!-- Create a button to start the animations. -->


<Button Margin="0,30,0,0" HorizontalAlignment="Left"
Content="Start Animations">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>

<!-- Creates an animation without acceleration or deceleration for comparison. -->


<DoubleAnimation
Storyboard.TargetName="nonAcceleratedOrDeceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
Duration="0:0:10" From="20" To="400" />

<!-- Creates an animation that accelerates through 40% of its duration. -->
<DoubleAnimation
Storyboard.TargetName="acceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
AccelerationRatio="0.4" Duration="0:0:10" From="20" To="400" />

<!-- Creates an animation that decelerates through 60% of its duration. -->
<DoubleAnimation
Storyboard.TargetName="deceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
DecelerationRatio="0.6" Duration="0:0:10" From="20" To="400" />

<!-- Creates an animation that accelerates through 40% of its duration and
decelerates through the 60% of its duration. -->
<DoubleAnimation
Storyboard.TargetName="acceleratedAndDeceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
AccelerationRatio="0.4" DecelerationRatio="0.6" Duration="0:0:10" From="20" To="400" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>

Se ha omitido el código en este ejemplo. Para el código completo, vea el comportamiento de tiempo de
animación (C#) o comportamiento de tiempo de animación (Visual Basic) .
Procedimiento Acumular valores de animaciones
durante la repetición de ciclos
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el IsCumulative propiedad que se va a acumular valores de animaciones
entre ciclos que se repiten.

Ejemplo
Use el IsCumulative propiedad que se va a acumular los valores base de una animación entre ciclos que se repiten.
Por ejemplo, si establece una animación se repita 9 veces (RepeatBehavior = "9 x") y establezca la propiedad que
se va a animar entre 10 y 15 (From = 10 a = 15), la propiedad se anima de 10 a 15 durante el primer ciclo de 15 a
20 durante el ciclo de segundo , de 20 a 25 durante el ciclo de terceros y así sucesivamente. Por lo tanto, cada ciclo
de animación usa el valor final de la animación desde el ciclo de animación anterior como su valor base.
Puede usar el IsCumulative propiedad con animaciones más básicas y la mayoría de las animaciones de
fotogramas clave. Para obtener más información, consulte información general sobre animaciones y información
general sobre animaciones de fotogramas clave.
El ejemplo siguiente muestra este comportamiento al animar el ancho de cuatro rectángulos. El ejemplo:
Anima el primer rectángulo con DoubleAnimation y establece el IsCumulative propiedad true .
Anima el segundo rectángulo con DoubleAnimation y establece el IsCumulative propiedad en el valor
predeterminado de false .
Anima el tercer rectángulo con DoubleAnimationUsingKeyFrames y establece el IsCumulative propiedad
true .

Anima el último rectángulo con DoubleAnimationUsingKeyFrames y establece el IsCumulative propiedad


false .

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="20" >

<!-- This rectangle is animated with DoubleAnimation and IsCumulative set to "True". -->
<Rectangle Name="withIsCumulative"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- This rectangle is animated with DoubleAnimation and IsCumulative set to "False". -->
<Rectangle Name="withoutIsCumulative"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- This rectangle is animated with DoubleAnimationUsingKeyFrames and IsCumulative set to "True". -->
<Rectangle Name="withIsCumulativeUsingKeyFrames"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- This rectangle is animated with DoubleAnimationUsingKeyFrames and IsCumulative set to "False". -->
<Rectangle Name="withoutIsCumulativeUsingKeyFrames"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- Create a button to restart the animations. -->


<Button Margin="0,30,0,0" HorizontalAlignment="Left">
Restart Animations
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>

<!-- DoubleAnimation with IsCumulative set to "True". Because IsCumulative is set to "True",
the base values of the animation will accumulate over repeat cycles. In this example, the
first iteration will be from 100 to 200, the second will be from 200 to 300, the third from
300 to 400, etc. -->
<DoubleAnimation
Storyboard.TargetName="withIsCumulative"
Storyboard.TargetProperty="Width"
RepeatBehavior="4x"
AutoReverse="True"
IsCumulative="True"
Duration="0:0:3" From="100" To="200" />

<!-- DoubleAnimation with IsCumulative set to "False". The starting value 100 pixels and repeat
cycles do not build on earlier ones. -->
<DoubleAnimation
Storyboard.TargetName="withoutIsCumulative"
Storyboard.TargetProperty="Width"
RepeatBehavior="4x"
AutoReverse="True"
IsCumulative="False"
Duration="0:0:3" From="100" To="200" />

<!-- DoubleAnimationUsingKeyFrames with IsCumulative set to "True". Similar to the


DoubleAnimation
above, the base value of each cycle builds on the last one. Note that the output value
is the total output value from all the key frames for a total output of 100 pixels. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="withIsCumulativeUsingKeyFrames"
Storyboard.TargetProperty="Width"
RepeatBehavior="4x"
AutoReverse="True"
IsCumulative="True" >
<DoubleAnimationUsingKeyFrames.KeyFrames>
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:0" />
<LinearDoubleKeyFrame Value="130" KeyTime="0:0:1" />
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="200" KeyTime="0:0:3" />
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>

<!-- DoubleAnimationUsingKeyFrames with IsCumulative set to "False". The base value of each
cycle
does not build on the last one. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="withoutIsCumulativeUsingKeyFrames"
Storyboard.TargetProperty="Width"
RepeatBehavior="4x"
AutoReverse="True"
IsCumulative="False" >
<DoubleAnimationUsingKeyFrames.KeyFrames>
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:0" />
<LinearDoubleKeyFrame Value="130" KeyTime="0:0:1" />
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="200" KeyTime="0:0:3" />
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>

</Storyboard>

</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>
Vea también
Agregar un valor de salida de animación a un valor inicial de animación
Repetir una animación
Información general sobre animaciones
Información general sobre animaciones de fotogramas clave
Temas "Cómo..."
Procedimiento Agregar un valor de salida de
animación a un valor inicial de animación
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo agregar un valor de salida de animación a un valor inicial de animación.

Ejemplo
El IsAdditive propiedad especifica si desea que el valor de salida de una animación que se agrega al valor inicial
(valor base) de una propiedad animada. Puede usar el IsAdditive propiedad con animaciones más básicas y la
mayoría de las animaciones de fotogramas clave. Para obtener más información, consulte información general
sobre animaciones y información general sobre animaciones de fotogramas clave.
El ejemplo siguiente muestra el efecto de usar el DoubleAnimation.IsAdditive propiedad con DoubleAnimation y
el uso de la DoubleAnimationUsingKeyFrames.IsAdditive propiedad con DoubleAnimationUsingKeyFrames.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="20" >

<!-- This rectangle is animated with DoubleAnimation and IsAdditive set to "True". -->
<Rectangle Name="withIsAdditive"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- This rectangle is animated with DoubleAnimation and IsAdditive set to "False". -->
<Rectangle Name="withoutIsAdditive"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- This rectangle is animated with DoubleAnimationUsingKeyFrames and IsAdditive set to "True". -->
<Rectangle Name="withIsAdditiveUsingKeyFrames"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- This rectangle is animated with DoubleAnimationUsingKeyFrames and IsAdditive set to "False". -->
<Rectangle Name="withoutIsAdditiveUsingKeyFrames"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- Create a button to restart the animations. -->


<Button Margin="0,30,0,0" HorizontalAlignment="Left">
Restart Animations
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>

<!-- DoubleAnimation with IsAdditive set to "True". Because IsAdditive is set to "True" the
actual starting value of the animation is equal to the sum of the default starting
value of 100 (From="100)and the animation output value of 100 (From="100" To="200")
Therefore
the animation begins at 200 pixels. Notice that each time the button is clicked and the
animation is initiated, the animation starting value builds upon the preceeding ending
value. -->
<DoubleAnimation
Storyboard.TargetName="withIsAdditive"
Storyboard.TargetProperty="Width"
Duration="0:0:3" From="100" To="200" IsAdditive="True" />

<!-- DoubleAnimation with IsAdditive set to "False". The starting value is the default starting
value of 100 pixels and subsequent animations do not build on earlier ones. -->
<DoubleAnimation
<DoubleAnimation
Storyboard.TargetName="withoutIsAdditive"
Storyboard.TargetProperty="Width"
Duration="0:0:3" From="100" To="200" IsAdditive="False" />

<!-- DoubleAnimationUsingKeyFrames with IsAdditive set to "True". Similar to the DoubleAnimation


above, this animation adds its output value to its starting value. Note that the output
value
is the total output value from all the key frames for a total output of 100 pixels. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="withIsAdditiveUsingKeyFrames"
Storyboard.TargetProperty="Width"
IsAdditive="True" >
<DoubleAnimationUsingKeyFrames.KeyFrames>
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:0" />
<LinearDoubleKeyFrame Value="130" KeyTime="0:0:1" />
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="200" KeyTime="0:0:3" />
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>

<!-- DoubleAnimationUsingKeyFrames with IsAdditive set to "False". The starting value is the
default starting value of 100 pixels and subsequent animations do not build on earlier
ones. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="withoutIsAdditiveUsingKeyFrames"
Storyboard.TargetProperty="Width"
IsAdditive="False" >
<DoubleAnimationUsingKeyFrames.KeyFrames>
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:0" />
<LinearDoubleKeyFrame Value="130" KeyTime="0:0:1" />
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="200" KeyTime="0:0:3" />
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>

</Storyboard>

</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>

Vea también
Acumular valores de animaciones durante la repetición de ciclos
Información general sobre animaciones
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de temporización y animación
Cómo: Animar una propiedad utilizando un guión
gráfico
08/01/2020 • 8 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un Storyboard para animar propiedades. Para animar una propiedad
mediante un Storyboard, cree una animación para cada propiedad que desee animar y cree también un
Storyboard que contenga las animaciones.
El tipo de propiedad determina el tipo de animación que se va a utilizar. Por ejemplo, para animar una
propiedad que toma Double valores, utilice un DoubleAnimation. Las propiedades adjuntas TargetName y
TargetProperty especifican el objeto y la propiedad a la que se aplica la animación.
Para iniciar un guion gráfico en Lenguaje XAML (Extensible Application Markup Language), use una acción de
BeginStoryboard y una EventTrigger. El EventTrigger inicia la acción de BeginStoryboard cuando se produce el
evento especificado por su propiedad RoutedEvent. La acción BeginStoryboard inicia el Storyboard.
En el ejemplo siguiente se utiliza Storyboard objetos para animar dos controles Button. Para que el primer
cambio de botón tenga el mismo tamaño, se anima su Width. Para hacer que el segundo botón cambie de color,
se usa la propiedad Color del SolidColorBrush para establecer la Background del botón que está animado.

Ejemplo
<!-- StoryboardExample.xaml
Uses storyboards to animate properties. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Animate Properties with Storyboards">

<Border Background="White">
<StackPanel Margin="30" HorizontalAlignment="Left" MinWidth="500">

<TextBlock>Storyboard Animation Example</TextBlock>

<!-- The width of this button is animated. -->


<Button Name="myWidthAnimatedButton"
Height="30" Width="200" HorizontalAlignment="Left">
A Button
<Button.Triggers>

<!-- Animates the width of the first button


from 200 to 300. -->
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="myWidthAnimatedButton"
Storyboard.TargetProperty="Width"
From="200" To="300" Duration="0:0:3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

<!-- The color of the brush used to paint this button is animated. -->
<Button Height="30" Width="200"
HorizontalAlignment="Left">Another Button
<Button.Background>
<SolidColorBrush x:Name="myAnimatedBrush" Color="Blue" />
</Button.Background>
<Button.Triggers>

<!-- Animates the color of the brush used to paint


the second button from red to blue . -->
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="myAnimatedBrush"
Storyboard.TargetProperty="Color"
From="Red" To="Blue" Duration="0:0:7" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Border>
</Page>

NOTE
Aunque las animaciones pueden tener como destino un objeto FrameworkElement, como un Control o Panel, y un objeto
Freezable, como un Brush o Transform, solo los elementos del marco tienen una propiedad Name. Para asignar un
nombre a un elemento inmovilizable para que pueda servir de destino para una animación, utilice x:Name (Directiva),
como se muestra en el ejemplo anterior.
Si utiliza código, debe crear un NameScope para un FrameworkElement y registrar los nombres de los objetos
que desea animar con ese FrameworkElement. Para iniciar las animaciones en el código, utilice una acción de
BeginStoryboard con un EventTrigger. Opcionalmente, puede usar un controlador de eventos y el método
Begin de Storyboard. En el siguiente ejemplo, se muestra cómo utilizar el método Begin.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.AnimatingWithStoryboards
{

// Uses a storyboard to animate the properties


// of two buttons.
public class StoryboardExample : Page
{

public StoryboardExample()
{
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());

this.WindowTitle = "Animate Properties using Storyboards";


StackPanel myStackPanel = new StackPanel();
myStackPanel.MinWidth = 500;
myStackPanel.Margin = new Thickness(30);
myStackPanel.HorizontalAlignment = HorizontalAlignment.Left;
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Storyboard Animation Example";
myStackPanel.Children.Add(myTextBlock);

//
// Create and animate the first button.
//

// Create a button.
Button myWidthAnimatedButton = new Button();
myWidthAnimatedButton.Height = 30;
myWidthAnimatedButton.Width = 200;
myWidthAnimatedButton.HorizontalAlignment = HorizontalAlignment.Left;
myWidthAnimatedButton.Content = "A Button";

// Set the Name of the button so that it can be referred


// to in the storyboard that's created later.
// The ID doesn't have to match the variable name;
// it can be any unique identifier.
myWidthAnimatedButton.Name = "myWidthAnimatedButton";

// Register the name with the page to which the button belongs.
this.RegisterName(myWidthAnimatedButton.Name, myWidthAnimatedButton);

// Create a DoubleAnimation to animate the width of the button.


DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 200;
myDoubleAnimation.To = 300;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(3000));

// Configure the animation to target the button's Width property.


Storyboard.SetTargetName(myDoubleAnimation, myWidthAnimatedButton.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Button.WidthProperty));

// Create a storyboard to contain the animation.


Storyboard myWidthAnimatedButtonStoryboard = new Storyboard();
myWidthAnimatedButtonStoryboard.Children.Add(myDoubleAnimation);
// Animate the button width when it's clicked.
myWidthAnimatedButton.Click += delegate(object sender, RoutedEventArgs args)
{
myWidthAnimatedButtonStoryboard.Begin(myWidthAnimatedButton);
};

myStackPanel.Children.Add(myWidthAnimatedButton);

//
// Create and animate the second button.
//

// Create a second button.


Button myColorAnimatedButton = new Button();
myColorAnimatedButton.Height = 30;
myColorAnimatedButton.Width = 200;
myColorAnimatedButton.HorizontalAlignment = HorizontalAlignment.Left;
myColorAnimatedButton.Content = "Another Button";

// Create a SolidColorBrush to paint the button's background.


SolidColorBrush myBackgroundBrush = new SolidColorBrush();
myBackgroundBrush.Color = Colors.Blue;

// Because a Brush isn't a FrameworkElement, it doesn't


// have a Name property to set. Instead, you just
// register a name for the SolidColorBrush with
// the page where it's used.
this.RegisterName("myAnimatedBrush", myBackgroundBrush);

// Use the brush to paint the background of the button.


myColorAnimatedButton.Background = myBackgroundBrush;

// Create a ColorAnimation to animate the button's background.


ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Red;
myColorAnimation.To = Colors.Blue;
myColorAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(7000));

// Configure the animation to target the brush's Color property.


Storyboard.SetTargetName(myColorAnimation, "myAnimatedBrush");
Storyboard.SetTargetProperty(myColorAnimation, new
PropertyPath(SolidColorBrush.ColorProperty));

// Create a storyboard to contain the animation.


Storyboard myColorAnimatedButtonStoryboard = new Storyboard();
myColorAnimatedButtonStoryboard.Children.Add(myColorAnimation);

// Animate the button background color when it's clicked.


myColorAnimatedButton.Click += delegate(object sender, RoutedEventArgs args)
{
myColorAnimatedButtonStoryboard.Begin(myColorAnimatedButton);
};

myStackPanel.Children.Add(myColorAnimatedButton);
this.Content = myStackPanel;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation

Namespace SDKSample
' Uses a storyboard to animate the properties
' of two buttons.
Public Class StoryboardExample
Inherits Page

Private Dim WithEvents myWidthAnimatedButton As Button


Private Dim WithEvents myColorAnimatedButton As Button
Private Dim myWidthAnimatedButtonStoryboard As Storyboard
Private Dim myColorAnimatedButtonStoryboard As Storyboard

Public Sub New()


' Create a name scope for the page.
NameScope.SetNameScope(Me, New NameScope())

Me.WindowTitle = "Animate Properties using Storyboards"


Dim myStackPanel As New StackPanel()
myStackPanel.MinWidth = 500
myStackPanel.Margin = New Thickness(30)
myStackPanel.HorizontalAlignment = HorizontalAlignment.Left
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Storyboard Animation Example"
myStackPanel.Children.Add(myTextBlock)

'
' Create and animate the first button.
'

' Create a button.


myWidthAnimatedButton = New Button()
myWidthAnimatedButton.Height = 30
myWidthAnimatedButton.Width = 200
myWidthAnimatedButton.HorizontalAlignment = HorizontalAlignment.Left
myWidthAnimatedButton.Content = "A Button"

' Set the Name of the button so that it can be referred


' to in the storyboard that's created later.
' The ID doesn't have to match the variable name;
' it can be any unique identifier.
myWidthAnimatedButton.Name = "myWidthAnimatedButton"

' Register the name with the page to which the button belongs.
Me.RegisterName(myWidthAnimatedButton.Name, myWidthAnimatedButton)

' Create a DoubleAnimation to animate the width of the button.


Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 200
myDoubleAnimation.To = 300
myDoubleAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(3000))

' Configure the animation to target the button's Width property.


Storyboard.SetTargetName(myDoubleAnimation, myWidthAnimatedButton.Name)
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Button.WidthProperty))

' Create a storyboard to contain the animation.


myWidthAnimatedButtonStoryboard = New Storyboard()
myWidthAnimatedButtonStoryboard.Children.Add(myDoubleAnimation)

myStackPanel.Children.Add(myWidthAnimatedButton)

'
' Create and animate the second button.
'

' Create a second button.


myColorAnimatedButton = New Button()
myColorAnimatedButton.Height = 30
myColorAnimatedButton.Width = 200
myColorAnimatedButton.Width = 200
myColorAnimatedButton.HorizontalAlignment = HorizontalAlignment.Left
myColorAnimatedButton.Content = "Another Button"

' Create a SolidColorBrush to paint the button's background.


Dim myBackgroundBrush As New SolidColorBrush()
myBackgroundBrush.Color = Colors.Blue

' Because a Brush isn't a FrameworkElement, it doesn't


' have a Name property to set. Instead, you just
' register a name for the SolidColorBrush with
' the page where it's used.
Me.RegisterName("myAnimatedBrush", myBackgroundBrush)

' Use the brush to paint the background of the button.


myColorAnimatedButton.Background = myBackgroundBrush

' Create a ColorAnimation to animate the button's background.


Dim myColorAnimation As New ColorAnimation()
myColorAnimation.From = Colors.Red
myColorAnimation.To = Colors.Blue
myColorAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(7000))

' Configure the animation to target the brush's Color property.


Storyboard.SetTargetName(myColorAnimation, "myAnimatedBrush")
Storyboard.SetTargetProperty(myColorAnimation, New PropertyPath(SolidColorBrush.ColorProperty))

' Create a storyboard to contain the animation.


myColorAnimatedButtonStoryboard = New Storyboard()
myColorAnimatedButtonStoryboard.Children.Add(myColorAnimation)

myStackPanel.Children.Add(myColorAnimatedButton)
Me.Content = myStackPanel

End Sub

' Start the animation when the button is clicked.


Private Sub myWidthAnimatedButton_Loaded(ByVal sender as object, ByVal args as RoutedEventArgs)
Handles myWidthAnimatedButton.Click

myWidthAnimatedButtonStoryboard.Begin(myWidthAnimatedButton)

End Sub

' Start the animation when the button is clicked.


Private Sub myColorAnimatedButton_Loaded(ByVal sender as object, ByVal args as RoutedEventArgs)
Handles myColorAnimatedButton.Click

myColorAnimatedButtonStoryboard.Begin(myColorAnimatedButton)

End Sub

End Class
End Namespace

Para más información sobre animaciones y guiones gráficos, vea Información general sobre animaciones.
Si utiliza código, no se limita a utilizar objetos de Storyboard para animar propiedades. Para más información y
ejemplos, vea Animar una propiedad sin utilizar un guión gráfico y Animar una propiedad usando un objeto
AnimationClock.
Procedimiento Animar una propiedad sin usar un
guión gráfico
23/10/2019 • 4 minutes to read • Edit Online

En este ejemplo se muestra una manera de aplicar una animación a una propiedad sin Storyboardusar.

NOTE
Esta funcionalidad no está disponible en Lenguaje XAML (Extensible Application Markup Language). Para información
sobre cómo animar una propiedad en XAML, vea Animar una propiedad utilizando un guión gráfico.

Para aplicar una animación local a una propiedad, use el BeginAnimation método. Este método toma dos
parámetros: un DependencyProperty que especifica la propiedad que se va a animar y la animación que se va a
aplicar a esa propiedad.

Ejemplo
En el ejemplo siguiente se muestra cómo animar el ancho y el color Buttonde fondo de un.

/*

This sample demonstrates how to apply non-storyboard animations to a property.


To animate in markup, you must use storyboards.

*/

using namespace System;


using namespace System::Windows;
using namespace System::Windows::Navigation;
using namespace System::Windows::Media;
using namespace System::Windows::Media::Animation;
using namespace System::Windows::Shapes;
using namespace System::Windows::Controls;

namespace Microsoft {
namespace Samples {
namespace Animation {
namespace LocalAnimations {
// Create the demonstration.
public ref class LocalAnimationExample : Page {

public:
LocalAnimationExample ()
{
WindowTitle = "Local Animation Example";
StackPanel^ myStackPanel = gcnew StackPanel();
myStackPanel->Margin = Thickness(20);

// Create and set the Button.


Button^ aButton = gcnew Button();
aButton->Content = "A Button";

// Animate the Button's Width.


DoubleAnimation^ myDoubleAnimation = gcnew DoubleAnimation();
myDoubleAnimation->From = 75;
myDoubleAnimation->To = 300;
myDoubleAnimation->To = 300;
myDoubleAnimation->Duration = Duration(TimeSpan::FromSeconds(5));
myDoubleAnimation->AutoReverse = true;
myDoubleAnimation->RepeatBehavior = RepeatBehavior::Forever;

// Apply the animation to the button's Width property.


aButton->BeginAnimation(Button::WidthProperty, myDoubleAnimation);

// Create and animate a Brush to set the button's Background.


SolidColorBrush^ myBrush = gcnew SolidColorBrush();
myBrush->Color = Colors::Blue;

ColorAnimation^ myColorAnimation = gcnew ColorAnimation();


myColorAnimation->From = Colors::Blue;
myColorAnimation->To = Colors::Red;
myColorAnimation->Duration = Duration(TimeSpan::FromMilliseconds(7000));
myColorAnimation->AutoReverse = true;
myColorAnimation->RepeatBehavior = RepeatBehavior::Forever;

// Apply the animation to the brush's Color property.


myBrush->BeginAnimation(SolidColorBrush::ColorProperty, myColorAnimation);
aButton->Background = myBrush;

// Add the Button to the panel.


myStackPanel->Children->Add(aButton);
this->Content = myStackPanel;
};
};
}
}
}
}
/*

This sample demonstrates how to apply non-storyboard animations to a property.


To animate in markup, you must use storyboards.

*/

using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls;

namespace Microsoft.Samples.Animation.LocalAnimations
{

// Create the demonstration.


public class LocalAnimationExample : Page
{

public LocalAnimationExample()
{

WindowTitle = "Local Animation Example";


StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(20);

// Create and set the Button.


Button aButton = new Button();
aButton.Content = "A Button";

// Animate the Button's Width.


DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 75;
myDoubleAnimation.To = 300;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Apply the animation to the button's Width property.


aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation);

// Create and animate a Brush to set the button's Background.


SolidColorBrush myBrush = new SolidColorBrush();
myBrush.Color = Colors.Blue;

ColorAnimation myColorAnimation = new ColorAnimation();


myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.Red;
myColorAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(7000));
myColorAnimation.AutoReverse = true;
myColorAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Apply the animation to the brush's Color property.


myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation);
aButton.Background = myBrush;

// Add the Button to the panel.


myStackPanel.Children.Add(aButton);
this.Content = myStackPanel;
}
}
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''This sample demonstrates how to apply non-storyboard animations to a property.
'''To animate in markup, you must use storyboards.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Imports System.Windows
Imports System.Windows.Navigation
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Imports System.Windows.Controls

Namespace Microsoft.Samples.Animation.LocalAnimations

' Create the demonstration.


Public Class LocalAnimationExample
Inherits Page

Public Sub New()

WindowTitle = "Animate Property Example"


Dim myStackPanel As New StackPanel()
myStackPanel.Margin = New Thickness(20)

' Create and set the Button.


Dim aButton As New Button()
aButton.Content = "A Button"

' Animate the Button's Width.


Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 75
myDoubleAnimation.To = 300
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))
myDoubleAnimation.AutoReverse = True
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever

' Apply the animation to the button's Width property.


aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation)

' Create and animate a Brush to set the button's Background.


Dim myBrush As New SolidColorBrush()
myBrush.Color = Colors.Blue

Dim myColorAnimation As New ColorAnimation()


myColorAnimation.From = Colors.Blue
myColorAnimation.To = Colors.Red
myColorAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(7000))
myColorAnimation.AutoReverse = True
myColorAnimation.RepeatBehavior = RepeatBehavior.Forever

' Apply the animation to the brush's Color property.


myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation)
aButton.Background = myBrush

' Add the Button to the panel.


myStackPanel.Children.Add(aButton)
Me.Content = myStackPanel
End Sub
End Class
End Namespace

Existe una variedad de clases de animación System.Windows.Media.Animation en el espacio de nombres para


animar diferentes tipos de propiedades. Para más información sobre la animación de propiedades, vea
Información general sobre animaciones. Para más información sobre las propiedades de dependencia (el tipo
de propiedades que se muestran en estos ejemplos) y sus características, vea Información general sobre las
propiedades de dependencia.
Hay otras maneras de animar sin utilizar Storyboard objetos; para obtener más información, vea información
general sobre técnicas de animación de propiedades.

Vea también
AnimationTimeline
BeginAnimation
System.Windows.Media.Animation
Storyboard
Información general sobre técnicas de animación de propiedades
Información general sobre animaciones
Procedimiento Animar en un ControlTemplate
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar Storyboard, EventTrigger, y Trigger objetos que se va a animar dentro de
un ControlTemplate.

Ejemplo
<!-- ControlStoryboardExample.xaml
Uses storyboards to animate properties with a ControlTemplate. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Animate Properties with Storyboards">

<Page.Resources>
<ControlTemplate x:Key="MyControlTemplate"
TargetType="{x:Type ContentControl}">
<Border
Margin="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<Border Name="innerBorder" Padding="10">
<Border.Background>
<SolidColorBrush x:Name="innerBorderBackgroundBrush"
Color="White" />
</Border.Background>
<Grid Name="contentPanel">
<Grid.Background>
<SolidColorBrush x:Name="contentPanelBrush" Color="White" />
</Grid.Background>
<ContentPresenter
Margin="10"
Content="{TemplateBinding Content}"
TextBlock.Foreground="{TemplateBinding Foreground}" />
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>

<!-- Event Trigger Example -->


<EventTrigger RoutedEvent="Border.MouseEnter" SourceName="innerBorder">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="innerBorderBackgroundBrush"
Storyboard.TargetProperty="Color"
From="White" To="#CCCCFF"
Duration="0:0:3" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>

<!-- Property Trigger Example -->


<Trigger Property="IsMouseOver" Value="True" SourceName="contentPanel">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="contentPanelBrush"
Storyboard.TargetProperty="Color"
To="Purple" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="contentPanelBrush"
Storyboard.TargetProperty="Color"
To="White" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

</Page.Resources>

<Border Background="White">
<StackPanel Margin="30" HorizontalAlignment="Left" MinWidth="500">

<ContentControl Template="{StaticResource MyControlTemplate}"


Content="Hello, World" />

</StackPanel>
</Border>
</Page>

Para obtener más información acerca de cómo animar las propiedades con guiones gráficos, vea Storyboards
Overview.

Vea también
ControlTemplate
Cómo animar en un estilo
27/01/2020 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo animar las propiedades dentro de un estilo. Al animar dentro de un estilo, solo
se puede destinar directamente el elemento de marco para el que se define el estilo. Para establecer como destino
un objeto Freezable, debe "punto inactivo" desde una propiedad del elemento con estilo.
En el ejemplo siguiente, se definen varias animaciones dentro de un estilo y se aplican a un Button. Cuando el
usuario mueve el mouse sobre el botón, lo atenúa de forma repetida y viceversa. Cuando el usuario mueve el
mouse fuera del botón, se vuelve completamente opaco. Al hacer clic en el botón, el color de fondo cambia de
naranja a blanco y viceversa. Dado que el SolidColorBrush que se usa para pintar el botón no se puede destinar
directamente, se obtiene acceso a él mediante el uso de puntos hacia abajo desde la propiedad Background del
botón.

Ejemplo
<!-- StyleStoryboardsExample.xaml
This example shows how to create storyboards in a style. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Storyboards in Styles Example" Background="White">
<Page.Resources>

<!-- Defines a Button style. -->


<Style TargetType="{x:Type Button}" x:Key="MyButtonStyle">
<Setter Property="Button.Background">
<Setter.Value>
<SolidColorBrush Color="Orange" />
</Setter.Value>
</Setter>
<Style.Triggers>

<!-- Animates the button's opacity on mouse over. -->


<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Button.Opacity)"
From="1.0" To="0.5" Duration="0:0:0.5" AutoReverse="True"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>

<!-- Returns the button's opacity to 1 when the mouse leaves. -->
<EventTrigger RoutedEvent="Button.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Button.Opacity)"
To="1" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<!-- Changes the button's color when clicked.
Notice that the animation can't target the
SolidColorBrush used to paint the button's background
directly. The brush must be accessed through the button's
Background property. -->
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)"
From="Orange" To="White" Duration="0:0:0.1" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Page.Resources>

<StackPanel Margin="20">
<Button Style="{StaticResource MyButtonStyle}">Click Me</Button>
</StackPanel>
</Page>

Tenga en cuenta que al animar dentro de un estilo, es posible tener como destino objetos que no existen. Por
ejemplo, suponga que el estilo usa un SolidColorBrush para establecer la propiedad de fondo de un botón, pero
en algún momento se invalida el estilo y el fondo del botón se establece con un LinearGradientBrush. Al intentar
animar el SolidColorBrush no se producirá una excepción; la animación simplemente producirá un error de forma
silenciosa.
Para obtener más información sobre la sintaxis de destino de guion gráfico, vea la información general sobre los
guiones gráficos. Para obtener más información acerca de la animación, consulte información general sobre
animaciones. Para obtener más información sobre los estilos, vea el estilo y la plantilla.
Procedimiento Animar la opacidad de un elemento o
pincel
23/10/2019 • 3 minutes to read • Edit Online

Para hacer que un elemento de marco se desvanezca y salga de la vista, puede Opacity animar su propiedad o
puede Opacity animar la Brush propiedad de (o pinceles) que se usa para pintarla. Animar la opacidad del
elemento hace que esta y sus elementos secundarios se muestreen y salgan de la vista, pero la animación del
pincel que se usa para pintar el elemento le permite ser más selectivo sobre qué parte del elemento se atenúa. Por
ejemplo, podría animar la opacidad de un pincel que se usa para pintar el fondo de un botón. Esto haría que el
fondo del botón se desvanecera y fuera de la vista, mientras que el texto se quedaba totalmente opaco.

NOTE
Animar Brushdeun proporciona ventajas de rendimiento sobre la Opacity animación de la propiedad de un elemento. Opacity

En el ejemplo siguiente, se animan dos botones para que se atenúen y desaparecen de la vista. La opacidad de la
primera Button se anima desde 1.0 hasta 0.0 Duration cinco segundos. El segundo botón también se anima,
pero la opacidad del SolidColorBrush que se usa para pintar Background su está animada en lugar de la opacidad
del botón completo. Cuando se ejecuta el ejemplo, el primer botón se atenúa completamente y se aleja de la vista,
mientras que solo el fondo del segundo botón se atenúa y sale de la vista. Su texto y borde permanecen totalmente
opacos.

Ejemplo
<!-- OpacityAnimationExample.xaml
This example shows how to animate the opacity of objects,
making them fade in and out of view. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Opacity Animation Example" Background="White">
<StackPanel Margin="20">

<!-- Clicking this button animates its opacity. -->


<Button Name="opacityAnimatedButton">
A Button
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="opacityAnimatedButton"
Storyboard.TargetProperty="(Button.Opacity)"
From="1" To="0" Duration="0:0:5" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

<!-- Clicking this button animates the opacity of the brush


used to paint its background. -->
<Button>
A Button
<Button.Background>
<SolidColorBrush x:Name="MyAnimatedBrush" Color="Orange" />
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyAnimatedBrush"
Storyboard.TargetProperty="(Brush.Opacity)"
From="1" To="0" Duration="0:0:5" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>

El código se ha omitido en este ejemplo. En el ejemplo completo también se muestra cómo animar la opacidad
Color de un LinearGradientBrushdentro de un. Para obtener el ejemplo completo, vea el ejemplo de animación de
la opacidad de un elemento.
Procedimiento Cambiar la velocidad de un reloj sin
cambiar la velocidad de su escala de tiempo
23/10/2019 • 4 minutes to read • Edit Online

Un ClockController del objeto SpeedRatio propiedad le permite cambiar la velocidad de un Clock sin alterar el
SpeedRatio el reloj de Timeline. En el ejemplo siguiente, un ClockController se usa para modificar de forma
interactiva el SpeedRatio de un reloj. El CurrentGlobalSpeedInvalidated eventos y el reloj CurrentGlobalSpeed
propiedad se usa para mostrar la velocidad del reloj actual global cada vez que su interactivo SpeedRatio se
cambia.

Ejemplo
/*
This example shows how to interactively control
the speed of a clock
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{
public class ClockControllerSpeedRatioExample : Page
{

private AnimationClock myControllableClock;


private Button speedRatioButton;
private TextBox speedRatioSettingTextBox;
private double doubleParseResult = 1;
private TextBlock currentGlobalSpeedTextBlock;

public ClockControllerSpeedRatioExample()
{
StackPanel mainPanel = new StackPanel();

// Create a rectangle to animate.


Rectangle animatedRectangle = new Rectangle();
animatedRectangle.Width = 100;
animatedRectangle.Height = 100;
animatedRectangle.Fill = Brushes.Orange;
mainPanel.Children.Add(animatedRectangle);
// Create a DoubleAnimation to
// animate its width.
DoubleAnimation widthAnimation =
new DoubleAnimation(
100,
500,
new Duration(TimeSpan.FromSeconds(5)));
//widthAnimation.RepeatBehavior = RepeatBehavior.Forever;
widthAnimation.AutoReverse = true;
widthAnimation.SpeedRatio = 0.5;

// Create a clock from the animation.


myControllableClock = widthAnimation.CreateClock();

// Apply the clock to the rectangle's Width property.


// Apply the clock to the rectangle's Width property.
animatedRectangle.ApplyAnimationClock(
Rectangle.WidthProperty, myControllableClock);

//
// Create some controls the enable the user to
// interactively control the SpeedRatio of the clock.
//
StackPanel speedRatioDetailsPanel = new StackPanel();
speedRatioDetailsPanel.Margin = new Thickness(0,20,0,20);
speedRatioDetailsPanel.Orientation = Orientation.Horizontal;
Label speedRatioLabel = new Label();
speedRatioLabel.Content = "Speed Ratio:";
speedRatioDetailsPanel.Children.Add(speedRatioLabel);

// Create a text box so that the user can


// specify the amount by which to seek.
speedRatioSettingTextBox = new TextBox();
speedRatioSettingTextBox.Text =
myControllableClock.Controller.SpeedRatio.ToString();
speedRatioSettingTextBox.VerticalAlignment = VerticalAlignment.Top;
speedRatioSettingTextBox.TextChanged +=
new TextChangedEventHandler(seekAmountTextBox_TextChanged);
speedRatioDetailsPanel.Children.Add(speedRatioSettingTextBox);

// Create a button to apply SpeedRatio changes.


speedRatioButton = new Button();
speedRatioButton.Content = "Apply Speed Ratio";
speedRatioButton.Click += new RoutedEventHandler(speedRatioButton_Clicked);
speedRatioDetailsPanel.Children.Add(speedRatioButton);

mainPanel.Children.Add(speedRatioDetailsPanel);

// Display the clock's global speed information.


Label myLabel = new Label();
myLabel.Content = "CurrentGlobalSpeed ";
mainPanel.Children.Add(myLabel);
currentGlobalSpeedTextBlock = new TextBlock();
currentGlobalSpeedTextBlock.Text =
myControllableClock.CurrentGlobalSpeed.ToString();
mainPanel.Children.Add(currentGlobalSpeedTextBlock);

// List for speed changes.


myControllableClock.CurrentGlobalSpeedInvalidated +=
new EventHandler(myControllableClock_currentGlobalSpeedInvalidated);

this.Content = mainPanel;
}

// Updates the clock's SpeedRatio.


private void speedRatioButton_Clicked(object sender, RoutedEventArgs e)
{

// This statement triggers a CurrentGlobalSpeedInvalidated


// event.
myControllableClock.Controller.SpeedRatio = doubleParseResult;
}

// Displays the current global speed.


private void myControllableClock_currentGlobalSpeedInvalidated(object sender, EventArgs e)
{

currentGlobalSpeedTextBlock.Text =
myControllableClock.CurrentGlobalSpeed.ToString()
+ " Event triggered at: "
+ DateTime.Now.ToString();
}

// Verifies that speedRatioSettingTextBox has valid text content.


// If it doesn't, the speedRatioButton is disabled.
// If it doesn't, the speedRatioButton is disabled.
private void seekAmountTextBox_TextChanged(object sender, TextChangedEventArgs e)
{

TextBox theTextBox = (TextBox)e.Source;


if (theTextBox.Text == null || theTextBox.Text.Length < 1
|| Double.TryParse(theTextBox.Text,
System.Globalization.NumberStyles.Any,
null, out doubleParseResult) == false)
speedRatioButton.IsEnabled = false;
else
speedRatioButton.IsEnabled = true;
}
}
}

'
' This example shows how to interactively control
' the speed of a clock
'

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation

Namespace Microsoft.Samples.Animation.TimingBehaviors
Public Class ClockControllerSpeedRatioExample
Inherits Page

Private ReadOnly myControllableClock As AnimationClock


Private ReadOnly speedRatioButton As Button
Private ReadOnly speedRatioSettingTextBox As TextBox
Private doubleParseResult As Double = 1
Private ReadOnly currentGlobalSpeedTextBlock As TextBlock

Public Sub New()


Dim mainPanel As New StackPanel()

' Create a rectangle to animate.


Dim animatedRectangle As New Rectangle With {
.Width = 100,
.Height = 100,
.Fill = Brushes.Orange
}
mainPanel.Children.Add(animatedRectangle)
' Create a DoubleAnimation to
' animate its width.
'widthAnimation.RepeatBehavior = RepeatBehavior.Forever
Dim widthAnimation As New DoubleAnimation(100, 500, New Duration(TimeSpan.FromSeconds(5))) With {
.AutoReverse = True,
.SpeedRatio = 0.5
}

' Create a clock from the animation.


myControllableClock = widthAnimation.CreateClock()

' Apply the clock to the rectangle's Width property.


animatedRectangle.ApplyAnimationClock(Rectangle.WidthProperty, myControllableClock)

'
' Create some controls the enable the user to
' interactively control the SpeedRatio of the clock.
'
Dim speedRatioDetailsPanel As New StackPanel With {
.Margin = New Thickness(0, 20, 0, 20),
.Orientation = Orientation.Horizontal
.Orientation = Orientation.Horizontal
}
Dim speedRatioLabel As New Label With {
.Content = "Speed Ratio:"
}
speedRatioDetailsPanel.Children.Add(speedRatioLabel)

' Create a text box so that the user can


' specify the amount by which to seek.
speedRatioSettingTextBox = New TextBox With {
.Text = myControllableClock.Controller.SpeedRatio.ToString(),
.VerticalAlignment = VerticalAlignment.Top
}
AddHandler speedRatioSettingTextBox.TextChanged, AddressOf seekAmountTextBox_TextChanged
speedRatioDetailsPanel.Children.Add(speedRatioSettingTextBox)

' Create a button to apply SpeedRatio changes.


speedRatioButton = New Button With {
.Content = "Apply Speed Ratio"
}
AddHandler speedRatioButton.Click, AddressOf speedRatioButton_Clicked
speedRatioDetailsPanel.Children.Add(speedRatioButton)

mainPanel.Children.Add(speedRatioDetailsPanel)

' Display the clock's global speed information.


Dim myLabel As New Label With {
.Content = "CurrentGlobalSpeed "
}
mainPanel.Children.Add(myLabel)
currentGlobalSpeedTextBlock = New TextBlock With {
.Text = myControllableClock.CurrentGlobalSpeed.ToString()
}
mainPanel.Children.Add(currentGlobalSpeedTextBlock)

' List for speed changes.


AddHandler myControllableClock.CurrentGlobalSpeedInvalidated, AddressOf
myControllableClock_currentGlobalSpeedInvalidated

Content = mainPanel
End Sub

' Updates the clock's SpeedRatio.


Private Sub speedRatioButton_Clicked(sender As Object, e As RoutedEventArgs)

' This statement triggers a CurrentGlobalSpeedInvalidated


' event.
myControllableClock.Controller.SpeedRatio = doubleParseResult

End Sub

' Displays the current global speed.


Private Sub myControllableClock_currentGlobalSpeedInvalidated(sender As Object, e As EventArgs)

currentGlobalSpeedTextBlock.Text = myControllableClock.CurrentGlobalSpeed.ToString() & " Event


triggered at: " & Date.Now.ToString()

End Sub

' Verifies that speedRatioSettingTextBox has valid text content.


' If it doesn't, the speedRatioButton is disabled.
Private Sub seekAmountTextBox_TextChanged(sender As Object, e As TextChangedEventArgs)

Dim theTextBox As TextBox = CType(e.Source, TextBox)


If theTextBox.Text Is Nothing OrElse theTextBox.Text.Length < 1 OrElse
Double.TryParse(theTextBox.Text, System.Globalization.NumberStyles.Any, Nothing, doubleParseResult) = False
Then
speedRatioButton.IsEnabled = False
Else
Else
speedRatioButton.IsEnabled = True
End If

End Sub

End Class
End Namespace
Procedimiento Controlar un guión gráfico después
de su inicio
23/10/2019 • 6 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el código para Storyboard controlar una después de haberse iniciado. Para
controlar un guion gráfico XAMLen, Trigger use TriggerAction los objetos y; para obtener un ejemplo, vea usar
desencadenadores de eventos para controlar un guión gráfico después de su inicio.
Para iniciar un guion gráfico, use su Begin método, que distribuye las animaciones del guión gráfico a las
propiedades que animan e inicia el guión gráfico.
Para que se pueda controlar un guión gráfico, use Begin el método y especifique true como el segundo
parámetro. Después, puede usar los métodos interactivos del guión gráfico para pausar, reanudar, buscar, detener,
acelerar o ralentizar el guión gráfico, o bien avanzar hasta su período de relleno. A continuación se muestra una
lista de los métodos interactivos del guión gráfico:
Pause: Pausa el guion gráfico.
Resume: Reanuda un guion gráfico en pausa.
SetSpeedRatio: Establece la velocidad interactiva del guión gráfico.
Seek: Busca el guion gráfico en la ubicación especificada.
SeekAlignedToLastTick: Busca el guión gráfico en la ubicación especificada. A diferencia del Seek método,
esta operación se procesa antes del siguiente paso.
SkipToFill: Hace avanzar el guión gráfico hasta su período de relleno, si tiene uno.
Stop: Detiene el guion gráfico.
En el ejemplo siguiente, se usan varios métodos de guion gráfico para controlar interactivamente un guión gráfico.

NOTE
Para ver un ejemplo de cómo controlar un guión gráfico mediante desencadenadores con, consulte XAML usar
desencadenadores de eventos para controlar un guión gráfico después de su inicio.

Ejemplo
/*
This example shows how to control
a storyboard after it has started.

*/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{
public partial class ControlStoryboardExample : Page
{

private Storyboard myStoryboard;

public ControlStoryboardExample()
{

// Create a name scope for the page.


NameScope.SetNameScope(this, new NameScope());

this.WindowTitle = "Controlling a Storyboard";


this.Background = Brushes.White;

StackPanel myStackPanel = new StackPanel();


myStackPanel.Margin = new Thickness(20);

// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 100;
myRectangle.Height = 20;
myRectangle.Margin = new Thickness(12,0,0,5);
myRectangle.Fill = new SolidColorBrush(Color.FromArgb(170, 51, 51, 255));
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myStackPanel.Children.Add(myRectangle);

// Assign the rectangle a name by


// registering it with the page, so that
// it can be targeted by storyboard
// animations.
this.RegisterName("myRectangle", myRectangle);

//
// Create an animation and a storyboard to animate the
// rectangle.
//
DoubleAnimation myDoubleAnimation =
new DoubleAnimation(100, 500, new Duration(TimeSpan.FromSeconds(5)));
Storyboard.SetTargetName(myDoubleAnimation, "myRectangle");
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.WidthProperty));
myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);

//
// Create some buttons to control the storyboard
// and a panel to contain them.
//
StackPanel buttonPanel = new StackPanel();
buttonPanel.Orientation = Orientation.Horizontal;
Button beginButton = new Button();
beginButton.Content = "Begin";
beginButton.Click += new RoutedEventHandler(beginButton_Clicked);
buttonPanel.Children.Add(beginButton);
Button pauseButton = new Button();
pauseButton.Content = "Pause";
pauseButton.Click +=new RoutedEventHandler(pauseButton_Clicked);
buttonPanel.Children.Add(pauseButton);
Button resumeButton = new Button();
resumeButton.Content = "Resume";
resumeButton.Click +=new RoutedEventHandler(resumeButton_Clicked);
buttonPanel.Children.Add(resumeButton);
Button skipToFillButton = new Button();
skipToFillButton.Content = "Skip to Fill";
skipToFillButton.Click +=new RoutedEventHandler(skipToFillButton_Clicked);
buttonPanel.Children.Add(skipToFillButton);
Button setSpeedRatioButton = new Button();
setSpeedRatioButton.Content = "Triple Speed";
setSpeedRatioButton.Click +=new RoutedEventHandler(setSpeedRatioButton_Clicked);
buttonPanel.Children.Add(setSpeedRatioButton);
buttonPanel.Children.Add(setSpeedRatioButton);
Button stopButton = new Button();
stopButton.Content = "Stop";
stopButton.Click +=new RoutedEventHandler(stopButton_Clicked);
buttonPanel.Children.Add(stopButton);
myStackPanel.Children.Add(buttonPanel);
this.Content = myStackPanel;
}

// Begins the storyboard.


private void beginButton_Clicked(object sender, RoutedEventArgs args)
{
// Specifying "true" as the second Begin parameter
// makes this storyboard controllable.
myStoryboard.Begin(this, true);
}

// Pauses the storyboard.


private void pauseButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Pause(this);
}

// Resumes the storyboard.


private void resumeButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Resume(this);
}

// Advances the storyboard to its fill period.


private void skipToFillButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.SkipToFill(this);
}

// Updates the storyboard's speed.


private void setSpeedRatioButton_Clicked(object sender, RoutedEventArgs args)
{
// Makes the storyboard progress three times as fast as normal.
myStoryboard.SetSpeedRatio(this, 3);
}

// Stops the storyboard.


private void stopButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Stop(this);
}
}
}

'
' This example shows how to control
' a storyboard after it has started.
'
'

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation

Namespace Microsoft.Samples.Animation.TimingBehaviors
Partial Public Class ControlStoryboardExample
Inherits Page
Private ReadOnly myStoryboard As Storyboard

Public Sub New()

' Create a name scope for the page.


NameScope.SetNameScope(Me, New NameScope())

WindowTitle = "Controlling a Storyboard"


Background = Brushes.White

Dim myStackPanel As New StackPanel With {


.Margin = New Thickness(20)
}

' Create a rectangle.


Dim myRectangle As New Rectangle With {
.Width = 100,
.Height = 20,
.Margin = New Thickness(12, 0, 0, 5),
.Fill = New SolidColorBrush(Color.FromArgb(170, 51, 51, 255)),
.HorizontalAlignment = HorizontalAlignment.Left
}
myStackPanel.Children.Add(myRectangle)

' Assign the rectangle a name by


' registering it with the page, so that
' it can be targeted by storyboard
' animations.
RegisterName("myRectangle", myRectangle)

'
' Create an animation and a storyboard to animate the
' rectangle.
'
Dim myDoubleAnimation As New DoubleAnimation(100, 500, New Duration(TimeSpan.FromSeconds(5)))
Storyboard.SetTargetName(myDoubleAnimation, "myRectangle")
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.WidthProperty))
myStoryboard = New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)

'
' Create some buttons to control the storyboard
' and a panel to contain them.
'
Dim buttonPanel As New StackPanel With {
.Orientation = Orientation.Horizontal
}
Dim beginButton As New Button With {
.Content = "Begin"
}
AddHandler beginButton.Click, AddressOf beginButton_Clicked
buttonPanel.Children.Add(beginButton)
Dim pauseButton As New Button With {
.Content = "Pause"
}
AddHandler pauseButton.Click, AddressOf pauseButton_Clicked
buttonPanel.Children.Add(pauseButton)
Dim resumeButton As New Button With {
.Content = "Resume"
}
AddHandler resumeButton.Click, AddressOf resumeButton_Clicked
buttonPanel.Children.Add(resumeButton)
Dim skipToFillButton As New Button With {
.Content = "Skip to Fill"
}
AddHandler skipToFillButton.Click, AddressOf skipToFillButton_Clicked
buttonPanel.Children.Add(skipToFillButton)
Dim setSpeedRatioButton As New Button With {
.Content = "Triple Speed"
.Content = "Triple Speed"
}
AddHandler setSpeedRatioButton.Click, AddressOf setSpeedRatioButton_Clicked
buttonPanel.Children.Add(setSpeedRatioButton)
Dim stopButton As New Button With {
.Content = "Stop"
}
AddHandler stopButton.Click, AddressOf stopButton_Clicked
buttonPanel.Children.Add(stopButton)
myStackPanel.Children.Add(buttonPanel)
Content = myStackPanel
End Sub

' Begins the storyboard.


Private Sub beginButton_Clicked(sender As Object, args As RoutedEventArgs)
' Specifying "true" as the second Begin parameter
' makes this storyboard controllable.
myStoryboard.Begin(Me, True)

End Sub

' Pauses the storyboard.


Private Sub pauseButton_Clicked(sender As Object, args As RoutedEventArgs)
myStoryboard.Pause(Me)

End Sub

' Resumes the storyboard.


Private Sub resumeButton_Clicked(sender As Object, args As RoutedEventArgs)
myStoryboard.Resume(Me)

End Sub

' Advances the storyboard to its fill period.


Private Sub skipToFillButton_Clicked(sender As Object, args As RoutedEventArgs)
myStoryboard.SkipToFill(Me)

End Sub

' Updates the storyboard's speed.


Private Sub setSpeedRatioButton_Clicked(sender As Object, args As RoutedEventArgs)
' Makes the storyboard progress three times as fast as normal.
myStoryboard.SetSpeedRatio(Me, 3)

End Sub

' Stops the storyboard.


Private Sub stopButton_Clicked(sender As Object, args As RoutedEventArgs)
myStoryboard.Stop(Me)

End Sub

End Class
End Namespace

Vea también
Utilizar desencadenadores de eventos para controlar un guión gráfico después de su inicio
Cómo: Controlar una animación mediante From, To y
By
20/02/2020 • 4 minutes to read • Edit Online

Una "from/to/by" o "Basic Animation" crea una transición entre dos valores de destino (consulte información
general sobre animaciones para ver una introducción a los diferentes tipos de animaciones). Para establecer los
valores de destino de una animación básica, utilice sus propiedades From, Toy By. En la tabla siguiente se resume
cómo se pueden usar las propiedades From, Toy By juntas o por separado para determinar los valores de destino
de una animación.

PROPIEDADES ESPECIFICADAS COMPORTAMIENTO RESULTANTE

From La animación progresa desde el valor especificado por la


propiedad From hasta el valor base de la propiedad que se
anima o hasta el valor de salida de una animación anterior, en
función de cómo esté configurada la animación anterior.

From y To La animación progresa desde el valor especificado por la


propiedad From hasta el valor especificado por la propiedad
To.

From y By La animación progresa desde el valor especificado por la


propiedad From hasta el valor especificado por la suma de las
propiedades From y By.

To La animación progresa desde el valor base de la propiedad


animada o desde el valor de salida de una animación anterior
hasta el valor especificado por la propiedad To.

By La animación progresa desde el valor base de la propiedad


que se anima o desde el valor de salida de una animación
previa hasta la suma de ese valor y el valor especificado por la
propiedad By.

NOTE
No establezca la propiedad To y la propiedad By en la misma animación.

Para usar otros métodos de interpolación o animar entre más de dos valores de destino, use una animación de
fotogramas clave. Consulte información General sobre animaciones de fotogramas clave para obtener más
información.
Para obtener información sobre cómo aplicar varias animaciones a una sola propiedad, vea información general
sobre animaciones de fotogramas clave.
En el ejemplo siguiente se muestran los distintos efectos de establecer las propiedades To, Byy From en las
animaciones.

Ejemplo
<!-- This example shows the different effects of setting
<!-- This example shows the different effects of setting
To, By, and From properties on animations. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<StackPanel Margin="20">

<!-- Demonstrates the From and To properties used together. -->


<Rectangle Name="fromToAnimatedRectangle" Height="10" Width="100"
HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />

<!-- Demonstrates the use of the To property. -->


<Rectangle Name="toAnimatedRectangle" Height="10" Width="100"
HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />

<!-- Demonstrates the use of the By property. -->


<Rectangle Name="byAnimatedRectangle" Height="10" Width="100"
HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />

<!-- Demonstrates the use of the From and By properties. -->


<Rectangle Name="fromByAnimatedRectangle" Height="10" Width="100"
HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />

<!-- Demonstrates the use of the From property. -->


<Rectangle Name="fromAnimatedRectangle" Height="10" Width="100"
HorizontalAlignment="Left" Margin="10" Fill="#99FF9900" />
<Button>
Start Animations
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard FillBehavior="Stop">

<!-- Demonstrates the From and To properties used together.


Animates the rectangle's Width property from 50 to 300 over 10 seconds. -->
<DoubleAnimation
Storyboard.TargetName="fromToAnimatedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
From="50" To="300" Duration="0:0:10" />

<!-- Demonstrates the To property used by itself.


Animates the Rectangle's Width property from its base value
(100) to 300 over 10 seconds. -->
<DoubleAnimation
Storyboard.TargetName="toAnimatedRectangle" Storyboard.TargetProperty="(Rectangle.Width)"
To="300" Duration="0:0:10" />

<!-- Demonstrates the By property used by itself.


Increments the Rectangle's Width property by 300 over 10 seconds.
As a result, the Width property is animated from its base value
(100) to 400 (100 + 300) over 10 seconds. -->
<DoubleAnimation
Storyboard.TargetName="byAnimatedRectangle" Storyboard.TargetProperty="(Rectangle.Width)"
By="300" Duration="0:0:10" />

<!-- Demonstrates the From and By properties used together.


Increments the Rectangle's Width property by 300 over 10 seconds.
As a result, the Width property is animated from 50
to 350 (50 + 300) over 10 seconds. -->
<DoubleAnimation
Storyboard.TargetName="fromByAnimatedRectangle" Storyboard.TargetProperty="(Rectangle.Width)"
From="50" By="300" Duration="0:0:10" />

<!-- Demonstrates the From property used by itself.


Animates the rectangle's Width property from 50 to its base value (100)
over 10 seconds. -->
<DoubleAnimation
Storyboard.TargetName="fromAnimatedRectangle" Storyboard.TargetProperty="(Rectangle.Width)"
From="50" Duration="0:0:10" />
From="50" Duration="0:0:10" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>

Consulte también
Información general sobre animaciones
Información general sobre animaciones de fotogramas clave
Ejemplo de valores de destino de animación From, To y By
Procedimiento Definir un ámbito de nombres
23/10/2019 • 3 minutes to read • Edit Online

Para animar con Storyboard en código, debe crear un NameScope y registre los nombres de los objetos de destino
con el elemento que posee ese ámbito de nombres. En el ejemplo siguiente, un NameScope se crea para
myMainPanel . Dos botones, button1 y button2 , se agregan a la pantalla y sus nombres registrados. Varias
animaciones y un Storyboard se crean. Del guión gráfico Begin método se usa para iniciar las animaciones.
Dado que button1 , button2 , y myMainPanel todas comparten el mismo ámbito de nombres, se puede utilizar
cualquiera de ellos con el Storyboard Begin método para iniciar las animaciones.

Ejemplo
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Microsoft.Samples.Animation.AnimatingWithStoryboards
{

public class ScopeExample : Page


{

private Storyboard myStoryboard;


private StackPanel myMainPanel;
private Button button1, button2;

public ScopeExample()
{

this.Background = Brushes.White;
myMainPanel = new StackPanel();

// Create a name scope for the stackpanel.


NameScope.SetNameScope(myMainPanel, new NameScope());

myMainPanel.Background = Brushes.Orange;

button1 = new Button();


button1.Name = "Button1";

// Register button1's name with myMainPanel.


myMainPanel.RegisterName(button1.Name, button1);
button1.Content = "Button 1";
button1.Click += new RoutedEventHandler(button1Clicked);
myMainPanel.Children.Add(button1);

button2 = new Button();


button2.Name = "Button2";

// Register button2's name with myMainPanel.


myMainPanel.RegisterName(button2.Name, button2);
button2.Content = "Button 2";
button2.Click += new RoutedEventHandler(button2Clicked);
myMainPanel.Children.Add(button2);

// Create some animations and a storyboard.


// Create some animations and a storyboard.
DoubleAnimation button1WidthAnimation =
new DoubleAnimation(300, 200, new Duration(TimeSpan.FromSeconds(5)));
Storyboard.SetTargetName(button1WidthAnimation, button1.Name);
Storyboard.SetTargetProperty(button1WidthAnimation, new PropertyPath(Button.WidthProperty));

DoubleAnimation button2WidthAnimation =
new DoubleAnimation(300, 200, new Duration(TimeSpan.FromSeconds(5)));
Storyboard.SetTargetName(button2WidthAnimation, button2.Name);
Storyboard.SetTargetProperty(button2WidthAnimation, new PropertyPath(Button.WidthProperty));

DoubleAnimation heightAnimationWithoutTarget =
new DoubleAnimation(300, 200, new Duration(TimeSpan.FromSeconds(5)));
Storyboard.SetTargetProperty(heightAnimationWithoutTarget, new
PropertyPath(FrameworkElement.HeightProperty));

myStoryboard = new Storyboard();


myStoryboard.Children.Add(button1WidthAnimation);
myStoryboard.Children.Add(button2WidthAnimation);
myStoryboard.Children.Add(heightAnimationWithoutTarget);

this.Content = myMainPanel;
}

private void button1Clicked(object sender, RoutedEventArgs args)


{

// Starts the animations. The animation without a specified


// target name, heightAnimationWithoutTarget, is applied to
// myMainPanel.
myStoryboard.Begin(myMainPanel);
}

private void button2Clicked(object sender, RoutedEventArgs args)


{

// Starts the animations. The animation without a specified


// target name, heightAnimationWithoutTarget, is applied to
// button2.
myStoryboard.Begin(button2);
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes

Namespace Microsoft.Samples.Animation.AnimatingWithStoryboards

Public Class ScopeExample


Inherits Page

Private myStoryboard As Storyboard


Private myMainPanel As StackPanel
Private button1, button2 As Button

Public Sub New()

Me.Background = Brushes.White
myMainPanel = New StackPanel()
' Create a name scope for the stackpanel.
NameScope.SetNameScope(myMainPanel, New NameScope())

myMainPanel.Background = Brushes.Orange

button1 = New Button()


button1.Name = "Button1"

' Register button1's name with myMainPanel.


myMainPanel.RegisterName(button1.Name, button1)
button1.Content = "Button 1"
AddHandler button1.Click, AddressOf button1Clicked
myMainPanel.Children.Add(button1)

button2 = New Button()


button2.Name = "Button2"

' Register button2's name with myMainPanel.


myMainPanel.RegisterName(button2.Name, button2)
button2.Content = "Button 2"
AddHandler button2.Click, AddressOf button2Clicked
myMainPanel.Children.Add(button2)

' Create some animations and a storyboard.


Dim button1WidthAnimation As New DoubleAnimation(300, 200, New Duration(TimeSpan.FromSeconds(5)))
Storyboard.SetTargetName(button1WidthAnimation, button1.Name)
Storyboard.SetTargetProperty(button1WidthAnimation, New PropertyPath(Button.WidthProperty))

Dim button2WidthAnimation As New DoubleAnimation(300, 200, New Duration(TimeSpan.FromSeconds(5)))


Storyboard.SetTargetName(button2WidthAnimation, button2.Name)
Storyboard.SetTargetProperty(button2WidthAnimation, New PropertyPath(Button.WidthProperty))

Dim heightAnimationWithoutTarget As New DoubleAnimation(300, 200, New


Duration(TimeSpan.FromSeconds(5)))
Storyboard.SetTargetProperty(heightAnimationWithoutTarget, New
PropertyPath(FrameworkElement.HeightProperty))

myStoryboard = New Storyboard()


myStoryboard.Children.Add(button1WidthAnimation)
myStoryboard.Children.Add(button2WidthAnimation)
myStoryboard.Children.Add(heightAnimationWithoutTarget)

Me.Content = myMainPanel

End Sub

Private Sub button1Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)

' Starts the animations. The animation without a specified


' target name, heightAnimationWithoutTarget, is applied to
' myMainPanel.
myStoryboard.Begin(myMainPanel)

End Sub

Private Sub button2Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)

' Starts the animations. The animation without a specified


' target name, heightAnimationWithoutTarget, is applied to
' button2.
myStoryboard.Begin(button2)

End Sub

End Class
End Namespace

Vea también
Animar una propiedad utilizando un guión gráfico
Información general sobre animaciones
Procedimiento Recibir una notificación cuando
cambia el estado de un reloj
23/10/2019 • 3 minutes to read • Edit Online

Un reloj CurrentStateInvalidated evento tiene lugar cuando su CurrentState deja de ser válido, por ejemplo,
cuando se inicia o detiene el reloj. Puede registrarse para este evento con directamente mediante un Clock, o bien
puede registrar con un Timeline.
En el ejemplo siguiente, un Storyboard y dos DoubleAnimation objetos se utilizan para animar el ancho de dos
rectángulos. El CurrentStateInvalidated eventos se usan para realizar escuchas de los cambios de estado de reloj.

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.Animation.TimingBehaviors.StateExample"
Background="LightGray">
<StackPanel Margin="20">

<TextBlock
Name="ParentTimelineStateTextBlock"></TextBlock>
<TextBlock
Name="Animation1StateTextBlock"></TextBlock>
<Rectangle
Name="Rectangle01"
Width="100" Height="50" Fill="Orange" />
<TextBlock Name="Animation2StateTextBlock"></TextBlock>
<Rectangle
Name="Rectangle02"
Width="100" Height="50" Fill="Gray" />

<Button Content="Start Animations" Margin="20">


<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard RepeatBehavior="2x" AutoReverse="True"
CurrentStateInvalidated="parentTimelineStateInvalidated" >
<DoubleAnimation
Storyboard.TargetName="Rectangle01"
Storyboard.TargetProperty="Width"
From="10" To="200" Duration="0:0:9"
BeginTime="0:0:1"
CurrentStateInvalidated="animation1StateInvalidated"/>
<DoubleAnimation
Storyboard.TargetName="Rectangle02"
Storyboard.TargetProperty="Width"
From="10" To="200" Duration="0:0:8"
BeginTime="0:0:1"
CurrentStateInvalidated="animation2StateInvalidated" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

</StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{

public partial class StateExample : Page


{

private void parentTimelineStateInvalidated(object sender, EventArgs args)


{
Clock myClock = (Clock)sender;
ParentTimelineStateTextBlock.Text +=
myClock.CurrentTime.ToString() + ":"
+ myClock.CurrentState.ToString() + " ";
}

private void animation1StateInvalidated(object sender, EventArgs args)


{

Clock myClock = (Clock)sender;

Animation1StateTextBlock.Text +=
myClock.Parent.CurrentTime.ToString() + ":"
+ myClock.CurrentState.ToString() + " ";
}

private void animation2StateInvalidated(object sender, EventArgs args)


{

Clock myClock = (Clock)sender;


Animation2StateTextBlock.Text +=
myClock.Parent.CurrentTime.ToString() + ":"
+ myClock.CurrentState.ToString() + " ";
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation

Namespace Microsoft.Samples.Animation.TimingBehaviors

Partial Public Class StateExample


Inherits Page

Private Sub parentTimelineStateInvalidated(ByVal sender As Object, ByVal args As EventArgs)


Dim myClock As Clock = CType(sender, Clock)
ParentTimelineStateTextBlock.Text += myClock.CurrentTime.ToString() & ":" &
myClock.CurrentState.ToString() & " "
End Sub

Private Sub animation1StateInvalidated(ByVal sender As Object, ByVal args As EventArgs)

Dim myClock As Clock = CType(sender, Clock)

Animation1StateTextBlock.Text += myClock.Parent.CurrentTime.ToString() & ":" &


myClock.CurrentState.ToString() & " "
End Sub

Private Sub animation2StateInvalidated(ByVal sender As Object, ByVal args As EventArgs)

Dim myClock As Clock = CType(sender, Clock)


Animation2StateTextBlock.Text += myClock.Parent.CurrentTime.ToString() & ":" &
myClock.CurrentState.ToString() & " "
End Sub
End Class
End Namespace

En la siguiente ilustración muestra los distintos Estados de las animaciones se especifica como la escala de tiempo
primaria (guión gráfico) progresa.

La siguiente tabla muestra las horas en que Animation1del CurrentStateInvalidated desencadena el evento:

Tiempo 1 10 19 21 30 39
(segundos)

Estado Activo Activo Detenido Activo Activo Detenido


La siguiente tabla muestra las horas en que Animation2del CurrentStateInvalidated desencadena el evento:

Tiempo 1 9 11 19 21 29 31 39
(segundo
s)

Estado Activo Rellenar Activo Detenido Activo Rellenar Activo Detenido

Tenga en cuenta que Animation1del CurrentStateInvalidated evento se desencadena en 10 segundos, aunque su


estado sigue siendo Active. Eso es porque su estado cambia a 10 segundos, pero puede cambiar de Active a Filling
y luego volver a Active en el mismo paso.
Procedimiento Repetir una animación
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el RepeatBehavior propiedad de un Timeline con el fin de controlar el
comportamiento de repetición de una animación.

Ejemplo
El RepeatBehavior propiedad de un Timeline controla el número de veces que una animación repite su duración
simple. Mediante el uso de RepeatBehavior, puede especificar que un Timeline se repite durante un determinado
número de veces (un número de iteraciones) o durante un período de tiempo especificado. En cualquier caso, la
animación pasa por tantas ejecuciones de principio a fin que necesita para rellenar el número solicitado o la
duración.
De forma predeterminada, las escalas de tiempo tienen un número de repeticiones de 1,0, lo que significa que se
reproducen una vez y no se repiten. Sin embargo, si establece la RepeatBehavior propiedad de un Timeline a
Forever, la escala de tiempo se repite indefinidamente.
El ejemplo siguiente muestra cómo usar el RepeatBehavior propiedad para controlar el comportamiento de
repetición de una animación. El ejemplo se anima la Width propiedad cinco rectángulos con cada rectángulo con
un tipo diferente del comportamiento de repetición.

<!-- RepeatBehaviorExample.xaml
This example shows how to use the RepeatBehavior property to make a timeline repeat. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="RepeatBehavior Example">

<Border HorizontalAlignment="Stretch">
<StackPanel Margin="20">

<!-- Create several rectangles to animate. -->


<Rectangle Name="ForeverRepeatingRectangle"
Fill="Orange" Width="50" Height="20" />
<Rectangle Name="FourSecondsRepeatingRectangle"
Fill="Orange" Width="50" Height="20" />
<Rectangle Name="TwiceRepeatingRectangle"
Fill="Orange" Width="50" Height="20" />
<Rectangle Name="HalfRepeatingRectangle"
Fill="Orange" Width="50" Height="20" />
<Rectangle Name="OneSecondRepeatingRectangle"
Fill="Orange" Width="50" Height="20" />

<!-- Create buttons to restart and stop the animations. -->


<StackPanel Orientation="Horizontal" Margin="0,20,0,0">
<Button Name="restartButton">Start Animations</Button>
<Button Name="stopButton" Background="#669900FF">Stop</Button>

<StackPanel.Triggers>
<EventTrigger SourceName="restartButton" RoutedEvent="Button.Click">
<BeginStoryboard Name="myBeginStoryboard">
<Storyboard>

<!-- Create an animation that repeats indefinitely. -->


<DoubleAnimation
Storyboard.TargetName="ForeverRepeatingRectangle"
Storyboard.TargetProperty="Width"
Storyboard.TargetProperty="Width"
From="50" To="300" Duration="0:0:2" RepeatBehavior="Forever" />

<!-- Create an animation that repeats for four seconds. As a result, the
animation repeats twice. -->
<DoubleAnimation
Storyboard.TargetName="FourSecondsRepeatingRectangle"
Storyboard.TargetProperty="Width"
From="50" To="300" Duration="0:0:2" RepeatBehavior="0:0:4" />

<!-- Create an animation that repeats twice. -->


<DoubleAnimation
Storyboard.TargetName="TwiceRepeatingRectangle"
Storyboard.TargetProperty="Width"
From="50" To="300" Duration="0:0:2" RepeatBehavior="2x" />

<!-- Create an animation that repeats 0.5 times. The resulting animation
plays for one second, half of its Duration. It animates from 50 to 150. -->
<DoubleAnimation
Storyboard.TargetName="HalfRepeatingRectangle"
Storyboard.TargetProperty="Width"
From="50" To="300" Duration="0:0:2" RepeatBehavior="0.5x" />

<!-- Create an animation that repeats for one second. The resulting animation
plays for one second, half of its Duration. It animates from 50 to 150. -->
<DoubleAnimation
Storyboard.TargetName="OneSecondRepeatingRectangle"
Storyboard.TargetProperty="Width"
From="50" To="300" Duration="0:0:2" RepeatBehavior="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger SourceName="stopButton" RoutedEvent="Button.Click">
<StopStoryboard BeginStoryboardName="myBeginStoryboard" />
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>
</StackPanel>
</Border>
</Page>

Para obtener un ejemplo completo, vea ejemplo de comportamiento de control de tiempo de animación.

Vea también
Acumular valores de animaciones durante la repetición de ciclos
Especificar si una escala de tiempo se invierte automáticamente
Temas de procedimientos de temporización y animación
Información general sobre animaciones
Ejemplo del comportamiento del control de tiempo de la animación
Procedimiento Buscar un guión gráfico
23/10/2019 • 2 minutes to read • Edit Online

El ejemplo siguiente muestra cómo usar el Seek método de un Storyboard para saltar a alguna posición en una
animación de guión gráfico.

Ejemplo
A continuación se muestra el marcado XAML para el ejemplo.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.SeekStoryboardExample">
<StackPanel Margin="20" >

<Rectangle Name="myRectangle"
Width="10" Height="20" Fill="#AA3333FF" HorizontalAlignment="Left" >
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard Name="myBeginStoryboard">
<Storyboard Name="myStoryboard" Duration="0:0:4">
<DoubleAnimation
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="Width"
Duration="0:0:4" From="10" To="500"/>
</Storyboard>

</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

<!-- Use this slider to seek to different points of the Storyboard Duration
(in milliseconds). -->
<Slider Name="SeekSlider" ValueChanged="OnSliderValueChanged" Height="Auto"
Width="500" Minimum="0" Maximum="4000" HorizontalAlignment="Left" />

</StackPanel>
</Page>

Ejemplo
El siguiente es el código utilizado con el código XAML anterior.
using System;
using System.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace SDKSample
{

public partial class SeekStoryboardExample : Page


{
private void OnSliderValueChanged(object sender, RoutedEventArgs e)
{
int sliderValue = (int)SeekSlider.Value;

// Use the value of the slider to seek to a duration value of the Storyboard (in milliseconds).
myStoryboard.Seek(myRectangle, new TimeSpan(0, 0, 0, 0, sliderValue), TimeSeekOrigin.BeginTime);
}
}
}

Imports System.Media
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media.Animation

Namespace SDKSample

Partial Public Class SeekStoryboardExample


Inherits Page
Private Sub OnSliderValueChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim sliderValue As Integer = CInt(SeekSlider.Value)

' Use the value of the slider to seek to a duration value of the Storyboard (in milliseconds).
myStoryboard.Seek(myRectangle, New TimeSpan(0, 0, 0, 0, sliderValue), TimeSeekOrigin.BeginTime)
End Sub
End Class

End Namespace

Vea también
Buscar guiones gráficos de forma sincrónica
Procedimiento Buscar guiones gráficos de forma
sincrónica
23/10/2019 • 2 minutes to read • Edit Online

El ejemplo siguiente muestra cómo usar el SeekAlignedToLastTick método de un Storyboard para buscar alguna
posición en una animación de guión gráfico de forma sincrónica.

Ejemplo
A continuación se muestra el marcado XAML para el ejemplo.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.SeekStoryboardSynchronouslyExample">
<StackPanel Margin="20" >

<Rectangle Name="myRectangle"
Width="10" Height="20" Fill="#AA3333FF" HorizontalAlignment="Left" >
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard Name="myBeginStoryboard">
<Storyboard Name="myStoryboard" Duration="0:0:4">
<DoubleAnimation
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="Width"
Duration="0:0:4" From="10" To="500"/>
</Storyboard>

</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

<!-- Use this slider to seek to different points of the Storyboard Duration
(in milliseconds). -->
<Slider Name="SeekSlider" ValueChanged="OnSliderValueChanged" Height="Auto"
Width="500" Minimum="0" Maximum="4000" HorizontalAlignment="Left" />

<!-- TextBlock displays the current time position of the Storyboard in milliseconds. -->
<TextBlock Name="PositionTextBlock"/>
</StackPanel>
</Page>

Ejemplo
El siguiente es el código utilizado con el código XAML anterior.
using System;
using System.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace SDKSample
{

public partial class SeekStoryboardSynchronouslyExample : Page


{
private void OnSliderValueChanged(object sender, RoutedEventArgs e)
{
int sliderValue = (int)SeekSlider.Value;

// The SeekAlignedToLastTick method should be used to seek a Storyboard synchronously.


myStoryboard.SeekAlignedToLastTick(myRectangle, new TimeSpan(0, 0, 0, 0, sliderValue),
TimeSeekOrigin.BeginTime);
PositionTextBlock.Text = sliderValue.ToString();
}
}
}

Imports System.Media
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media.Animation

Namespace SDKSample

Partial Public Class SeekStoryboardSynchronouslyExample


Inherits Page
Private Sub OnSliderValueChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim sliderValue As Integer = CInt(SeekSlider.Value)

' The SeekAlignedToLastTick method should be used to seek a Storyboard synchronously.


myStoryboard.SeekAlignedToLastTick(myRectangle, New TimeSpan(0, 0, 0, 0, sliderValue),
TimeSeekOrigin.BeginTime)
PositionTextBlock.Text = sliderValue.ToString()
End Sub
End Class

End Namespace
Procedimiento Definir una duración para una
animación
23/10/2019 • 3 minutes to read • Edit Online

Un Timeline representa un segmento de tiempo y la longitud de ese segmento viene determinada por la escala de
tiempo Duration. Cuando un Timeline llega al final de su duración, detiene la reproducción. Si el Timeline tiene
objetos Timeline secundarios, detener la reproducción. En el caso de una animación, la Duration especifica cuánto
tiempo tarda la animación en la transición desde su valor inicial hasta su valor final.
Puede especificar un Duration con una hora específica y finita o los valores especiales Automatic o Forever.
Duración de una animación siempre debe ser un valor de tiempo, porque una animación siempre debe tener una
longitud definida, finita, de lo contrario, la animación no sabría cómo realizar la transición entre sus valores de
destino. Escalas de tiempo contenedoras (TimelineGroup objetos), como Storyboard y ParallelTimeline, tienen una
duración predeterminada de Automatic, lo que significa que finalizan automáticamente cuando detiene la
reproducción de su último miembro secundario.
En el siguiente color de ejemplo, el ancho, alto y el relleno de un Rectangle está animada. Las duraciones están
establecidas en escalas de tiempo de animación y el contenedor resultante en los efectos de animación como
controlar la velocidad de una animación percibida y reemplazar la duración de objetos Timeline secundarios con la
duración de un objeto contenedor.

Ejemplo
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="20">

<Rectangle Width="100" Height="100" Name="myRectangle">


<Rectangle.Fill>
<SolidColorBrush x:Name="MyAnimatedBrush" Color="Black" />
</Rectangle.Fill>
<Rectangle.Triggers>

<!-- Animates the rectangle fill to yellow and width to 300. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>

<!-- By default, TimelineGroup objects like Storyboard and ParallelTimeline have


a Duration of "Automatic". A TimelineGroup's automatic duration encompasses its
last-ending child. In this example, there is only one child of the Storyboard, the
ParallelTimeline, so when the ParallelTimeline ends, the Storyboard duration will
automatically end. -->
<Storyboard>

<!-- This ParallelTimeline has overriden its default duration of "Automatic" with
a finite duration of half a second. This will force this Timeline to end after half a
second even though its child Timelines have a longer duration (2 and 4 seconds respectively).
This cuts off the animation prematurely and the rectangle's fill will not go all the way to
yellow nor will the rectangle width get all the way to 300. Again, the default duration of a
ParallelTimeline is "Automatic" so if you remove the finite duration, the ParallelTimeline
will wait for its child timelines to end before it ends. -->

<!-- Note: To specify a finite time in XAML, use the syntax of "days:hours:seconds". As
mentioned,
this ParallelTimeline has a duration of half a second. -->
<ParallelTimeline Duration="0:0:0.5">

<!-- For Animation Timelines like DoubleAnimation, the duration is one factor that
determines the rate at which an animation appears to progress. For example, the
DoubleAnimation
below that animates the rectangle height will complete in only one second while the animation
that animates the width willwill complete in 2 seconds which is relatively fast compared to
the DoubleAnimation
which animates the rectangle width over 4 seconds. -->
<DoubleAnimation
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="Height"
To="300" Duration="0:0:1" />

<DoubleAnimation
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="Width"
To="300" Duration="0:0:4" />

<ColorAnimation
Storyboard.TargetName="MyAnimatedBrush"
Storyboard.TargetProperty="Color"
To="Yellow" Duration="0:0:2" />

</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>

</Rectangle.Triggers>
</Rectangle>
</StackPanel>
</Page>
Vea también
Duration
Información general sobre animaciones
Procedimiento Establecer una propiedad después de
animarla con un guión gráfico
23/10/2019 • 4 minutes to read • Edit Online

En algunos casos, es posible que parece que no se puede cambiar el valor de una propiedad después de que se
ha animado.

Ejemplo
En el ejemplo siguiente, un Storyboard sirve para animar el color de un SolidColorBrush. El guión gráfico se
desencadena cuando se hace clic en el botón. El Completed se controla el evento para que el programa recibe
una notificación cuando el ColorAnimation se complete.

<Button
Content="Animate and Then Set Example 1">
<Button.Background>
<SolidColorBrush x:Name="Button1BackgroundBrush"
Color="Red" />
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Button1BackgroundBrush"
Storyboard.TargetProperty="Color"
From="Red" To="Yellow" Duration="0:0:5"
FillBehavior="HoldEnd"
Completed="setButton1BackgroundBrushColor" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

Ejemplo
Después de la ColorAnimation finalice, el programa intenta cambiar el color del pincel a azul.

private void setButton1BackgroundBrushColor(object sender, EventArgs e)


{

// Does not appear to have any effect:


// the brush remains yellow.
Button1BackgroundBrush.Color = Colors.Blue;
}

Private Sub setButton1BackgroundBrushColor(ByVal sender As Object, ByVal e As EventArgs)

' Does not appear to have any effect:


' the brush remains yellow.
Button1BackgroundBrush.Color = Colors.Blue
End Sub
El código anterior no parece hacer nada: la permanece pincel amarillo, que es el valor proporcionado por el
ColorAnimation que anima el pincel. El valor de propiedad subyacente (el valor base) realmente se cambia a azul.
Sin embargo, el valor efectivo o actual, sigue siendo amarillo porque la ColorAnimation continúa invalidando el
valor base. Si desea que el valor base vuelva a ser el valor efectivo, debe detener la animación de influir en la
propiedad. Hay tres maneras de hacer esto con animaciones de guión gráfico:
Establecer la animación FillBehavior propiedad Stop
Quitar el guión gráfico.
Quitar la animación de la propiedad individual.

Establecer FillBehavior (propiedad) de la animación en Stop


Estableciendo FillBehavior a Stop, indica a la animación deje de afectar a su propiedad de destino una vez que
llega al final de su período activo.

<Button
Content="Animate and Then Set Example 2">
<Button.Background>
<SolidColorBrush x:Name="Button2BackgroundBrush"
Color="Red" />
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Button2BackgroundBrush"
Storyboard.TargetProperty="Color"
From="Red" To="Yellow" Duration="0:0:5"
FillBehavior="Stop"
Completed="setButton2BackgroundBrushColor" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

private void setButton2BackgroundBrushColor(object sender, EventArgs e)


{

// This appears to work:


// the brush changes to blue.
Button2BackgroundBrush.Color = Colors.Blue;
}

Private Sub setButton2BackgroundBrushColor(ByVal sender As Object, ByVal e As EventArgs)

' This appears to work:


' the brush changes to blue.
Button2BackgroundBrush.Color = Colors.Blue
End Sub

Quitar el guión gráfico


Mediante el uso de un RemoveStoryboard desencadenador o la Storyboard.Remove método, indicar a las
animaciones de guión gráfico para que dejen de afectar a sus propiedades de destino. La diferencia entre este
enfoque y la configuración de la FillBehavior propiedad es que puede quitar el guión gráfico en cualquier
momento, mientras el FillBehavior propiedad sólo tiene efecto cuando la animación alcanza el final de su período
activo.

<Button
Name="Button3"
Content="Animate and Then Set Example 3">
<Button.Background>
<SolidColorBrush x:Name="Button3BackgroundBrush"
Color="Red" />
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard x:Name="MyStoryboard">
<ColorAnimation
Storyboard.TargetName="Button3BackgroundBrush"
Storyboard.TargetProperty="Color"
From="Red" To="Yellow" Duration="0:0:5"
FillBehavior="HoldEnd"
Completed="setButton3BackgroundBrushColor" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

private void setButton3BackgroundBrushColor(object sender, EventArgs e)


{

// This appears to work:


// the brush changes to blue.
MyStoryboard.Remove(Button3);
Button3BackgroundBrush.Color = Colors.Blue;
}

Private Sub setButton3BackgroundBrushColor(ByVal sender As Object, ByVal e As EventArgs)

' This appears to work:


' the brush changes to blue.
MyStoryboard.Remove(Button3)
Button3BackgroundBrush.Color = Colors.Blue
End Sub

Quitar una animación de una propiedad individual


Otra técnica para detener una animación que afecte a una propiedad es usar el
BeginAnimation(DependencyProperty, AnimationTimeline) método del objeto que se anima. Especifique la
propiedad animada como primer parámetro y null como el segundo.
<Button
Name="Button4"
Content="Animate and Then Set Example 4">
<Button.Background>
<SolidColorBrush x:Name="Button4BackgroundBrush"
Color="Red" />
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Button4BackgroundBrush"
Storyboard.TargetProperty="Color"
From="Red" To="Yellow" Duration="0:0:5"
FillBehavior="HoldEnd"
Completed="setButton4BackgroundBrushColor" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

private void setButton4BackgroundBrushColor(object sender, EventArgs e)


{

// This appears to work:


// the brush changes to blue.
Button4BackgroundBrush.BeginAnimation(SolidColorBrush.ColorProperty, null);
Button4BackgroundBrush.Color = Colors.Blue;
}

Private Sub setButton4BackgroundBrushColor(ByVal sender As Object, ByVal e As EventArgs)

' This appears to work:


' the brush changes to blue.
Button4BackgroundBrush.BeginAnimation(SolidColorBrush.ColorProperty, Nothing)
Button4BackgroundBrush.Color = Colors.Blue
End Sub

Esta técnica también funciona para las animaciones sin guiones gráficos.

Vea también
FillBehavior
Storyboard.Remove
RemoveStoryboard
Información general sobre animaciones
Información general sobre técnicas de animación de propiedades
Procedimiento Simplificar las animaciones mediante
escalas de tiempo secundarias
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo simplificar animaciones utilizando secundarios ParallelTimeline objetos. Un
Storyboard es un tipo de Timeline que proporciona información de destino para las escalas de tiempo contiene.
Use un Storyboard para proporcionar información, incluida la información de objeto y propiedad de destino de la
escala de tiempo.
Para iniciar una animación, utilice uno o varios ParallelTimeline objetos como elementos secundarios anidados de
un Storyboard. Estos ParallelTimeline objetos pueden contener otras animaciones y por lo tanto, pueden
encapsular mejor las secuencias de temporización de animaciones complejas. Por ejemplo, si está animando un
TextBlock y varias formas en el mismo Storyboard, puede separar las animaciones para los TextBlock y las formas y
ponerlas todas en otro ParallelTimeline. Dado que cada ParallelTimeline tiene su propio BeginTime y todos los
elementos secundarios de la ParallelTimeline empiezan en relación con esto BeginTime, se encapsula mejor la
temporización.
El ejemplo siguiente anima dos partes de texto ( TextBlock objetos) desde dentro del mismo Storyboard. Un
ParallelTimeline encapsula las animaciones de uno de los TextBlock objetos.
Nota de rendimiento: Aunque puede anidar Storyboard escalas de tiempo dentro de otras, ParallelTimelineson
más apropiadas para la anidación porque requieren menos sobrecarga. (El Storyboard clase hereda de la
ParallelTimeline clase.)

Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas >

<!-- TextBlock with text "ParallelTimelines are..." that gets animated. -->
<TextBlock Name="FirstTextBlock" Canvas.Top="30" Canvas.Left="300" FontSize="24" >
ParallelTimelines are...
<TextBlock.RenderTransform>
<TransformGroup>
<SkewTransform x:Name="FirstTextBlockSkew" CenterX="25" CenterY="25" AngleX="0" AngleY="0" />
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>

<!-- TextBlock with text "Useful" that gets animated. -->


<TextBlock Name="SecondTextBlock" Opacity="0" Canvas.Top="30" Canvas.Left="585" FontSize="24" >
Useful
<TextBlock.RenderTransform>
<TransformGroup>
<SkewTransform x:Name="SecondTextBlockSkew" CenterX="25" CenterY="25" AngleX="0" AngleY="0" />
<ScaleTransform x:Name="SecondTextBlockScale" CenterX="0" CenterY="24" />
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>

<!-- Event Trigger that controls all animations on the page. -->
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard>
<!-- "ParallelTimelines are..." fades into view. -->
<DoubleAnimation Storyboard.TargetName="FirstTextBlock"
Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="0" To="1" />

<!-- "ParallelTimelines are..." skews to the left. -->


<DoubleAnimation Storyboard.TargetName="FirstTextBlockSkew"
Storyboard.TargetProperty="AngleX" Duration="0:0:1" BeginTime="0:0:2" From="0" To="45" />

<!-- This ParallelTimeline contains all the animations for the TextBlock with the text
"Useful" in it. This ParallelTimeline begins 4 seconds after the Storyboard timeline begins and
all child
animations begin relative to this parent timeline. -->
<ParallelTimeline BeginTime="0:0:4">

<!-- "Useful" fades into view. -->


<DoubleAnimation Storyboard.TargetName="SecondTextBlock"
Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="0" To="1" />

<!-- "Useful" slides in from the right. -->


<DoubleAnimation Storyboard.TargetName="SecondTextBlockSkew"
Storyboard.TargetProperty="AngleX" Duration="0:0:2" From="90" To="180" />

<!-- "Useful" skews to the right. -->


<DoubleAnimation Storyboard.TargetName="SecondTextBlockSkew"
Storyboard.TargetProperty="AngleX" BeginTime="0:0:3" Duration="0:0:0.2" From="0" To="-60" />

<!-- "Useful" Gets taller. -->


<DoubleAnimation Storyboard.TargetName="SecondTextBlockScale"
Storyboard.TargetProperty="ScaleY" BeginTime="0:0:3" Duration="0:0:0.2" From="1" To="3" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
</Page>

Vea también
Información general sobre animaciones
Especificar HandoffBehavior entre animaciones de guión gráfico
Procedimiento Especificar HandoffBehavior entre
animaciones de guión gráfico
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo especificar el comportamiento de entrega entre animaciones de guión gráfico. El
HandoffBehavior propiedad de BeginStoryboard especifica cómo las animaciones nuevas interactúan con otras
existentes que ya se han aplicado a una propiedad.

Ejemplo
El ejemplo siguiente crea dos botones que aumentan cuando se mueve el cursor del mouse sobre ellos y
disminuyen de tamaño cuando el cursor se mueve inmediatamente. Si un botón del mouse y, a continuación,
quitar rápidamente el cursor, la segunda animación se aplicará antes de que finalice la primera de ellas. Es si se
superponen dos animaciones como esta, que puede ver la diferencia entre el HandoffBehavior valores de
Compose y SnapshotAndReplace. Un valor de Compose combina las animaciones superpuestas causando una
transición más suave entre animaciones, mientras que un valor de SnapshotAndReplace hace que la nueva
animación reemplace inmediatamente la animación que anteriormente se superponen.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<!-- This Style specifies mouseover and mouseout behaviors. The button gets larger when
the cursor moves over it and smaller when the cursor moves away. Note that the same Properties
(ScaleX and ScaleY) are being targeted by both animations. The BeginStoryboard for each animation
uses a HandoffBehavior of "Compose" which causes the old animation to interpolate more gradually into
the new one. -->
<Style x:Key="ButtonWithCompose" TargetType="{x:Type Button}">
<Setter Property="Button.RenderTransform">
<Setter.Value>
<ScaleTransform CenterX="50" CenterY="50" ScaleX="1" ScaleY="1" />
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard >
<Storyboard>
<DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleX" To="3"
/>
<DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleY" To="3"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard HandoffBehavior="Compose">
<Storyboard>
<DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleX" />
<DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleY" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Style>
<!-- For this button style, BeginStoryboard uses the default HandoffBehavior of "SnapShotAndReplace" -->
<Style x:Key="ButtonWithSnapShotAndReplace" TargetType="{x:Type Button}">
<Setter Property="Button.RenderTransform">
<Setter.Value>
<ScaleTransform CenterX="50" CenterY="50" ScaleX="1" ScaleY="1" />
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard >
<Storyboard>
<DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleX" To="3"
/>
<DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleY" To="3"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleX" />
<DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="RenderTransform.ScaleY" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Page.Resources>
<Canvas>
<Button Style="{StaticResource ButtonWithSnapShotAndReplace}" Canvas.Top="200" Canvas.Left="200"
Width="100" Height="100">
SnapShotAndReplace
</Button>
<Button Style="{StaticResource ButtonWithCompose}" Canvas.Top="200" Canvas.Left="400" Width="100"
Height="100">
Compose
</Button>
</Canvas>
</Page>

Vea también
BeginStoryboard
HandoffBehavior
Información general sobre animaciones
Temas de procedimientos de temporización y animación
Procedimiento Especificar el comportamiento de
relleno de una escala de tiempo que ha llegado al
final de su período de actividad
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo especificar el FillBehavior para la inactiva Timeline de una propiedad animada.

Ejemplo
El FillBehavior propiedad de un Timeline determina lo que ocurre en el valor de una propiedad animada cuando
no se está animada, es decir, cuando el Timeline está inactivo, pero su elemento primario Timeline está dentro de
su activo o el período de espera. ¿Por ejemplo, se seguirá una propiedad animada final de su valor después de la
animación finaliza, o lo hace volver al valor que tenía antes de inicia la animación?
En el ejemplo siguiente se usa un DoubleAnimation para animar la Width de dos rectángulos. Cada rectángulo usa
otra Timeline objeto.
Una Timeline tiene un FillBehavior que se establece en Stop, lo que hace que el ancho del rectángulo se va a volver
a su no animado valor cuando la Timeline finaliza. El otro Timeline tiene un FillBehavior de HoldEnd, lo que hace
que el ancho permanezca en su extremo valor cuando la Timeline finaliza.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel Margin="20">
<Border Background="#99FFFFFF">
<TextBlock Margin="20">
This example shows how the FillBehavior property determines how an animation behaves
after it reaches the end of its duration.
</TextBlock>
</Border>

<TextBlock>FillBehavior="Deactivate"</TextBlock>
<Rectangle Name="deactiveAnimationRectangle" Width="20" Height="20" Fill="#AA3333FF"
HorizontalAlignment="Left" >
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- The animated rectangle's width reverts back to its non-animated value
after the animation ends. -->
<DoubleAnimation
Storyboard.TargetName="deactiveAnimationRectangle"
Storyboard.TargetProperty="Width"
From="100" To="400" Duration="0:0:2" FillBehavior="Stop" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

<TextBlock Margin="0,20,0,0">FillBehavior="HoldEnd" </TextBlock>


<Rectangle Name="holdEndAnimationRectangle" Width="20" Height="20" Fill="#AA3333FF"
HorizontalAlignment="Left" >
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- The animated rectangle's width remains at its end value after the
animation ends. -->
<DoubleAnimation Storyboard.TargetName="holdEndAnimationRectangle"
Storyboard.TargetProperty="Width"
From="100" To="400" Duration="0:0:2" FillBehavior="HoldEnd" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
</Page>

Para obtener un ejemplo completo, vea Animation Example Gallery.

Vea también
DoubleAnimation
Width
Timeline
FillBehavior
Stop
HoldEnd
Información general sobre animaciones
Temas de procedimientos de temporización y animación
Procedimiento Especificar si una escala de tiempo se
invierte automáticamente
23/10/2019 • 2 minutes to read • Edit Online

Una escala de tiempo AutoReverse propiedad determina si reproduce en orden inverso después de completar una
iteración de avance. El ejemplo siguiente muestra varias animaciones con duración idéntico y los valores de
destino, pero con diferentes AutoReverse configuración. Para demostrar cómo el AutoReverse propiedad se
comporta con diferentes RepeatBehavior , algunas animaciones están configurados para repetir. La última
animación se muestra cómo el AutoReverse propiedad funciona en escalas de tiempo anidadas.

Ejemplo
<!-- AutoReverseExample.xaml
This example shows how to use the AutoReverse property to make a timeline
play backwards at the end of each iteration.
Several rectangles are animated by DoubleAnimations with
identical durations and target values, but with different
AutoReverse and RepeatBehavior settings.-->

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="AutoReverse Example">
<StackPanel Margin="20">

<!-- Create some rectangles to animate. -->


<Rectangle Name="withoutAutoReverseRectangle"
Width="100" Height="20" Fill="Blue" />

<Rectangle Name="autoReverseRectangle"
Width="100" Height="20" Fill="Blue" />

<Rectangle Name="autoReverseRectangleWithRepeats"
Width="100" Height="20" Fill="Blue" />

<Rectangle Name="complexAutoReverseExample"
Width="100" Height="20" Fill="Blue" />

<!-- Use a button to restart the animations. -->


<Button Margin="30" Content="Start Animations">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>

<!-- Create an animation that does not automatically play in reverse.


This animation plays for a total of 2 seconds. -->
<DoubleAnimation
Storyboard.TargetName="withoutAutoReverseRectangle"
Storyboard.TargetProperty="Width"
Duration="0:0:2" From="100" To="400" AutoReverse="False" />

<!-- Create an animation that automatically reverses at the end of each iteration.
This animation plays for a total of 4 seconds. -->
<DoubleAnimation Storyboard.TargetName="autoReverseRectangle"
Storyboard.TargetProperty="Width"
Duration="0:0:2" From="100" To="400" AutoReverse="True" />

<!-- Create an animation that automatically reverses at the end of each iteration.
Set the animation to repeat twice. As a result, then animation plays forward,
Set the animation to repeat twice. As a result, then animation plays forward,
the backward, then forward, and then backward again.
This animation plays for a total of 8 seconds. -->
<DoubleAnimation Storyboard.TargetName="autoReverseRectangleWithRepeats"
Storyboard.TargetProperty="Width"
Duration="0:0:2" From="100" To="400" AutoReverse="True" RepeatBehavior="2x" />

<!-- Set the parent timeline's AutoReverse property to True and set the animation's
RepeatBehavior to 2x. As a result, the animation plays forward twice and then
backwards twice.
This animation plays for a total of 8 seconds. -->
<ParallelTimeline AutoReverse="True">
<DoubleAnimation
Storyboard.TargetName="complexAutoReverseExample"
Storyboard.TargetProperty="Width"
Duration="0:0:2" From="100" To="400" RepeatBehavior="2x" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>
Procedimiento Activar una animación al cambiar el
valor de una propiedad
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un Trigger para iniciar un Storyboard cuando cambia un valor de
propiedad. Puede usar un Trigger dentro de un Style, ControlTemplate, o DataTemplate.

Ejemplo
En el ejemplo siguiente se usa un Trigger para animar la Opacity de un Button cuando su IsMouseOver propiedad
pasa a ser true .

<!-- PropertyTriggerExample.xaml
Shows how to use property triggers to start animations. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Animate Properties with Storyboards">
<Page.Resources>

<Style x:Key="PropertyTriggerExampleButtonStyle" TargetType="{x:Type Button}">

<Setter Property="Opacity" Value="0.25" />

<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">

<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To="1" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To="0.25" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>

<StackPanel Margin="20">

<Button Style="{StaticResource PropertyTriggerExampleButtonStyle}">


Move the mouse over me.
</Button>

</StackPanel>
</Page>

Las animaciones aplicadas por la propiedad Trigger se comportan los objetos en un modo más complejo que
EventTrigger animaciones o animaciones a usar Storyboard métodos. Se "continúan" con animaciones definida
por otros Trigger objetos, pero se crean con EventTrigger y animaciones activadas por métodos.

Vea también
Trigger
Información general sobre técnicas de animación de propiedades
Información general sobre objetos Storyboard
Procedimiento Usar desencadenadores de eventos
para controlar un guión gráfico después de su inicio
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo controlar Storyboard una después de iniciarse. Para iniciar Storyboard
XAMLmediante, use BeginStoryboard, que distribuye las animaciones a los objetos y propiedades que se animan
y, a continuación, inicia el guión gráfico. Si asigna BeginStoryboard un nombre mediante la especificación de su
Name propiedad, lo convierte en un guión gráfico controlable. Después, puede controlar interactivamente el
guión gráfico una vez que se inicia.
Use las siguientes acciones de guion gráfico EventTrigger junto con objetos para controlar un guion gráfico.
PauseStoryboard: Pausa el guion gráfico.
ResumeStoryboard: Reanuda un guion gráfico en pausa.
SetStoryboardSpeedRatio: Cambia la velocidad del guion gráfico.
SkipStoryboardToFill: Hace avanzar un guión gráfico hasta el final de su período de relleno, si tiene uno.
StopStoryboard: Detiene el guion gráfico.
RemoveStoryboard: Quita el guión gráfico, liberando recursos.

Ejemplo
En el ejemplo siguiente se usan acciones de guion gráfico controlables para controlar interactivamente un guión
gráfico.

NOTE
Para ver un ejemplo de cómo controlar un guión gráfico mediante código, vea controlar un guión gráfico después de
comenzar a usar sus métodos interactivos.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Controlling a Storyboard" >
<StackPanel Margin="20" >

<!-- This rectangle is animated. -->


<Rectangle Name="myRectangle"
Width="100" Height="20" Margin="12,0,0,5" Fill="#AA3333FF" HorizontalAlignment="Left" />

<!-- This StackPanel contains all the Buttons. -->


<StackPanel Orientation="Horizontal" Margin="0,30,0,0">

<Button Name="BeginButton">Begin</Button>
<Button Name="PauseButton">Pause</Button>
<Button Name="ResumeButton">Resume</Button>
<Button Name="SeekButton">Seek</Button>
<Button Name="SkipToFillButton">Skip To Fill</Button>
<Button Name="SetSpeedRatioButton">Triple Speed</Button>
<Button Name="StopButton">Stop</Button>

<StackPanel.Triggers>
<!-- Begin the Storyboard -->
<EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard >
<DoubleAnimation
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="Width"
Duration="0:0:5" From="100" To="500" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>

<!-- Pause the Storyboard -->


<EventTrigger RoutedEvent="Button.Click" SourceName="PauseButton">
<PauseStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>

<!-- Resume the Storyboard -->


<EventTrigger RoutedEvent="Button.Click" SourceName="ResumeButton">
<ResumeStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>

<!-- Seek one second into the storyboard's active period. -->
<EventTrigger RoutedEvent="Button.Click" SourceName="SeekButton">
<SeekStoryboard
BeginStoryboardName="MyBeginStoryboard"
Offset="0:0:1" Origin="BeginTime" />
</EventTrigger>

<!-- Skip to Fill -->


<EventTrigger RoutedEvent="Button.Click" SourceName="SkipToFillButton">
<SkipStoryboardToFill BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>

<!-- Stop the Storyboard -->


<EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
<StopStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>

<!-- Triple the speed of the Storyboard -->


<EventTrigger RoutedEvent="Button.Click" SourceName="SetSpeedRatioButton">
<SetStoryboardSpeedRatio SpeedRatio="3" BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>
</StackPanel>
</Page>

Para obtener más ejemplos, vea la Galería de ejemplo de animación.

Vea también
ResumeStoryboard
SetStoryboardSpeedRatio
SkipStoryboardToFill
PauseStoryboard
StopStoryboard
SeekStoryboard
Controlar un guión gráfico una vez iniciado usando métodos interactivos
Información general sobre animaciones
Información general sobre objetos Storyboard
Temas "Cómo..." de relojes
23/10/2019 • 2 minutes to read • Edit Online

Los temas siguientes describen cómo usar un Clock objeto para mantener la información de estado de tiempo
para un Timeline.

En esta sección
Animar una propiedad usando un objeto AnimationClock
Controlar interactivamente un reloj
Buscar un reloj de forma sincrónica

Referencia
Clock
Storyboard
System.Windows.Media.Animation
Timeline

Secciones relacionadas
Información general sobre animaciones
Información general sobre objetos Storyboard
Procedimiento Animar una propiedad mediante un
objeto AnimationClock
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo usar Clock objetos que se va a animar una propiedad.
Hay tres maneras de animar una propiedad de dependencia:
Crear un AnimationTimeline y asociarlo a esa propiedad mediante el uso de un Storyboard.
Utilice el objeto BeginAnimation método para aplicar una sola AnimationTimeline a una propiedad de
destino.
Crear un AnimationClock desde un AnimationTimeline y aplicarla a una propiedad.
Storyboard los objetos y el BeginAnimation método le permiten animar propiedades sin crear ni distribuir los
relojes directamente (para obtener ejemplos, vea animar una propiedad utilizando un guión gráfico y animar una
propiedad sin Utilizar un guión gráfico); los relojes se crean y distribuyen automáticamente.

Ejemplo
El ejemplo siguiente muestra cómo crear un AnimationClock y aplicarlo a dos propiedades similares.

/*
This example shows how to create and apply
an AnimationClock.
*/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{
public class AnimationClockExample : Page
{

ScaleTransform myScaleTransform;

public AnimationClockExample()
{

this.WindowTitle = "Opacity Animation Example";


this.Background = Brushes.White;
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(20);

// Create a button that with a ScaleTransform.


// The ScaleTransform will animate when the
// button is clicked.
Button myButton = new Button();
myButton.Margin = new Thickness(50);
myButton.HorizontalAlignment = HorizontalAlignment.Left;
myButton.Content = "Click Me";
myScaleTransform = new ScaleTransform(1,1);
myButton.RenderTransform = myScaleTransform;
myButton.RenderTransform = myScaleTransform;

// Associate an event handler with the


// button's Click event.
myButton.Click += new RoutedEventHandler(myButton_Clicked);

myStackPanel.Children.Add(myButton);
this.Content = myStackPanel;
}

// Create and apply and animation when the button is clicked.


private void myButton_Clicked(object sender, RoutedEventArgs e)
{

// Create a DoubleAnimation to animate the


// ScaleTransform.
DoubleAnimation myAnimation =
new DoubleAnimation(
1, // "From" value
5, // "To" value
new Duration(TimeSpan.FromSeconds(5))
);
myAnimation.AutoReverse = true;

// Create a clock the for the animation.


AnimationClock myClock = myAnimation.CreateClock();

// Associate the clock the ScaleX and


// ScaleY properties of the button's
// ScaleTransform.
myScaleTransform.ApplyAnimationClock(
ScaleTransform.ScaleXProperty, myClock);
myScaleTransform.ApplyAnimationClock(
ScaleTransform.ScaleYProperty, myClock);
}
}
}

'
' This example shows how to create and apply
' an AnimationClock.
'

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation

Namespace Microsoft.Samples.Animation.TimingBehaviors
Public Class AnimationClockExample
Inherits Page

Private ReadOnly myScaleTransform As ScaleTransform

Public Sub New()

WindowTitle = "Opacity Animation Example"


Background = Brushes.White
Dim myStackPanel As New StackPanel With {
.Margin = New Thickness(20)
}

' Create a button that with a ScaleTransform.


' The ScaleTransform will animate when the
' button is clicked.
' button is clicked.
Dim myButton As New Button With {
.Margin = New Thickness(50),
.HorizontalAlignment = HorizontalAlignment.Left,
.Content = "Click Me"
}
myScaleTransform = New ScaleTransform(1,1)
myButton.RenderTransform = myScaleTransform

' Associate an event handler with the


' button's Click event.
AddHandler myButton.Click, AddressOf myButton_Clicked

myStackPanel.Children.Add(myButton)
Content = myStackPanel
End Sub

' Create and apply and animation when the button is clicked.
Private Sub myButton_Clicked(sender As Object, e As RoutedEventArgs)

' Create a DoubleAnimation to animate the


' ScaleTransform.
Dim myAnimation As New DoubleAnimation(1, 5, New Duration(TimeSpan.FromSeconds(5))) With {
.AutoReverse = True
} ' "To" value - "From" value

' Create a clock the for the animation.


Dim myClock As AnimationClock = myAnimation.CreateClock()

' Associate the clock the ScaleX and


' ScaleY properties of the button's
' ScaleTransform.
myScaleTransform.ApplyAnimationClock(ScaleTransform.ScaleXProperty, myClock)
myScaleTransform.ApplyAnimationClock(ScaleTransform.ScaleYProperty, myClock)
End Sub
End Class
End Namespace

Para obtener un ejemplo que muestra cómo controlar interactivamente un Clock después de iniciarse, vea
controlar interactivamente un reloj.

Vea también
Animar una propiedad utilizando un guión gráfico
Animar una propiedad sin utilizar un guión gráfico
Información general sobre técnicas de animación de propiedades
Procedimiento Controlar interactivamente un reloj
23/10/2019 • 7 minutes to read • Edit Online

La Clock propiedad de ClockController un objeto permite iniciar, pausar, reanudar, buscar, avanzar el reloj hasta su
período de relleno y detener el reloj interactivamente. Solo se puede controlar interactivamente el reloj raíz de un
árbol de control de tiempo.

NOTE
Hay otras maneras de controlar interactivamente animaciones que no requieren que trabaje directamente con los relojes:
también puede usar guiones gráficos. Los guiones gráficos se admiten tanto en el marcado como en el código. Para obtener
un ejemplo, vea animar una propiedad mediante un guión gráfico o la información general sobre animaciones.

En el ejemplo siguiente, se usan varios botones para controlar interactivamente un reloj de animación.

Ejemplo
/*
This example shows how to interactively control
a root clock.
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{
public class ClockControllerExample : Page
{

private AnimationClock myControllableClock;


private Button seekButton;
private TextBox seekAmountTextBox;
private ListBox timeSeekOriginListBox;

public ClockControllerExample()
{
StackPanel mainPanel = new StackPanel();

// Create a rectangle to animate.


Rectangle animatedRectangle = new Rectangle();
animatedRectangle.Width = 100;
animatedRectangle.Height = 100;
animatedRectangle.Fill = Brushes.Orange;
mainPanel.Children.Add(animatedRectangle);

// Create a DoubleAnimation to
// animate its width.
DoubleAnimation widthAnimation =
new DoubleAnimation(
100,
500,
new Duration(TimeSpan.FromSeconds(5)));

// Create a clock from the animation.


myControllableClock = widthAnimation.CreateClock();

// Apply the clock to the rectangle's Width property.


animatedRectangle.ApplyAnimationClock(
Rectangle.WidthProperty, myControllableClock);
myControllableClock.Controller.Stop();

//
// Create some buttons to control the clock.
//

// Create a button to begin the clock.


Button beginButton = new Button();
beginButton.Content = "Begin";
beginButton.Click +=
new RoutedEventHandler(beginButton_Clicked);
mainPanel.Children.Add(beginButton);

// Create a button to pause the clock.


Button pauseButton = new Button();
pauseButton.Content = "Pause";
pauseButton.Click +=
new RoutedEventHandler(pauseButton_Clicked);
mainPanel.Children.Add(pauseButton);

// Create a button to resume the clock.


Button resumeButton = new Button();
resumeButton.Content = "Resume";
resumeButton.Click +=
new RoutedEventHandler(resumeButton_Clicked);
mainPanel.Children.Add(resumeButton);

// Create a button to advance the clock to


// its fill period.
Button skipToFillButton = new Button();
skipToFillButton.Content = "Skip to Fill";
skipToFillButton.Click +=
new RoutedEventHandler(skipToFillButton_Clicked);
mainPanel.Children.Add(skipToFillButton);

// Create a button to stop the clock.


Button stopButton = new Button();
stopButton.Content = "Stop";
stopButton.Click +=
new RoutedEventHandler(stopButton_Clicked);
mainPanel.Children.Add(stopButton);

//
// Create some controls the enable the user to
// seek the clock.
//

StackPanel seekDetailsPanel = new StackPanel();


seekDetailsPanel.Margin = new Thickness(0,20,0,20);
seekDetailsPanel.Orientation = Orientation.Horizontal;
Label seekAmountLabel = new Label();
seekAmountLabel.Content = "Seek amount:";
seekDetailsPanel.Children.Add(seekAmountLabel);

// Create a text box so that the user can


// specify the amount by which to seek.
seekAmountTextBox = new TextBox();
seekAmountTextBox.Text = "0:0:1";
seekAmountTextBox.VerticalAlignment = VerticalAlignment.Top;
seekAmountTextBox.TextChanged +=
new TextChangedEventHandler(seekAmountTextBox_TextChanged);
seekDetailsPanel.Children.Add(seekAmountTextBox);

Label timeSeekOriginLabel = new Label();


timeSeekOriginLabel.Content = "Seek Origin:";
seekDetailsPanel.Children.Add(timeSeekOriginLabel);

// Create a ListBox so the user can


// select whether the seek time is relative
// to the clock's BeginTime or Duration.
timeSeekOriginListBox = new ListBox();
timeSeekOriginListBox.Items.Add("BeginTime");
timeSeekOriginListBox.Items.Add("Duration");
timeSeekOriginListBox.Padding = new Thickness(5);
timeSeekOriginListBox.SelectedIndex = 0;
seekDetailsPanel.Children.Add(timeSeekOriginListBox);

// Create a button to seek the clock.


seekButton = new Button();
seekButton.Content = "Seek";
seekButton.Click += new RoutedEventHandler(seekButton_Clicked);
seekDetailsPanel.Children.Add(seekButton);
mainPanel.Children.Add(seekDetailsPanel);

this.Content = mainPanel;
}

// Starts the clock.


private void beginButton_Clicked(object sender, RoutedEventArgs e)
{
myControllableClock.Controller.Begin();
}

// Pauses the clock.


private void pauseButton_Clicked(object sender, RoutedEventArgs e)
{
myControllableClock.Controller.Pause();
}

// Resumes the clock.


private void resumeButton_Clicked(object sender, RoutedEventArgs e)
{
myControllableClock.Controller.Resume();
}

// Adances the clock to its fill period.


private void skipToFillButton_Clicked(object sender, RoutedEventArgs e)
{
myControllableClock.Controller.SkipToFill();
}

// Stops the clock.


private void stopButton_Clicked(object sender, RoutedEventArgs e)
{
myControllableClock.Controller.Stop();
}

// Seeks the clock.


private void seekButton_Clicked(object sender, RoutedEventArgs e)
{

try {

// Obtain the seek amount from the seekAmountTextBox TextBox.


TimeSpan seekAmount = TimeSpan.Parse(seekAmountTextBox.Text);

// Determine the seek origin by reading the selected value


// from the timeSeekOriginListBox ListBox.
TimeSeekOrigin selectedOrigin =
(TimeSeekOrigin)Enum.Parse(typeof(TimeSeekOrigin),
(string)timeSeekOriginListBox.SelectedItem);

// Seek to the specified location.


// Seek to the specified location.
myControllableClock.Controller.Seek(seekAmount, selectedOrigin);
}catch(FormatException formatEx)
{
MessageBox.Show(seekAmountTextBox.Text
+ " is not a valid TimeSpan. Please enter another value.");

// Disable the seek button until the user enters another value.
seekButton.IsEnabled = false;
}
}

// Verifies that seekAmountTextBox has text content.


// If there is no text, disable the seek button.
private void seekAmountTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox theTextBox = (TextBox)e.Source;
if (theTextBox.Text == null || theTextBox.Text.Length < 1)
seekButton.IsEnabled = false;
else
seekButton.IsEnabled = true;
}
}
}

'
' This example shows how to interactively control
' a root clock.
'

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation

Namespace Microsoft.Samples.Animation.TimingBehaviors
Public Class ClockControllerExample
Inherits Page

Private ReadOnly myControllableClock As AnimationClock


Private ReadOnly seekButton As Button
Private ReadOnly seekAmountTextBox As TextBox
Private ReadOnly timeSeekOriginListBox As ListBox

Public Sub New()


Dim mainPanel As New StackPanel()

' Create a rectangle to animate.


Dim animatedRectangle As New Rectangle With {
.Width = 100,
.Height = 100,
.Fill = Brushes.Orange
}
mainPanel.Children.Add(animatedRectangle)

' Create a DoubleAnimation to


' animate its width.
Dim widthAnimation As New DoubleAnimation(100, 500, New Duration(TimeSpan.FromSeconds(5)))

' Create a clock from the animation.


myControllableClock = widthAnimation.CreateClock()

' Apply the clock to the rectangle's Width property.


animatedRectangle.ApplyAnimationClock(Rectangle.WidthProperty, myControllableClock)
myControllableClock.Controller.Stop()

'
'
' Create some buttons to control the clock.
'

' Create a button to begin the clock.


Dim beginButton As New Button With {
.Content = "Begin"
}
AddHandler beginButton.Click, AddressOf beginButton_Clicked
mainPanel.Children.Add(beginButton)

' Create a button to pause the clock.


Dim pauseButton As New Button With {
.Content = "Pause"
}
AddHandler pauseButton.Click, AddressOf pauseButton_Clicked
mainPanel.Children.Add(pauseButton)

' Create a button to resume the clock.


Dim resumeButton As New Button With {
.Content = "Resume"
}
AddHandler resumeButton.Click, AddressOf resumeButton_Clicked
mainPanel.Children.Add(resumeButton)

' Create a button to advance the clock to


' its fill period.
Dim skipToFillButton As New Button With {
.Content = "Skip to Fill"
}
AddHandler skipToFillButton.Click, AddressOf skipToFillButton_Clicked
mainPanel.Children.Add(skipToFillButton)

' Create a button to stop the clock.


Dim stopButton As New Button With {
.Content = "Stop"
}
AddHandler stopButton.Click, AddressOf stopButton_Clicked
mainPanel.Children.Add(stopButton)

'
' Create some controls the enable the user to
' seek the clock.
'

Dim seekDetailsPanel As New StackPanel With {


.Margin = New Thickness(0, 20, 0, 20),
.Orientation = Orientation.Horizontal
}
Dim seekAmountLabel As New Label With {
.Content = "Seek amount:"
}
seekDetailsPanel.Children.Add(seekAmountLabel)

' Create a text box so that the user can


' specify the amount by which to seek.
seekAmountTextBox = New TextBox With {
.Text = "0:0:1",
.VerticalAlignment = VerticalAlignment.Top
}
AddHandler seekAmountTextBox.TextChanged, AddressOf seekAmountTextBox_TextChanged
seekDetailsPanel.Children.Add(seekAmountTextBox)

Dim timeSeekOriginLabel As New Label With {


.Content = "Seek Origin:"
}
seekDetailsPanel.Children.Add(timeSeekOriginLabel)

' Create a ListBox so the user can


' select whether the seek time is relative
' select whether the seek time is relative
' to the clock's BeginTime or Duration.
timeSeekOriginListBox = New ListBox()
timeSeekOriginListBox.Items.Add("BeginTime")
timeSeekOriginListBox.Items.Add("Duration")
timeSeekOriginListBox.Padding = New Thickness(5)
timeSeekOriginListBox.SelectedIndex = 0
seekDetailsPanel.Children.Add(timeSeekOriginListBox)

' Create a button to seek the clock.


seekButton = New Button With {
.Content = "Seek"
}
AddHandler seekButton.Click, AddressOf seekButton_Clicked
seekDetailsPanel.Children.Add(seekButton)
mainPanel.Children.Add(seekDetailsPanel)

Content = mainPanel
End Sub

' Starts the clock.


Private Sub beginButton_Clicked(sender As Object, e As RoutedEventArgs)
myControllableClock.Controller.Begin()
End Sub

' Pauses the clock.


Private Sub pauseButton_Clicked(sender As Object, e As RoutedEventArgs)
myControllableClock.Controller.Pause()
End Sub

' Resumes the clock.


Private Sub resumeButton_Clicked(sender As Object, e As RoutedEventArgs)
myControllableClock.Controller.Resume()
End Sub

' Adances the clock to its fill period.


Private Sub skipToFillButton_Clicked(sender As Object, e As RoutedEventArgs)
myControllableClock.Controller.SkipToFill()
End Sub

' Stops the clock.


Private Sub stopButton_Clicked(sender As Object, e As RoutedEventArgs)
myControllableClock.Controller.Stop()
End Sub

' Seeks the clock.


Private Sub seekButton_Clicked(sender As Object, e As RoutedEventArgs)

Try

' Obtain the seek amount from the seekAmountTextBox TextBox.


Dim seekAmount As TimeSpan = TimeSpan.Parse(seekAmountTextBox.Text)

' Determine the seek origin by reading the selected value


' from the timeSeekOriginListBox ListBox.
Dim selectedOrigin As TimeSeekOrigin = CType(System.Enum.Parse(GetType(TimeSeekOrigin),
CStr(timeSeekOriginListBox.SelectedItem)), TimeSeekOrigin)

' Seek to the specified location.


myControllableClock.Controller.Seek(seekAmount, selectedOrigin)

Catch formatEx As FormatException


MessageBox.Show(seekAmountTextBox.Text & " is not a valid TimeSpan. Please enter another
value.")

' Disable the seek button until the user enters another value.
seekButton.IsEnabled = False
End Try
End Sub
End Sub

' Verifies that seekAmountTextBox has text content.


' If there is no text, disable the seek button.
Private Sub seekAmountTextBox_TextChanged(sender As Object, e As TextChangedEventArgs)
Dim theTextBox As TextBox = CType(e.Source, TextBox)
If theTextBox.Text Is Nothing OrElse theTextBox.Text.Length < 1 Then
seekButton.IsEnabled = False
Else
seekButton.IsEnabled = True
End If

End Sub

End Class
End Namespace

Vea también
Animar una propiedad utilizando un guión gráfico
Información general sobre animaciones
Procedimiento Buscar un reloj de forma sincrónica
23/10/2019 • 7 minutes to read • Edit Online

Use el SeekAlignedToLastTick método para buscar un reloj de hasta un momento determinado de forma
sincrónica. En el ejemplo siguiente se muestra tanto el Seek y SeekAlignedToLastTick métodos de un
ClockController.
En este ejemplo se muestra cómo buscar un Clock; para obtener un ejemplo que muestra cómo buscar un guión
gráfico, vea buscar un guión gráfico de forma sincrónica .

Ejemplo
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data;
using System.Xml;
using System.Configuration;

namespace SDKSample
{
/// <summary>
/// Shows how to interactively control a clock.
/// </summary>

public class SeekAlignedToLastTickExample : Page


{

private AnimationClock myClock;


private TextBlock currentTimeIndicator;
private TextBox seekDestination;
private TextBlock rectangleWidthIndicator;
private Rectangle myRectangle;

public SeekAlignedToLastTickExample()
{

this.WindowTitle = "Controlling a Storyboard";


this.Background = Brushes.White;

StackPanel myStackPanel = new StackPanel();


myStackPanel.Margin = new Thickness(20);

// Create a rectangle.
myRectangle = new Rectangle();
myRectangle.Width = 100;
myRectangle.Height = 20;
myRectangle.Margin = new Thickness(12,0,0,5);
myRectangle.Fill = new SolidColorBrush(Color.FromArgb(170, 51, 51, 255));
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myStackPanel.Children.Add(myRectangle);

//
// Create an animation and a storyboard to animate the
// rectangle.
//
DoubleAnimation myDoubleAnimation =
DoubleAnimation myDoubleAnimation =
new DoubleAnimation(100, 500, new Duration(TimeSpan.FromSeconds(60)));
myClock = myDoubleAnimation.CreateClock();
myRectangle.ApplyAnimationClock(Rectangle.WidthProperty, myClock);
myClock.Controller.Stop();

//
// Create some buttons to control the storyboard
// and a panel to contain them.
//
StackPanel buttonPanel = new StackPanel();
buttonPanel.Orientation = Orientation.Horizontal;
Button beginButton = new Button();
beginButton.Content = "Begin";
beginButton.Click += new RoutedEventHandler(beginButton_Clicked);
buttonPanel.Children.Add(beginButton);
Button pauseButton = new Button();
pauseButton.Content = "Pause";
pauseButton.Click +=new RoutedEventHandler(pauseButton_Clicked);
buttonPanel.Children.Add(pauseButton);
Button resumeButton = new Button();
resumeButton.Content = "Resume";
resumeButton.Click +=new RoutedEventHandler(resumeButton_Clicked);
buttonPanel.Children.Add(resumeButton);
Button skipToFillButton = new Button();
skipToFillButton.Content = "Skip to Fill";
skipToFillButton.Click +=new RoutedEventHandler(skipToFillButton_Clicked);
buttonPanel.Children.Add(skipToFillButton);
Button setSpeedRatioButton = new Button();
setSpeedRatioButton.Content = "Triple Speed";
setSpeedRatioButton.Click +=new RoutedEventHandler(setSpeedRatioButton_Clicked);
buttonPanel.Children.Add(setSpeedRatioButton);
Button stopButton = new Button();
stopButton.Content = "Stop";
stopButton.Click +=new RoutedEventHandler(stopButton_Clicked);
buttonPanel.Children.Add(stopButton);
Button removeButton = new Button();
removeButton.Content = "Remove";
removeButton.Click +=new RoutedEventHandler(removeButton_Clicked);
buttonPanel.Children.Add(removeButton);

myStackPanel.Children.Add(buttonPanel);

// Create some controls to display the


// storyboard's current time and the
// current width of the rectangle.
StackPanel seekPanel = new StackPanel();
seekPanel.Margin = new Thickness(10);
StackPanel aPanel = new StackPanel();
Label aLabel = new Label();
aPanel.Orientation = Orientation.Horizontal;
aLabel.Content = "Current Time: ";
aPanel.Children.Add(aLabel);
currentTimeIndicator = new TextBlock();
aPanel.Children.Add(currentTimeIndicator);
seekPanel.Children.Add(aPanel);

aPanel = new StackPanel();


aPanel.Orientation = Orientation.Horizontal;
aLabel = new Label();
aLabel.Content = "Rectangle Width: ";
aPanel.Children.Add(aLabel);
rectangleWidthIndicator = new TextBlock();
rectangleWidthIndicator.Text = myRectangle.Width.ToString();
aPanel.Children.Add(rectangleWidthIndicator);
seekPanel.Children.Add(aPanel);

// Create some controls to enable the


// user to specify a seek position.
aPanel = new StackPanel();
aPanel.Orientation = Orientation.Horizontal;
aLabel = new Label();
aLabel.Content = "Seek Offset: " ;
aPanel.Children.Add(aLabel);
seekDestination = new TextBox();
seekDestination.Text = "0";
aPanel.Children.Add(seekDestination);
seekPanel.Children.Add(aPanel);

Button seekButton = new Button();


seekButton.Content = "Seek";
seekButton.Click += new RoutedEventHandler(seekButton_Clicked);
seekPanel.Children.Add(seekButton);
Button seekAlignedToLastTickButton = new Button();
seekAlignedToLastTickButton.Content = "Seek Aligned to Last Tick";
seekAlignedToLastTickButton.Click += new RoutedEventHandler(seekAlignedToLastTickButton_Clicked);
seekPanel.Children.Add(seekAlignedToLastTickButton);

myStackPanel.Children.Add(seekPanel);

this.Content = myStackPanel;

myClock.CurrentTimeInvalidated += new EventHandler(myClock_CurrentTimeInvalidated);


}

// Begins the clock.


private void beginButton_Clicked(object sender, RoutedEventArgs args)
{

myClock.Controller.Begin();
}

// Pauses the clock.


private void pauseButton_Clicked(object sender, RoutedEventArgs args)
{
myClock.Controller.Pause();
}

// Resumes the clock.


private void resumeButton_Clicked(object sender, RoutedEventArgs args)
{
myClock.Controller.Resume();
}

// Advances the clock to its fill period.


private void skipToFillButton_Clicked(object sender, RoutedEventArgs args)
{
myClock.Controller.SkipToFill();
}

// Updates the clock's speed.


private void setSpeedRatioButton_Clicked(object sender, RoutedEventArgs args)
{
// Makes the clock progress three times as fast as normal.
myClock.Controller.SpeedRatio = 3;
}

// Stops the clock.


private void stopButton_Clicked(object sender, RoutedEventArgs args)
{
myClock.Controller.Stop();
}

// Removes the clock.


private void removeButton_Clicked(object sender, RoutedEventArgs args)
{
myClock.Controller.Remove();
}

private void seekButton_Clicked(object sender, RoutedEventArgs args)


{
try {

// The rectangle width will probably not be at its new


// value when this call is made, because the
// clock probably hasn't ticked yet.
TimeSpan seekTime = TimeSpan.Parse(seekDestination.Text);
myClock.Controller.Seek(seekTime, TimeSeekOrigin.BeginTime);
rectangleWidthIndicator.Text = myRectangle.Width.ToString();
}catch(FormatException ex)
{
MessageBox.Show("Invalid TimeSpan value.");
seekDestination.Focus();
}
}

private void seekAlignedToLastTickButton_Clicked(object sender, RoutedEventArgs args)


{

try {

// The rectangle width will be at its new


// value when this call is made, because SeekAlignedToLastTick
// operation immediately updates timeline and animation
// values.
TimeSpan seekTime = TimeSpan.Parse(seekDestination.Text);
myClock.Controller.SeekAlignedToLastTick(seekTime, TimeSeekOrigin.BeginTime);
rectangleWidthIndicator.Text = myRectangle.Width.ToString();
}catch(FormatException ex)
{
MessageBox.Show("Invalid TimeSpan value.");
seekDestination.Focus();
}
}

private void myClock_CurrentTimeInvalidated(object sender, EventArgs e)


{

currentTimeIndicator.Text = myClock.CurrentTime.ToString();
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports System.Data
Imports System.Xml
Imports System.Configuration

Namespace SDKSample
''' <summary>
''' Shows how to interactively control a clock.
''' </summary>

Public Class SeekAlignedToLastTickExample


Inherits Page
Private myClock As AnimationClock
Private currentTimeIndicator As TextBlock
Private seekDestination As TextBox
Private rectangleWidthIndicator As TextBlock
Private myRectangle As Rectangle

Public Sub New()

Me.WindowTitle = "Controlling a Storyboard"


Me.Background = Brushes.White

Dim myStackPanel As New StackPanel()


myStackPanel.Margin = New Thickness(20)

' Create a rectangle.


myRectangle = New Rectangle()
With myRectangle
.Width = 100
.Height = 20
.Margin = New Thickness(12, 0, 0, 5)
.Fill = New SolidColorBrush(Color.FromArgb(170, 51, 51, 255))
.HorizontalAlignment = HorizontalAlignment.Left
End With
myStackPanel.Children.Add(myRectangle)

'
' Create an animation and a storyboard to animate the
' rectangle.
'
Dim myDoubleAnimation As New DoubleAnimation(100, 500, New Duration(TimeSpan.FromSeconds(60)))
myClock = myDoubleAnimation.CreateClock()
myRectangle.ApplyAnimationClock(Rectangle.WidthProperty, myClock)
myClock.Controller.Stop()

'
' Create some buttons to control the storyboard
' and a panel to contain them.
'
Dim buttonPanel As New StackPanel()
buttonPanel.Orientation = Orientation.Horizontal
Dim beginButton As New Button()
beginButton.Content = "Begin"
AddHandler beginButton.Click, AddressOf beginButton_Clicked
buttonPanel.Children.Add(beginButton)
Dim pauseButton As New Button()
pauseButton.Content = "Pause"
AddHandler pauseButton.Click, AddressOf pauseButton_Clicked
buttonPanel.Children.Add(pauseButton)
Dim resumeButton As New Button()
resumeButton.Content = "Resume"
AddHandler resumeButton.Click, AddressOf resumeButton_Clicked
buttonPanel.Children.Add(resumeButton)
Dim skipToFillButton As New Button()
skipToFillButton.Content = "Skip to Fill"
AddHandler skipToFillButton.Click, AddressOf skipToFillButton_Clicked
buttonPanel.Children.Add(skipToFillButton)
Dim setSpeedRatioButton As New Button()
setSpeedRatioButton.Content = "Triple Speed"
AddHandler setSpeedRatioButton.Click, AddressOf setSpeedRatioButton_Clicked
buttonPanel.Children.Add(setSpeedRatioButton)
Dim stopButton As New Button()
stopButton.Content = "Stop"
AddHandler stopButton.Click, AddressOf stopButton_Clicked
buttonPanel.Children.Add(stopButton)
Dim removeButton As New Button()
removeButton.Content = "Remove"
removeButton.Content = "Remove"
AddHandler removeButton.Click, AddressOf removeButton_Clicked
buttonPanel.Children.Add(removeButton)

myStackPanel.Children.Add(buttonPanel)

' Create some controls to display the


' storyboard's current time and the
' current width of the rectangle.
Dim seekPanel As New StackPanel()
seekPanel.Margin = New Thickness(10)
Dim aPanel As New StackPanel()
Dim aLabel As New Label()
aPanel.Orientation = Orientation.Horizontal
aLabel.Content = "Current Time: "
aPanel.Children.Add(aLabel)
currentTimeIndicator = New TextBlock()
aPanel.Children.Add(currentTimeIndicator)
seekPanel.Children.Add(aPanel)

aPanel = New StackPanel()


aPanel.Orientation = Orientation.Horizontal
aLabel = New Label()
aLabel.Content = "Rectangle Width: "
aPanel.Children.Add(aLabel)
rectangleWidthIndicator = New TextBlock()
rectangleWidthIndicator.Text = myRectangle.Width.ToString()
aPanel.Children.Add(rectangleWidthIndicator)
seekPanel.Children.Add(aPanel)

' Create some controls to enable the


' user to specify a seek position.

aPanel = New StackPanel()


aPanel.Orientation = Orientation.Horizontal
aLabel = New Label()
aLabel.Content = "Seek Offset: "
aPanel.Children.Add(aLabel)
seekDestination = New TextBox()
seekDestination.Text = "0"
aPanel.Children.Add(seekDestination)
seekPanel.Children.Add(aPanel)

Dim seekButton As New Button()


seekButton.Content = "Seek"
AddHandler seekButton.Click, AddressOf seekButton_Clicked
seekPanel.Children.Add(seekButton)
Dim seekAlignedToLastTickButton As New Button()
seekAlignedToLastTickButton.Content = "Seek Aligned to Last Tick"
AddHandler seekAlignedToLastTickButton.Click, AddressOf seekAlignedToLastTickButton_Clicked
seekPanel.Children.Add(seekAlignedToLastTickButton)

myStackPanel.Children.Add(seekPanel)

Me.Content = myStackPanel

AddHandler myClock.CurrentTimeInvalidated, AddressOf myClock_CurrentTimeInvalidated


End Sub

' Begins the clock.


Private Sub beginButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)

myClock.Controller.Begin()
End Sub

' Pauses the clock.


Private Sub pauseButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myClock.Controller.Pause()
myClock.Controller.Pause()

End Sub

' Resumes the clock.


Private Sub resumeButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myClock.Controller.Resume()

End Sub

' Advances the clock to its fill period.


Private Sub skipToFillButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myClock.Controller.SkipToFill()

End Sub

' Updates the clock's speed.


Private Sub setSpeedRatioButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
' Makes the clock progress three times as fast as normal.
myClock.Controller.SpeedRatio = 3

End Sub

' Stops the clock.


Private Sub stopButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myClock.Controller.Stop()

End Sub

' Removes the clock.


Private Sub removeButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myClock.Controller.Remove()

End Sub

Private Sub seekButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)


Try

' The rectangle width will probably not be at its new


' value when this call is made, because the
' clock probably hasn't ticked yet.
Dim seekTime As TimeSpan = TimeSpan.Parse(seekDestination.Text)
myClock.Controller.Seek(seekTime, TimeSeekOrigin.BeginTime)
rectangleWidthIndicator.Text = myRectangle.Width.ToString()

Catch ex As FormatException
MessageBox.Show("Invalid TimeSpan value.")
seekDestination.Focus()
End Try
End Sub

Private Sub seekAlignedToLastTickButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)

Try

' The rectangle width will be at its new


' value when this call is made, because SeekAlignedToLastTick
' operation immediately updates timeline and animation
' values.
Dim seekTime As TimeSpan = TimeSpan.Parse(seekDestination.Text)
myClock.Controller.SeekAlignedToLastTick(seekTime, TimeSeekOrigin.BeginTime)
rectangleWidthIndicator.Text = myRectangle.Width.ToString()

Catch ex As FormatException
MessageBox.Show("Invalid TimeSpan value.")
seekDestination.Focus()
End Try
End Sub

Private Sub myClock_CurrentTimeInvalidated(ByVal sender As Object, ByVal e As EventArgs)


Private Sub myClock_CurrentTimeInvalidated(ByVal sender As Object, ByVal e As EventArgs)

currentTimeIndicator.Text = myClock.CurrentTime.ToString()

End Sub

End Class
End Namespace
Temas "Cómo..." de animaciones de fotogramas
clave
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección muestran cómo usar animaciones de fotogramas clave para animar a más de dos
valores de propiedad y controlar la interpolación.

En esta sección
Animar un objeto mediante fotogramas clave
Animar un objeto Boolean mediante fotogramas clave
Animar un objeto Double mediante fotogramas clave
Animar un objeto Matrix mediante fotogramas clave
Animar un punto mediante fotogramas clave
Animar la geometría de un rectángulo mediante fotogramas clave
Animar un objeto String mediante fotogramas clave
Animar un color mediante fotogramas clave
Animar los cambios de tamaño mediante fotogramas clave
Animar el grosor de un borde mediante fotogramas clave
Controlar la temporización de animaciones de fotogramas clave

Referencia
DoubleAnimationUsingKeyFrames
Storyboard
KeyTime

Vea también
Gráficos y multimedia
Información general sobre animaciones
Información general sobre animaciones de fotogramas clave
Procedimiento Animar un objeto mediante
fotogramas clave
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo animar un objeto, que en este ejemplo Background es la propiedad Page de un
control, mediante fotogramas clave.

Ejemplo
En el ejemplo siguiente se ObjectAnimationUsingKeyFrames usa la clase para animar los Background cambios de
color Page de la propiedad de un control. La animación de ejemplo cambia a un pincel de fondo diferente a
intervalos regulares. Esta animación usa la DiscreteObjectKeyFrame clase para crear tres fotogramas clave
diferentes. La animación utiliza fotogramas clave de la siguiente manera:
1. Al final del primer segundo, anima una instancia de la LinearGradientBrush clase. En esta sección del
ejemplo se aplica un degradado lineal al color de fondo para que el color pase de amarillo a rojo.
2. Al final del siguiente segundo, anima una instancia de la RadialGradientBrush clase. En esta sección del
ejemplo se aplica un degradado radial al color de fondo para que el color pase de blanco a azul a negro.
3. Al final del tercer segundo, anima una instancia de la DrawingBrush clase. En esta sección del ejemplo se
aplica un patrón de tablero de ajedrez al fondo.
4. La animación comienza de nuevo y se repite indefinidamente.

NOTE
DiscreteObjectKeyFramees el único tipo de fotograma clave que se puede utilizar con ObjectAnimationUsingKeyFrames la
clase. Fotogramas DiscreteObjectKeyFrame clave, como crear cambios súbitos en valores, es decir, los cambios de color de
este ejemplo se producen repentinamente.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Page.Triggers>
<EventTrigger RoutedEvent="Page.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- ObjectAnimationUsingKeyFrames is used to animate properties that take


an object as a value. This animation lasts for 4 seconds using 3 KeyFrames which
swap different brush objects at regular intervals, making the background of the Page
change. -->
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="Background"
Duration="0:0:4" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames.KeyFrames>

<!-- Note: Only discrete interpolation (DiscreteObjectKeyFrame) is available for


use with ObjectAnimationUsingKeyFrames which merely swaps objects according to
a specified timeline. Other types of interpolation are too problematic to apply
to objects. -->

<!-- Using a DiscreteObjectKeyFrame, the Page Background suddenly changes


to a LinearGradientBrush after the first second of the animation. -->
to a LinearGradientBrush after the first second of the animation. -->
<DiscreteObjectKeyFrame KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Red" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>

<!-- Using a DiscreteObjectKeyFrame, the Page Background suddenly changes


to a RadialGradientBrush after the second second of the animation. -->
<DiscreteObjectKeyFrame KeyTime="0:0:2">
<DiscreteObjectKeyFrame.Value>
<RadialGradientBrush GradientOrigin="0.75,0.25">
<RadialGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0.0" />
<GradientStop Color="MediumBlue" Offset="0.5" />
<GradientStop Color="Black" Offset="1.0" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>

<!-- Using a DiscreteObjectKeyFrame, the Page Background suddenly


changes to a DrawingBrush (creates a checkerboard pattern) after the
third second of the animation. -->
<DiscreteObjectKeyFrame KeyTime="0:0:3">
<DiscreteObjectKeyFrame.Value>
<DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="Black"
Geometry="M 0,0 L0,0.5 0.5,0.5 0.5,1 1,1 1,0.5 0.5,0.5 0.5,0" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Page.Triggers>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.

Vea también
ObjectAnimationUsingKeyFrames
Background
Page
DiscreteObjectKeyFrame
LinearGradientBrush
RadialGradientBrush
DrawingBrush
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar un objeto Boolean mediante
fotogramas clave
23/10/2019 • 5 minutes to read • Edit Online

En este ejemplo se muestra cómo animar el valor de propiedad booleana de una Button control mediante
fotogramas clave.

Ejemplo
En el ejemplo siguiente se usa el BooleanAnimationUsingKeyFrames clase se va a animar el IsEnabled propiedad
de un Button control. Todos los fotogramas clave en este ejemplo utilizan una instancia de la
DiscreteBooleanKeyFrame clase. Los fotogramas clave discretos como DiscreteBooleanKeyFrame crean saltos
súbitos entre los valores, es decir, el movimiento de la animación es brusco.

// Demonstrates a BooleanAnimationUsingKeyFrames. The animation is used to


// animate the IsEnabled property of a button.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;

namespace Microsoft.Samples.KeyFrameExamples
{
public class BooleanAnimationUsingKeyFramesExample : Page
{
public BooleanAnimationUsingKeyFramesExample()
{
Title = "BooleanAnimationUsingKeyFrames Example";
Background = Brushes.White;
Margin = new Thickness(20);

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

StackPanel myStackPanel = new StackPanel();


myStackPanel.Orientation = Orientation.Vertical;
myStackPanel.Margin = new Thickness(20);

// Create a TextBlock to introduce the example.


TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Click the button to animate its IsEnabled property"
+ " with aBooleanAnimationUsingKeyFrames animation.";
myStackPanel.Children.Add(myTextBlock);

// Create the Button that is the target of the animation.


Button myButton = new Button();
myButton.Margin = new Thickness(200);
myButton.Content = "Click Me";

myStackPanel.Children.Add(myButton);

// Assign the Button a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"AnimatedButton", myButton);
// Create a BooleanAnimationUsingKeyFrames to
// animate the IsEnabled property of the Button.
BooleanAnimationUsingKeyFrames booleanAnimation
= new BooleanAnimationUsingKeyFrames();
booleanAnimation.Duration = TimeSpan.FromSeconds(4);

// All the key frames defined below are DiscreteBooleanKeyFrames.


// Discrete key frames create sudden "jumps" between values
// (no interpolation). Only discrete key frames can be used
// for Boolean key frame animations.

// Value at the beginning is false


booleanAnimation.KeyFrames.Add(
new DiscreteBooleanKeyFrame(
false, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.0))) // KeyTime
);

// Value becomes true after the first second.


booleanAnimation.KeyFrames.Add(
new DiscreteBooleanKeyFrame(
true, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1.0))) // KeyTime
);

// Value becomes false after the 2nd second.


booleanAnimation.KeyFrames.Add(
new DiscreteBooleanKeyFrame(
false, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.0))) // KeyTime
);

// Value becomes true after the third second.


booleanAnimation.KeyFrames.Add(
new DiscreteBooleanKeyFrame(
true, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3.0))) // KeyTime
);

// Value becomes false after 3 and half seconds.


booleanAnimation.KeyFrames.Add(
new DiscreteBooleanKeyFrame(
false, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3.5))) // KeyTime
);

// Value becomes true after the fourth second.


booleanAnimation.KeyFrames.Add(
new DiscreteBooleanKeyFrame(
true, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4.0))) // KeyTime
);

// Set the animation to target the IsEnabled property


// of the object named "AnimatedButton".
Storyboard.SetTargetName(booleanAnimation, "AnimatedButton");
Storyboard.SetTargetProperty(
booleanAnimation, new PropertyPath(Button.IsEnabledProperty));

// Create a storyboard to apply the animation.


Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(booleanAnimation);

// Start the storyboard when the button is clicked.


myButton.Click += delegate(object sender, RoutedEventArgs e)
{
myStoryboard.Begin(this);
};
Content = myStackPanel;
}
}
}

' Demonstrates a BooleanAnimationUsingKeyFrames. The animation is used to


' animate the IsEnabled property of a button.

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation
Imports System.Windows.Media

Namespace Microsoft.Samples.KeyFrameExamples
Public Class BooleanAnimationUsingKeyFramesExample
Inherits Page
Public Sub New()
Title = "BooleanAnimationUsingKeyFrames Example"
Background = Brushes.White
Margin = New Thickness(20)

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myStackPanel As New StackPanel()


myStackPanel.Orientation = Orientation.Vertical
myStackPanel.Margin = New Thickness(20)

' Create a TextBlock to introduce the example.


Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Click the button to animate its IsEnabled property" & " with
aBooleanAnimationUsingKeyFrames animation."
myStackPanel.Children.Add(myTextBlock)

' Create the Button that is the target of the animation.


Dim myButton As New Button()
myButton.Margin = New Thickness(200)
myButton.Content = "Click Me"

myStackPanel.Children.Add(myButton)

' Assign the Button a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("AnimatedButton", myButton)

' Create a BooleanAnimationUsingKeyFrames to


' animate the IsEnabled property of the Button.
Dim booleanAnimation As New BooleanAnimationUsingKeyFrames()
booleanAnimation.Duration = TimeSpan.FromSeconds(4)

' All the key frames defined below are DiscreteBooleanKeyFrames.


' Discrete key frames create sudden "jumps" between values
' (no interpolation). Only discrete key frames can be used
' for Boolean key frame animations.

' Value at the beginning is false


booleanAnimation.KeyFrames.Add(New DiscreteBooleanKeyFrame(False,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.0)))) ' KeyTime - Target value (KeyValue)

' Value becomes true after the first second.


booleanAnimation.KeyFrames.Add(New DiscreteBooleanKeyFrame(True,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1.0)))) ' KeyTime - Target value (KeyValue)
' Value becomes false after the 2nd second.
booleanAnimation.KeyFrames.Add(New DiscreteBooleanKeyFrame(False,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.0)))) ' KeyTime - Target value (KeyValue)

' Value becomes true after the third second.


booleanAnimation.KeyFrames.Add(New DiscreteBooleanKeyFrame(True,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3.0)))) ' KeyTime - Target value (KeyValue)

' Value becomes false after 3 and half seconds.


booleanAnimation.KeyFrames.Add(New DiscreteBooleanKeyFrame(False,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3.5)))) ' KeyTime - Target value (KeyValue)

' Value becomes true after the fourth second.


booleanAnimation.KeyFrames.Add(New DiscreteBooleanKeyFrame(True,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4.0)))) ' KeyTime - Target value (KeyValue)

' Set the animation to target the IsEnabled property


' of the object named "AnimatedButton".
Storyboard.SetTargetName(booleanAnimation, "AnimatedButton")
Storyboard.SetTargetProperty(booleanAnimation, New PropertyPath(Button.IsEnabledProperty))

' Create a storyboard to apply the animation.


Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(booleanAnimation)

' Start the storyboard when the button is clicked.


AddHandler myButton.Click, Sub(sender As Object, e As RoutedEventArgs) myStoryboard.Begin(Me)

Content = myStackPanel
End Sub

End Class
End Namespace
<!-- Demonstrates a BooleanAnimationUsingKeyFrames. The animation is used to
animate the IsEnabled property of a button. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="KeyFrameBoolean Animation Example">

<StackPanel Orientation="Vertical" Margin="20">

<TextBlock>
Click the button to animate its IsEnabled property with a
BooleanAnimationUsingKeyFrames animation.
</TextBlock>

<Button Name="myAnimatedButton" Margin="200">Click Me


<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetName="myAnimatedButton"
Storyboard.TargetProperty="IsEnabled"
Duration="0:0:4" FillBehavior="HoldEnd">

<!-- All the key frames below are DiscreteBooleanKeyFrames. Discrete key frames create
sudden "jumps" between values (no interpolation). Only discrete key frames can be used
for Boolean key frame animations. -->
<DiscreteBooleanKeyFrame Value="False" KeyTime="0:0:0" />
<DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:1" />
<DiscreteBooleanKeyFrame Value="False" KeyTime="0:0:2" />
<DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:3" />
<DiscreteBooleanKeyFrame Value="False" KeyTime="0:0:3.5" />
<DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:4" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.

Vea también
BooleanAnimationUsingKeyFrames
IsEnabled
Button
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar un objeto Double mediante
fotogramas clave
23/10/2019 • 7 minutes to read • Edit Online

En este ejemplo se muestra cómo animar el valor de una propiedad que toma un Double mediante fotogramas
clave.

Ejemplo
En el ejemplo siguiente se mueve un rectángulo por una pantalla. El ejemplo se usa el
DoubleAnimationUsingKeyFrames clase se va a animar el X propiedad de un TranslateTransform aplicado a un
Rectangle. Esta animación, que se repite indefinidamente, utiliza tres fotogramas clave de la manera siguiente:
1. Durante los primeros tres segundos, utiliza una instancia de la LinearDoubleKeyFrame clase para mover el
rectángulo a lo largo de una ruta de acceso a un ritmo constante desde su posición inicial hasta la posición
500. Los fotogramas clave lineales como LinearDoubleKeyFrame crean una transición lineal suave entre
valores.
2. Al final del cuarto segundo, utiliza una instancia de la DiscreteDoubleKeyFrame clase para mover el
rectángulo a la posición siguiente. Los fotogramas clave discretos como DiscreteDoubleKeyFrame crean
saltos súbitos entre los valores. En este ejemplo, el rectángulo está en la posición inicial y aparece de pronto
en la posición 500.
3. En los dos últimos segundos, utiliza una instancia de la SplineDoubleKeyFrame clase para devolver el
rectángulo a su posición inicial. Los fotogramas clave spline como SplineDoubleKeyFrame crean una
transición variable entre los valores según el valor de la KeySpline propiedad. En este ejemplo, el rectángulo
comienza a moverse despacio y se acelera exponencialmente hacia el final del segmento temporal.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;

namespace Microsoft.Samples.KeyFrameExamples
{
/// <summary>
/// This example shows how to use the DoubleAnimationUsingKeyFrames class to
/// animate the position of an object.
/// Key frame animations enable you to create complex animations
/// by specifying multiple destination values
/// and controlling the animation's interpolation method.
/// </summary>
public class AltDoubleAnimationUsingKeyFramesExample : Page
{
public AltDoubleAnimationUsingKeyFramesExample()
{
Title = "DoubleAnimationUsingKeyFrames Example";
Background = Brushes.White;
Margin = new Thickness(20);

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());
// Create a rectangle.
Rectangle aRectangle = new Rectangle();
aRectangle.Width = 100;
aRectangle.Height = 100;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 5;

// Create a Canvas to contain and


// position the rectangle.
Canvas containerCanvas = new Canvas();
containerCanvas.Width = 610;
containerCanvas.Height = 300;
containerCanvas.Children.Add(aRectangle);
Canvas.SetTop(aRectangle, 100);
Canvas.SetLeft(aRectangle, 10);

// Create a TranslateTransform to
// move the rectangle.
TranslateTransform animatedTranslateTransform =
new TranslateTransform();
aRectangle.RenderTransform = animatedTranslateTransform;

// Assign the TranslateTransform a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"AnimatedTranslateTransform", animatedTranslateTransform);

// Create a DoubleAnimationUsingKeyFrames to
// animate the TranslateTransform.
DoubleAnimationUsingKeyFrames translationAnimation
= new DoubleAnimationUsingKeyFrames();
translationAnimation.Duration = TimeSpan.FromSeconds(6);

// Animate from the starting position to 500


// over the first second using linear
// interpolation.
translationAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(
500, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3))) // KeyTime
);

// Animate from 500 (the value of the previous key frame)


// to 400 at 4 seconds using discrete interpolation.
// Because the interpolation is discrete, the rectangle will appear
// to "jump" from 500 to 400.
translationAnimation.KeyFrames.Add(
new DiscreteDoubleKeyFrame(
400, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4))) // KeyTime
);

// Animate from 400 (the value of the previous key frame) to 0


// over two seconds, starting at 4 seconds (the key time of the
// last key frame) and ending at 6 seconds.
translationAnimation.KeyFrames.Add(
new SplineDoubleKeyFrame(
0, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(6)), // KeyTime
new KeySpline(0.6,0.0,0.9,0.0) // KeySpline
)
);

// Set the animation to repeat forever.


translationAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the animation to target the X property


// of the object named "AnimatedTranslateTransform."
Storyboard.SetTargetName(translationAnimation, "AnimatedTranslateTransform");
Storyboard.SetTargetName(translationAnimation, "AnimatedTranslateTransform");
Storyboard.SetTargetProperty(
translationAnimation, new PropertyPath(TranslateTransform.XProperty));

// Create a storyboard to apply the animation.


Storyboard translationStoryboard = new Storyboard();
translationStoryboard.Children.Add(translationAnimation);

// Start the storyboard after the rectangle loads.


aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
translationStoryboard.Begin(this);
};

Content = containerCanvas;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation
Imports System.Windows.Media

Namespace Microsoft.Samples.KeyFrameExamples
''' <summary>
''' This example shows how to use the DoubleAnimationUsingKeyFrames class to
''' animate the position of an object.
''' Key frame animations enable you to create complex animations
''' by specifying multiple destination values
''' and controlling the animation's interpolation method.
''' </summary>
Public Class AltDoubleAnimationUsingKeyFramesExample
Inherits Page
Public Sub New()
Title = "DoubleAnimationUsingKeyFrames Example"
Background = Brushes.White
Margin = New Thickness(20)

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

' Create a rectangle.


Dim aRectangle As New Rectangle()
aRectangle.Width = 100
aRectangle.Height = 100
aRectangle.Stroke = Brushes.Black
aRectangle.StrokeThickness = 5

' Create a Canvas to contain and


' position the rectangle.
Dim containerCanvas As New Canvas()
containerCanvas.Width = 610
containerCanvas.Height = 300
containerCanvas.Children.Add(aRectangle)
Canvas.SetTop(aRectangle, 100)
Canvas.SetLeft(aRectangle, 10)

' Create a TranslateTransform to


' move the rectangle.
Dim animatedTranslateTransform As New TranslateTransform()
aRectangle.RenderTransform = animatedTranslateTransform

' Assign the TranslateTransform a name so that


' it can be targeted by a Storyboard.
' it can be targeted by a Storyboard.
Me.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform)

' Create a DoubleAnimationUsingKeyFrames to


' animate the TranslateTransform.
Dim translationAnimation As New DoubleAnimationUsingKeyFrames()
translationAnimation.Duration = TimeSpan.FromSeconds(6)

' Animate from the starting position to 500


' over the first second using linear
' interpolation.
translationAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(500,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3)))) ' KeyTime - Target value (KeyValue)

' Animate from 500 (the value of the previous key frame)
' to 400 at 4 seconds using discrete interpolation.
' Because the interpolation is discrete, the rectangle will appear
' to "jump" from 500 to 400.
translationAnimation.KeyFrames.Add(New DiscreteDoubleKeyFrame(400,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4)))) ' KeyTime - Target value (KeyValue)

' Animate from 400 (the value of the previous key frame) to 0
' over two seconds, starting at 4 seconds (the key time of the
' last key frame) and ending at 6 seconds.
translationAnimation.KeyFrames.Add(New SplineDoubleKeyFrame(0,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(6)), New KeySpline(0.6,0.0,0.9,0.0))) ' KeySpline - KeyTime -
Target value (KeyValue)

' Set the animation to repeat forever.


translationAnimation.RepeatBehavior = RepeatBehavior.Forever

' Set the animation to target the X property


' of the object named "AnimatedTranslateTransform."
Storyboard.SetTargetName(translationAnimation, "AnimatedTranslateTransform")
Storyboard.SetTargetProperty(translationAnimation, New PropertyPath(TranslateTransform.XProperty))

' Create a storyboard to apply the animation.


Dim translationStoryboard As New Storyboard()
translationStoryboard.Children.Add(translationAnimation)

' Start the storyboard after the rectangle loads.


AddHandler aRectangle.Loaded, Sub(sender As Object, e As RoutedEventArgs)
translationStoryboard.Begin(Me)

Content = containerCanvas
End Sub

End Class
End Namespace
<!-- This example shows how to use the DoubleAnimationUsingKeyFrames to
animate the position of an object.
Key frame animations enable you to create complex animations
by specifying multiple destination values
and controlling the animation's interpolation method.
-->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DoubleAnimationUsingKeyFrames Example"
Background="White" Margin="20">
<Canvas Width="610" Height="300">

<!-- The position of this rectangle is animated using


a key frame animation. -->
<Rectangle
Canvas.Top="100"
Canvas.Left="10"
Height="100"
Width="100"
Stroke="Black"
StrokeThickness="5">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="AnimatedTranslateTransform" />
</Rectangle.RenderTransform>

<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- Animate the TranslateTransform.X property using 3 KeyFrames


which animates the rectangle along a straight line.
This animation repeats indefinitely. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="X"
Duration="0:0:6"
RepeatBehavior="Forever">

<!-- Using a LinearDoubleKeyFrame, the rectangle moves


steadily from its starting position to 500 over
the first 3 seconds. -->
<LinearDoubleKeyFrame Value="500" KeyTime="0:0:3" />

<!-- Using a DiscreteDoubleKeyFrame, the rectangle suddenly


appears at 400 after the fourth second of the animation. -->
<DiscreteDoubleKeyFrame Value="400" KeyTime="0:0:4" />

<!-- Using a SplineDoubleKeyFrame, the rectangle moves


back to its starting point. The
animation starts out slowly at first and then speeds up.
This KeyFrame ends after the 6th
second. -->
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0" KeyTime="0:0:6" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.
Para mantener la coherencia con otros ejemplos de animación, las versiones de código de este ejemplo utiliza un
Storyboard objeto al que aplicar el DoubleAnimationUsingKeyFrames. Como alternativa, al aplicar una animación
única en código, es más fácil de usar el BeginAnimation método en lugar de usar un Storyboard. Para obtener un
ejemplo, vea Animar una propiedad sin utilizar un guión gráfico.

Vea también
DoubleAnimationUsingKeyFrames
Rectangle
LinearDoubleKeyFrame
DiscreteDoubleKeyFrame
SplineDoubleKeyFrame
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar un objeto Matrix mediante
fotogramas clave
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo animar la Matrix propiedad de una MatrixTransform mediante fotogramas clave.

Ejemplo
En el ejemplo siguiente se MatrixAnimationUsingKeyFrames usa la clase para Matrix animar la
MatrixTransformpropiedad de un. En el ejemplo se MatrixTransform usa el objeto para transformar la apariencia y
la Buttonposición de.
Esta animación usa la DiscreteMatrixKeyFrame clase para crear dos fotogramas clave y hace lo siguiente con ellos:
1. Anima la primera Matrix durante los primeros 0,2 segundos. En el ejemplo se M11 cambian M12 las
propiedades y Matrixde. Este cambio hace que el botón se estire y se convierta en sesgado. En el ejemplo
también se OffsetX cambian OffsetY las propiedades y para que el botón cambie de posición.
2. Anima el segundo Matrix a 1,0 segundos. El botón se mueve a otra posición mientras el botón deja de
sesgarse o ajustarse.
3. Repite la animación indefinidamente.

NOTE
Los fotogramas clave que DiscreteMatrixKeyFrame se derivan del objeto crean saltos súbitos entre los valores, es decir, el
movimiento de la animación es entrecortado.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MatrixAnimationUsingPath Example">
<StackPanel Margin="20">
<Canvas HorizontalAlignment="Left" Width="340" Height="240" >

<!-- The Button that is animated. -->


<Button Margin="-30,0,0,0" MinWidth="100">
Click
<Button.RenderTransform>
<MatrixTransform x:Name="myMatrixTransform">
<MatrixTransform.Matrix >
<Matrix OffsetX="10" OffsetY="100"/>
</MatrixTransform.Matrix>
</MatrixTransform>
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- Animates the button's MatrixTransform using MatrixAnimationUsingKeyFrames.


Animates to first Matrix in the first 0.2 seconds, to second Matrix in the next
second, and then starts over. Notice that the first KeyFrame stretches the button
and skews it using the M11 and M12 Matrix properties respectively. Also, animations are
using Discrete interpolation, so the MatrixTransform appears to "jump" from one value
to the next. -->
<MatrixAnimationUsingKeyFrames
Storyboard.TargetName="myMatrixTransform"
Storyboard.TargetProperty="Matrix"
Duration="0:0:3"
RepeatBehavior="Forever">
<DiscreteMatrixKeyFrame KeyTime="0:0:0.2">
<DiscreteMatrixKeyFrame.Value>
<Matrix OffsetX="100" OffsetY="200" M11="3" M12="1" />
</DiscreteMatrixKeyFrame.Value>
</DiscreteMatrixKeyFrame>
<DiscreteMatrixKeyFrame KeyTime="0:0:1">
<DiscreteMatrixKeyFrame.Value>
<Matrix OffsetX="300" OffsetY="100" M11="1" M12="0" />
</DiscreteMatrixKeyFrame.Value>
</DiscreteMatrixKeyFrame>
</MatrixAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>

</Button.Triggers>
</Button>

</Canvas>
</StackPanel>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.

Vea también
Matrix
MatrixTransform
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar un punto mediante
fotogramas clave
23/10/2019 • 6 minutes to read • Edit Online

En este ejemplo se muestra cómo usar el PointAnimationUsingKeyFrames clase para animar un Point.

Ejemplo
En el ejemplo siguiente se mueve una elipse a lo largo de un trazado triangular. El ejemplo se usa el
PointAnimationUsingKeyFrames clase se va a animar el Center propiedad de un EllipseGeometry. Esta animación
utiliza tres fotogramas clave de la siguiente manera:
1. Durante el primer medio segundo, utiliza una instancia de la LinearPointKeyFrame clase para mover la
elipse a lo largo de una ruta de acceso a un ritmo constante desde su posición inicial. Los fotogramas clave
lineales como LinearPointKeyFrame crean una interpolación lineal suave entre valores.
2. Durante el fin de la siguiente medio segundo, utiliza una instancia de la DiscretePointKeyFrame clase para
mover repentinamente la elipse a lo largo de la ruta de acceso a la siguiente posición. Los fotogramas clave
discretos como DiscretePointKeyFrame crean saltos súbitos entre los valores.
3. Durante los dos últimos segundos, utiliza una instancia de la SplinePointKeyFrame clase para devolver la
elipse a su posición inicial. Los fotogramas clave spline como SplinePointKeyFrame crean una transición
variable entre los valores según los valores de la KeySpline propiedad. En este ejemplo, la animación
comienza despacio y se acelera exponencialmente hacia el final del segmento temporal.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;

namespace Microsoft.Samples.KeyFrameExamples
{
/// <summary>
/// This example shows how to use the PointAnimationUsingKeyFrames class
/// to animate the position of an object.
/// </summary>
public class PointAnimationUsingKeyFramesExample : Page
{
public PointAnimationUsingKeyFramesExample()
{
Title = "PointAnimationUsingKeyFrames Example";
Background = Brushes.White;
Margin = new Thickness(20);

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

// Create an EllipseGeometry.
EllipseGeometry myAnimatedEllipseGeometry =
new EllipseGeometry(new Point(200,100), 15, 15);

// Assign the EllipseGeometry a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
this.RegisterName(
"MyAnimatedEllipseGeometry", myAnimatedEllipseGeometry);

// Create a Path element to display the geometry.


Path aPath = new Path();
aPath.Fill = Brushes.Blue;
aPath.Data = myAnimatedEllipseGeometry;

// Create a Canvas to contain the path.


Canvas containerCanvas = new Canvas();
containerCanvas.Width = 500;
containerCanvas.Height = 400;
containerCanvas.Children.Add(aPath);

// Create a PointAnimationUsingKeyFrames to
// animate the EllipseGeometry.
PointAnimationUsingKeyFrames centerPointAnimation
= new PointAnimationUsingKeyFrames();
centerPointAnimation.Duration = TimeSpan.FromSeconds(5);

// Animate from the starting position to (100,300)


// over the first half-second using linear
// interpolation.
centerPointAnimation.KeyFrames.Add(
new LinearPointKeyFrame(
new Point(100, 300), // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5))) // KeyTime
);

// Animate from (100,300) (the value of the previous key frame)


// to (400,300) at 1 second using discrete interpolation.
// Because the interpolation is discrete, the ellipse will appear
// to "jump" to (400,300) at 1 second.
centerPointAnimation.KeyFrames.Add(
new DiscretePointKeyFrame(
new Point(400, 300), // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))) // KeyTime
);

// Animate from (400,300) (the value of the previous key frame) to (200,100)
// over two seconds, starting at 1 second (the key time of the
// last key frame) and ending at 3 seconds.
centerPointAnimation.KeyFrames.Add(
new SplinePointKeyFrame(
new Point(200, 100), // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3)), // KeyTime
new KeySpline(0.6, 0.0, 0.9, 0.0) // KeySpline
)
);

// Set the animation to repeat forever.


centerPointAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the animation to target the Center property


// of the object named "MyAnimatedEllipseGeometry".
Storyboard.SetTargetName(centerPointAnimation, "MyAnimatedEllipseGeometry");
Storyboard.SetTargetProperty(
centerPointAnimation, new PropertyPath(EllipseGeometry.CenterProperty));

// Create a storyboard to apply the animation.


Storyboard ellipseStoryboard = new Storyboard();
ellipseStoryboard.Children.Add(centerPointAnimation);

// Start the storyboard when the Path loads.


aPath.Loaded += delegate(object sender, RoutedEventArgs e)
{
ellipseStoryboard.Begin(this);
};

Content = containerCanvas;
Content = containerCanvas;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation
Imports System.Windows.Media

Namespace Microsoft.Samples.KeyFrameExamples
''' <summary>
''' This example shows how to use the PointAnimationUsingKeyFrames class
''' to animate the position of an object.
''' </summary>
Public Class PointAnimationUsingKeyFramesExample
Inherits Page
Public Sub New()
Title = "PointAnimationUsingKeyFrames Example"
Background = Brushes.White
Margin = New Thickness(20)

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

' Create an EllipseGeometry.


Dim myAnimatedEllipseGeometry As New EllipseGeometry(New Point(200,100), 15, 15)

' Assign the EllipseGeometry a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("MyAnimatedEllipseGeometry", myAnimatedEllipseGeometry)

' Create a Path element to display the geometry.


Dim aPath As New Path()
aPath.Fill = Brushes.Blue
aPath.Data = myAnimatedEllipseGeometry

' Create a Canvas to contain the path.


Dim containerCanvas As New Canvas()
containerCanvas.Width = 500
containerCanvas.Height = 400
containerCanvas.Children.Add(aPath)

' Create a PointAnimationUsingKeyFrames to


' animate the EllipseGeometry.
Dim centerPointAnimation As New PointAnimationUsingKeyFrames()
centerPointAnimation.Duration = TimeSpan.FromSeconds(5)

' Animate from the starting position to (100,300)


' over the first half-second using linear
' interpolation.
centerPointAnimation.KeyFrames.Add(New LinearPointKeyFrame(New Point(100, 300),
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5)))) ' KeyTime - Target value (KeyValue)

' Animate from (100,300) (the value of the previous key frame)
' to (400,300) at 1 second using discrete interpolation.
' Because the interpolation is discrete, the ellipse will appear
' to "jump" to (400,300) at 1 second.
centerPointAnimation.KeyFrames.Add(New DiscretePointKeyFrame(New Point(400, 300),
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)))) ' KeyTime - Target value (KeyValue)

' Animate from (400,300) (the value of the previous key frame) to (200,100)
' over two seconds, starting at 1 second (the key time of the
' last key frame) and ending at 3 seconds.
centerPointAnimation.KeyFrames.Add(New SplinePointKeyFrame(New Point(200, 100),
centerPointAnimation.KeyFrames.Add(New SplinePointKeyFrame(New Point(200, 100),
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3)), New KeySpline(0.6, 0.0, 0.9, 0.0))) ' KeySpline - KeyTime -
Target value (KeyValue)

' Set the animation to repeat forever.


centerPointAnimation.RepeatBehavior = RepeatBehavior.Forever

' Set the animation to target the Center property


' of the object named "MyAnimatedEllipseGeometry".
Storyboard.SetTargetName(centerPointAnimation, "MyAnimatedEllipseGeometry")
Storyboard.SetTargetProperty(centerPointAnimation, New
PropertyPath(EllipseGeometry.CenterProperty))

' Create a storyboard to apply the animation.


Dim ellipseStoryboard As New Storyboard()
ellipseStoryboard.Children.Add(centerPointAnimation)

' Start the storyboard when the Path loads.


AddHandler aPath.Loaded, Sub(sender As Object, e As RoutedEventArgs) ellipseStoryboard.Begin(Me)

Content = containerCanvas
End Sub

End Class
End Namespace
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="White" Margin="20">
<Canvas Width="400" Height="400">
<Path Fill="Blue">
<Path.Data>

<!-- Describes an ellipse. -->


<EllipseGeometry x:Name="MyAnimatedEllipseGeometry"
Center="200,100" RadiusX="15" RadiusY="15" />
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- Animating the Center property uses 3 KeyFrames, which animate


the ellipse allong a triangular path. -->
<PointAnimationUsingKeyFrames
Storyboard.TargetProperty="Center"
Storyboard.TargetName="MyAnimatedEllipseGeometry"
Duration="0:0:5" RepeatBehavior="Forever">

<!-- Over the first half second, Using a LinearPointKeyFrame, the ellipse
moves steadily from its starting position along the first line of the
trianglar path. -->
<LinearPointKeyFrame
KeyTime="0:0:0.5"
Value="100,300" />

<!-- Using a DiscretePointKeyFrame, the ellipse suddenly changes position


after the first second of the animation. -->
<DiscretePointKeyFrame
KeyTime="0:0:1"
Value="400,300" />

<!-- Using a SplinePointKeyFrame, the ellipse moves back to its starting


position. It moves slowly at first and then speeds up. This key frame
takes 2 seconds to complete. -->
<SplinePointKeyFrame
KeySpline="0.6,0.0 0.9,0.00"
KeyTime="0:0:3"
Value="200,100" />
</PointAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Canvas>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.
Para mantener la coherencia con otros ejemplos de animación, las versiones de código de este ejemplo utiliza un
Storyboard objeto al que aplicar el PointAnimationUsingKeyFrames. Sin embargo, al aplicar una animación única
en código, resulta más fácil de usar el BeginAnimation método en lugar de usar un Storyboard. Para obtener un
ejemplo, vea Animar una propiedad sin utilizar un guión gráfico.

Vea también
PointAnimationUsingKeyFrames
EllipseGeometry.Center
EllipseGeometry
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar la geometría de un rectángulo
mediante fotogramas clave
23/10/2019 • 6 minutes to read • Edit Online

En este ejemplo se muestra cómo animar la Rect propiedad de un RectangleGeometry mediante fotogramas clave.

Ejemplo
En el ejemplo siguiente se usa el RectAnimationUsingKeyFrames clase se va a animar el Rect propiedad de un
RectangleGeometry. Esta animación utiliza tres fotogramas clave de la siguiente manera:
1. Durante los primeros dos segundos, utiliza una instancia de la LinearRectKeyFrame clase para animar un
cambio gradual en la posición, ancho y alto de un rectángulo. Los fotogramas clave lineales como
LinearRectKeyFrame crean una transición lineal suave entre valores.
2. Durante el fin de la siguiente medio segundo, utiliza una instancia de la DiscreteRectKeyFrame clase para
reducir de repente el alto del rectángulo. Los fotogramas clave discretos como DiscreteRectKeyFrame crean
cambios súbitos entre los valores, es decir, la reducción del alto se produce de forma rápida y brusca.
3. Durante los dos últimos segundos, utiliza una instancia de la SplineRectKeyFrame clase para cambiar el
rectángulo a su tamaño y posición originales. Los fotogramas clave spline como SplineRectKeyFrame crean
una transición variable entre los valores según los valores de la KeySpline propiedad. En este ejemplo, el
cambio comienza despacio y se acelera exponencialmente hacia el final del segmento temporal.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;

namespace Microsoft.Samples.KeyFrameExamples
{
/// <summary>
/// This example shows how to use the RectAnimationUsingKeyFrames class to
/// animate the position and size of a rectangle.
/// Key frame animations enable you to create complex animations
/// by specifying multiple destination values
/// and controlling the animation's interpolation method.
/// </summary>
public class RectAnimationUsingKeyFramesExample : Page
{
public RectAnimationUsingKeyFramesExample()
{
Title = "RectAnimationUsingKeyFrames Example";
Background = Brushes.White;
Margin = new Thickness(20);

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

StackPanel myStackPanel = new StackPanel();


myStackPanel.Orientation = Orientation.Vertical;
myStackPanel.HorizontalAlignment = HorizontalAlignment.Center;

//Add the Path Element


Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.Fill = Brushes.LemonChiffon;
myPath.StrokeThickness = 1;

// Create a RectangleGeometry to specify the Path data.


RectangleGeometry myRectangleGeometry = new RectangleGeometry();
myRectangleGeometry.Rect = new Rect(0, 200, 100, 100);
myPath.Data = myRectangleGeometry;

myStackPanel.Children.Add(myPath);

// Assign the TranslateTransform a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"AnimatedRectangleGeometry", myRectangleGeometry);

// Create a RectAnimationUsingKeyFrames to
// animate the RectangleGeometry.
RectAnimationUsingKeyFrames rectAnimation
= new RectAnimationUsingKeyFrames();
rectAnimation.Duration = TimeSpan.FromSeconds(6);

// Set the animation to repeat forever.


rectAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Animate position, width, and height in first 2 seconds. LinearRectKeyFrame creates


// a smooth, linear animation between values.
rectAnimation.KeyFrames.Add(
new LinearRectKeyFrame(
new Rect(600,50,200,50), // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2))) // KeyTime
);

// In the next half second, change height to 10. DiscreteRectKeyFrame creates a


// sudden "jump" between values.
rectAnimation.KeyFrames.Add(
new DiscreteRectKeyFrame(
new Rect(600, 50, 200, 10), // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.5))) // KeyTime
);

// In the final 2 seconds of the animation, go back to the starting position, width, and height.
// Spline key frames like SplineRectKeyFrame creates a variable transition between values
depending
// on the KeySpline property. In this example, the animation starts off slow but toward the end of
// the time segment, it speeds up exponentially.
rectAnimation.KeyFrames.Add(
new SplineRectKeyFrame(
new Rect(0, 200, 100, 100), // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4.5)), // KeyTime
new KeySpline(0.6, 0.0, 0.9, 0.0) // KeySpline
)
);

// Set the animation to target the Rect property


// of the object named "AnimatedRectangleGeometry."
Storyboard.SetTargetName(rectAnimation, "AnimatedRectangleGeometry");
Storyboard.SetTargetProperty(
rectAnimation, new PropertyPath(RectangleGeometry.RectProperty));

// Create a storyboard to apply the animation.


Storyboard rectStoryboard = new Storyboard();
rectStoryboard.Children.Add(rectAnimation);

// Start the storyboard after the rectangle loads.


myPath.Loaded += delegate(object sender, RoutedEventArgs e)
{
rectStoryboard.Begin(this);
rectStoryboard.Begin(this);
};

Content = myStackPanel;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation
Imports System.Windows.Media

Namespace Microsoft.Samples.KeyFrameExamples
''' <summary>
''' This example shows how to use the RectAnimationUsingKeyFrames class to
''' animate the position and size of a rectangle.
''' Key frame animations enable you to create complex animations
''' by specifying multiple destination values
''' and controlling the animation's interpolation method.
''' </summary>
Public Class RectAnimationUsingKeyFramesExample
Inherits Page
Public Sub New()
Title = "RectAnimationUsingKeyFrames Example"
Background = Brushes.White
Margin = New Thickness(20)

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myStackPanel As New StackPanel()


myStackPanel.Orientation = Orientation.Vertical
myStackPanel.HorizontalAlignment = HorizontalAlignment.Center

'Add the Path Element


Dim myPath As New Path()
myPath.Stroke = Brushes.Black
myPath.Fill = Brushes.LemonChiffon
myPath.StrokeThickness = 1

' Create a RectangleGeometry to specify the Path data.


Dim myRectangleGeometry As New RectangleGeometry()
myRectangleGeometry.Rect = New Rect(0, 200, 100, 100)
myPath.Data = myRectangleGeometry

myStackPanel.Children.Add(myPath)

' Assign the TranslateTransform a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("AnimatedRectangleGeometry", myRectangleGeometry)

' Create a RectAnimationUsingKeyFrames to


' animate the RectangleGeometry.
Dim rectAnimation As New RectAnimationUsingKeyFrames()
rectAnimation.Duration = TimeSpan.FromSeconds(6)

' Set the animation to repeat forever.


rectAnimation.RepeatBehavior = RepeatBehavior.Forever

' Animate position, width, and height in first 2 seconds. LinearRectKeyFrame creates
' a smooth, linear animation between values.
rectAnimation.KeyFrames.Add(New LinearRectKeyFrame(New Rect(600,50,200,50),
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2)))) ' KeyTime - Target value (KeyValue)
' In the next half second, change height to 10. DiscreteRectKeyFrame creates a
' sudden "jump" between values.
rectAnimation.KeyFrames.Add(New DiscreteRectKeyFrame(New Rect(600, 50, 200, 10),
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.5)))) ' KeyTime - Target value (KeyValue)

' In the final 2 seconds of the animation, go back to the starting position, width, and height.
' Spline key frames like SplineRectKeyFrame creates a variable transition between values depending
' on the KeySpline property. In this example, the animation starts off slow but toward the end of
' the time segment, it speeds up exponentially.
rectAnimation.KeyFrames.Add(New SplineRectKeyFrame(New Rect(0, 200, 100, 100),
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4.5)), New KeySpline(0.6, 0.0, 0.9, 0.0))) ' KeySpline - KeyTime -
Target value (KeyValue)

' Set the animation to target the Rect property


' of the object named "AnimatedRectangleGeometry."
Storyboard.SetTargetName(rectAnimation, "AnimatedRectangleGeometry")
Storyboard.SetTargetProperty(rectAnimation, New PropertyPath(RectangleGeometry.RectProperty))

' Create a storyboard to apply the animation.


Dim rectStoryboard As New Storyboard()
rectStoryboard.Children.Add(rectAnimation)

' Start the storyboard after the rectangle loads.


AddHandler myPath.Loaded, Sub(sender As Object, e As RoutedEventArgs) rectStoryboard.Begin(Me)

Content = myStackPanel
End Sub

End Class
End Namespace
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ThicknessAnimationUsingKeyFrames Example">

<StackPanel Orientation="Vertical" HorizontalAlignment="Center">

<Path Stroke="Black" StrokeThickness="1" Fill="LemonChiffon">


<Path.Data>
<RectangleGeometry x:Name="myRectangleGeometry" Rect="0,200,100,100" />
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- Animate the Rect property of the RectangleGeometry which causes the
rectangle to animate its position as well as its width and height. -->
<RectAnimationUsingKeyFrames
Storyboard.TargetName="myRectangleGeometry"
Storyboard.TargetProperty ="Rect"
Duration="0:0:6" FillBehavior="HoldEnd" RepeatBehavior="Forever">

<!-- Animate position, width, and height in first 2 seconds. LinearRectKeyFrame creates
a smooth, linear animation between values. -->
<LinearRectKeyFrame Value="600,50,200,50" KeyTime="0:0:2" />

<!-- In the next half second, change height to 10. DiscreteRectKeyFrame creates a
sudden "jump" between values. -->
<DiscreteRectKeyFrame Value="600,50,200,10" KeyTime="0:0:2.5" />

<!-- In the final 2 seconds of the animation, go back to the starting position, width, and
height.
Spline key frames like SplineRectKeyFrame creates a variable transition between values
depending
on the KeySpline property. In this example, the animation starts off slow but toward the end
of
the time segment, it speeds up exponentially.-->
<SplineRectKeyFrame Value="0,200,100,100" KeyTime="0:0:4.5" KeySpline="0.6,0.0 0.9,0.00" />
</RectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>

</StackPanel>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.

Vea también
RectangleGeometry
Rect
RectAnimationUsingKeyFrames
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar un objeto String mediante
fotogramas clave
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo animar una cadena, que en este ejemplo es el Content propiedad de un Button
control mediante fotogramas clave.

Ejemplo
En el ejemplo siguiente se usa el StringAnimationUsingKeyFrames clase se va a animar el Content propiedad de
un Button.
Todos los fotogramas clave en este ejemplo utilizan una instancia de la DiscreteStringKeyFrame clase porque una
animación de cadena que se crea con fotogramas clave solo puede usar fotogramas clave discretos. Los
fotogramas clave discretos como DiscreteStringKeyFrame crean saltos súbitos entre los valores, es decir, los
cambios realizados en la animación se producen rápidamente y no son sutiles.
<!-- Demonstrates the StringAnimationUsingKeyFrames class. A StringAnimationUsingKeyFrames is used to
animate the TextContent property of a Text element. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.KeyFrameExamples.StringAnimationUsingKeyFramesExample"
Name="myRootElement"
WindowTitle="StringAnimationUsingKeyFrames Example">

<StackPanel HorizontalAlignment="Center">
<Button Name="myAnimatedButton" Margin="200"
FontSize="16pt" FontFamily="Verdana">Some Text
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames
Storyboard.TargetName="myAnimatedButton" Storyboard.TargetProperty="(Button.Content)"
Duration="0:0:8" FillBehavior="HoldEnd">

<!-- All the key frames below are DiscreteStringKeyFrames. Discrete key frames create
sudden "jumps" between values (no interpolation). Only discrete key frames can be used
for String key frame animations. -->
<DiscreteStringKeyFrame Value="" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="A" KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="An" KeyTime="0:0:1.5" />
<DiscreteStringKeyFrame Value="Ani" KeyTime="0:0:2" />
<DiscreteStringKeyFrame Value="Anim" KeyTime="0:0:2.5" />
<DiscreteStringKeyFrame Value="Anima" KeyTime="0:0:3" />
<DiscreteStringKeyFrame Value="Animat" KeyTime="0:0:3.5" />
<DiscreteStringKeyFrame Value="Animate" KeyTime="0:0:4" />
<DiscreteStringKeyFrame Value="Animated" KeyTime="0:0:4.5" />
<DiscreteStringKeyFrame Value="Animated " KeyTime="0:0:5" />
<DiscreteStringKeyFrame Value="Animated T" KeyTime="0:0:5.5" />
<DiscreteStringKeyFrame Value="Animated Te" KeyTime="0:0:6" />
<DiscreteStringKeyFrame Value="Animated Tex" KeyTime="0:0:6.5" />
<DiscreteStringKeyFrame Value="Animated Text" KeyTime="0:0:7" />
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.

Vea también
StringAnimationUsingKeyFrames
Content
Button
DiscreteStringKeyFrame
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar un color mediante fotogramas
clave
23/10/2019 • 7 minutes to read • Edit Online

En este ejemplo se muestra cómo animar la Color de un SolidColorBrush mediante fotogramas clave.

Ejemplo
En el ejemplo siguiente se usa el ColorAnimationUsingKeyFrames clase se va a animar el Color propiedad de un
SolidColorBrush. Esta animación utiliza tres fotogramas clave de la siguiente manera:
1. Durante los primeros dos segundos, utiliza una instancia de la LinearColorKeyFrame clase para cambiar
gradualmente el color de verde a rojo. Los fotogramas clave lineales como LinearColorKeyFrame crean una
transición lineal suave entre valores.
2. Durante el fin de la siguiente medio segundo, utiliza una instancia de la DiscreteColorKeyFrame clase para
cambiar rápidamente el color de rojo a amarillo. Los fotogramas clave discretos como
DiscreteColorKeyFrame crean cambios súbitos entre los valores, es decir, el cambio de color en esta parte
de la animación se produce de forma rápida y brusca.
3. Durante los dos últimos segundos, utiliza una instancia de la SplineColorKeyFrame clase vuelvan a cambiar
el color, esta vez de amarillo a verde. Los fotogramas clave spline como SplineColorKeyFrame crean una
transición variable entre los valores según los valores de la KeySpline propiedad. En este ejemplo, el cambio
de color comienza despacio y se acelera exponencialmente hacia el final del segmento temporal.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;

namespace Microsoft.Samples.KeyFrameExamples
{
public class ColorAnimationUsingKeyFramesExample : Page
{
public ColorAnimationUsingKeyFramesExample()
{
Title = "BooleanAnimationUsingKeyFrames Example";
Background = Brushes.White;
Margin = new Thickness(20);

// Create a NameScope for this page so that


// Storyboards can be used.
NameScope.SetNameScope(this, new NameScope());

StackPanel myStackPanel = new StackPanel();


myStackPanel.Orientation = Orientation.Vertical;
myStackPanel.HorizontalAlignment = HorizontalAlignment.Center;

// Create the Border that is the target of the animation.


SolidColorBrush animatedBrush = new SolidColorBrush();
animatedBrush.Color = Color.FromArgb(255, 0, 255, 0);
Border myBorder = new Border();

// Set the initial color of the border to green.


myBorder.BorderBrush = animatedBrush;
myBorder.BorderBrush = animatedBrush;
myBorder.BorderThickness = new Thickness(28);
myBorder.Padding = new Thickness(20);
myStackPanel.Children.Add(myBorder);

// Create a TextBlock to host inside the Border.


TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "This example shows how to use the ColorAnimationUsingKeyFrames"
+ " to create an animation on the BorderBrush property of a Border.";
myBorder.Child = myTextBlock;

// Assign the Brush a name so that


// it can be targeted by a Storyboard.
this.RegisterName(
"AnimatedBrush", animatedBrush);

// Create a ColorAnimationUsingKeyFrames to
// animate the BorderBrush property of the Button.
ColorAnimationUsingKeyFrames colorAnimation
= new ColorAnimationUsingKeyFrames();
colorAnimation.Duration = TimeSpan.FromSeconds(6);

// Create brushes to use as animation values.


Color redColor = new Color();
redColor = Color.FromArgb(255, 255, 0, 0);
Color yellowColor = new Color();
yellowColor = Color.FromArgb(255, 255, 255, 0);
Color greenColor = new Color();
greenColor = Color.FromArgb(255, 0, 255, 0);

// Go from green to red in the first 2 seconds. LinearColorKeyFrame creates


// a smooth, linear animation between values.
colorAnimation.KeyFrames.Add(
new LinearColorKeyFrame(
redColor, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.0))) // KeyTime
);

// In the next half second, go to yellow. DiscreteColorKeyFrame creates a


// sudden jump between values.
colorAnimation.KeyFrames.Add(
new DiscreteColorKeyFrame(
yellowColor, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.5))) // KeyTime
);

// In the final 2 seconds of the animation, go from yellow back to green. SplineColorKeyFrame
// creates a variable transition between values depending on the KeySpline property. In this
example,
// the animation starts off slow but toward the end of the time segment, it speeds up
exponentially.
colorAnimation.KeyFrames.Add(
new SplineColorKeyFrame(
greenColor, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4.5)), // KeyTime
new KeySpline(0.6, 0.0, 0.9, 0.0) // KeySpline
)
);

// Set the animation to repeat forever.


colorAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the animation to target the Color property


// of the object named "AnimatedBrush".
Storyboard.SetTargetName(colorAnimation, "AnimatedBrush");
Storyboard.SetTargetProperty(
colorAnimation, new PropertyPath(SolidColorBrush.ColorProperty));

// Create a storyboard to apply the animation.


Storyboard myStoryboard = new Storyboard();
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(colorAnimation);

// Start the storyboard when the Border loads.


myBorder.Loaded += delegate(object sender, RoutedEventArgs e)
{
myStoryboard.Begin(this);
};

Content = myStackPanel;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation
Imports System.Windows.Media

Namespace Microsoft.Samples.KeyFrameExamples
Public Class ColorAnimationUsingKeyFramesExample
Inherits Page
Public Sub New()
Title = "BooleanAnimationUsingKeyFrames Example"
Background = Brushes.White
Margin = New Thickness(20)

' Create a NameScope for this page so that


' Storyboards can be used.
NameScope.SetNameScope(Me, New NameScope())

Dim myStackPanel As New StackPanel()


myStackPanel.Orientation = Orientation.Vertical
myStackPanel.HorizontalAlignment = HorizontalAlignment.Center

' Create the Border that is the target of the animation.


Dim animatedBrush As New SolidColorBrush()
animatedBrush.Color = Color.FromArgb(255, 0, 255, 0)
Dim myBorder As New Border()

' Set the initial color of the border to green.


myBorder.BorderBrush = animatedBrush
myBorder.BorderThickness = New Thickness(28)
myBorder.Padding = New Thickness(20)
myStackPanel.Children.Add(myBorder)

' Create a TextBlock to host inside the Border.


Dim myTextBlock As New TextBlock()
myTextBlock.Text = "This example shows how to use the ColorAnimationUsingKeyFrames" & " to create
an animation on the BorderBrush property of a Border."
myBorder.Child = myTextBlock

' Assign the Brush a name so that


' it can be targeted by a Storyboard.
Me.RegisterName("AnimatedBrush", animatedBrush)

' Create a ColorAnimationUsingKeyFrames to


' animate the BorderBrush property of the Button.
Dim colorAnimation As New ColorAnimationUsingKeyFrames()
colorAnimation.Duration = TimeSpan.FromSeconds(6)

' Create brushes to use as animation values.


Dim redColor As New Color()
redColor = Color.FromArgb(255, 255, 0, 0)
Dim yellowColor As New Color()
yellowColor = Color.FromArgb(255, 255, 255, 0)
yellowColor = Color.FromArgb(255, 255, 255, 0)
Dim greenColor As New Color()
greenColor = Color.FromArgb(255, 0, 255, 0)

' Go from green to red in the first 2 seconds. LinearColorKeyFrame creates


' a smooth, linear animation between values.
colorAnimation.KeyFrames.Add(New LinearColorKeyFrame(redColor,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.0)))) ' KeyTime - Target value (KeyValue)

' In the next half second, go to yellow. DiscreteColorKeyFrame creates a


' sudden jump between values.
colorAnimation.KeyFrames.Add(New DiscreteColorKeyFrame(yellowColor,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.5)))) ' KeyTime - Target value (KeyValue)

' In the final 2 seconds of the animation, go from yellow back to green. SplineColorKeyFrame
' creates a variable transition between values depending on the KeySpline property. In this
example,
' the animation starts off slow but toward the end of the time segment, it speeds up
exponentially.
colorAnimation.KeyFrames.Add(New SplineColorKeyFrame(greenColor,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4.5)), New KeySpline(0.6, 0.0, 0.9, 0.0))) ' KeySpline - KeyTime -
Target value (KeyValue)

' Set the animation to repeat forever.


colorAnimation.RepeatBehavior = RepeatBehavior.Forever

' Set the animation to target the Color property


' of the object named "AnimatedBrush".
Storyboard.SetTargetName(colorAnimation, "AnimatedBrush")
Storyboard.SetTargetProperty(colorAnimation, New PropertyPath(SolidColorBrush.ColorProperty))

' Create a storyboard to apply the animation.


Dim myStoryboard As New Storyboard()
myStoryboard.Children.Add(colorAnimation)

' Start the storyboard when the Border loads.


AddHandler myBorder.Loaded, Sub(sender As Object, e As RoutedEventArgs) myStoryboard.Begin(Me)

Content = myStackPanel
End Sub

End Class
End Namespace
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ThicknessAnimationUsingKeyFrames Example">

<StackPanel Orientation="Vertical" HorizontalAlignment="Center">


<Border Background="#99FFFFFF" BorderThickness="28"
Margin="0,60,0,20" Padding="20" >
<Border.BorderBrush>
<SolidColorBrush x:Name="MyAnimatedBrush" Color="Green" />
</Border.BorderBrush>
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- Animate from green to red using a linear key frame, from red to
yellow using a discrete key frame, and from yellow back to green with
a spline key frame. This animation repeats forever. -->
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="Color"
Storyboard.TargetName="MyAnimatedBrush"
Duration="0:0:6" FillBehavior="HoldEnd" RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames.KeyFrames>

<!-- Go from green to red in the first 2 seconds. LinearColorKeyFrame creates


a smooth, linear animation between values. -->
<LinearColorKeyFrame Value="Red" KeyTime="0:0:2" />

<!-- In the next half second, go to yellow. DiscreteColorKeyFrame creates a


sudden jump between values. -->
<DiscreteColorKeyFrame Value="Yellow" KeyTime="0:0:2.5" />

<!-- In the final 2 seconds of the animation, go from yellow back to green.
SplineColorKeyFrame
creates a variable transition between values depending on the KeySpline property. In this
example,
the animation starts off slow but toward the end of the time segment, it speeds up
exponentially.-->
<SplineColorKeyFrame Value="Green" KeyTime="0:0:4.5" KeySpline="0.6,0.0 0.9,0.00" />
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>

<TextBlock>
This example shows how to use the ColorAnimationUsingKeyFrames to create
an animation on the BorderBrush property of a Border.
</TextBlock>
</Border>

</StackPanel>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.

Vea también
Color
SolidColorBrush
ColorAnimationUsingKeyFrames
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar los cambios de tamaño
mediante fotogramas clave
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo animar los cambios del tamaño mediante fotogramas clave.

Ejemplo
En el ejemplo siguiente se usa el SizeAnimationUsingKeyFrames clase se va a animar el Size propiedad de un
ArcSegment. Esta animación utiliza tres fotogramas clave de la siguiente manera:
1. Durante el primer medio segundo de la animación, usa una instancia de la LinearSizeKeyFrame clase para
aumentar gradualmente el tamaño del arco. Los fotogramas clave lineales como LinearSizeKeyFrame crean
una transición lineal suave entre valores.
2. Al final de la siguiente medio segundo, utiliza una instancia de la DiscreteSizeKeyFrame clase, de repente,
aumentar el tamaño del arco. Los fotogramas clave discretos como DiscreteSizeKeyFrame crean saltos
súbitos entre los valores, es decir, los cambios de tamaño se producen de repente y no son sutiles.
3. A través de los dos últimos segundos, utiliza una instancia de la SplineSizeKeyFrame clase para aumentar el
tamaño del arco. Los fotogramas clave spline como SplineSizeKeyFrame crean una transición variable entre
los valores según los valores de la KeySpline propiedad. En este ejemplo, el tamaño del arco aumenta
lentamente al principio y va aumentando exponencialmente hacia el final del segmento temporal.
<!-- This example shows how to use the SizeAnimationUsingKeyFrames to animate the
size of an ArcSegment. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

<Canvas HorizontalAlignment="Left" Margin="0" >

<!-- Create an arc on the screen that animates its size when it loads. -->
<Path Stroke="Black" StrokeThickness="2" >
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="100,200">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment x:Name="myArcSegment" Size="90,80"
SweepDirection="Clockwise" Point="500,200" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard Name="myBeginStoryBoard">
<Storyboard>

<!-- Animating the Size property uses 3 KeyFrames. -->


<SizeAnimationUsingKeyFrames
Storyboard.TargetName="myArcSegment"
Storyboard.TargetProperty="Size" >
<SizeAnimationUsingKeyFrames.KeyFrames>
<!-- Using a LinearSizeKeyFrame, the size of the arc increases
gradually over the first half second of the animation. -->
<LinearSizeKeyFrame KeyTime="0:0:0.5" Value="120,120" />

<!-- Using a DiscreteSizeKeyFrame, the size increases suddenly


after the first second of the animation. -->
<DiscreteSizeKeyFrame KeyTime="0:0:1" Value="150,150" />

<!-- Using a SplineSizeKeyFrame, the Size increases slowly at first


and then speeds up exponentially. This KeyFrame takes 2 seconds. -->
<SplineSizeKeyFrame KeySpline="0.6,0.0 0.9,0.00" KeyTime="0:0:3" Value="300,300" />

</SizeAnimationUsingKeyFrames.KeyFrames>
</SizeAnimationUsingKeyFrames>

</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Canvas>

</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.

Vea también
SizeAnimationUsingKeyFrames
Size
ArcSegment
LinearSizeKeyFrame
DiscreteSizeKeyFrame
SplineSizeKeyFrame
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Procedimiento Animar el grosor de un borde
mediante fotogramas clave
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo animar la BorderThickness propiedad de un Border.

Ejemplo
En el ejemplo siguiente se usa el ThicknessAnimationUsingKeyFrames clase se va a animar el BorderThickness
propiedad de un Border. Esta animación utiliza tres fotogramas clave de la siguiente manera:
1. Durante el primer medio segundo, utiliza una instancia de la LinearThicknessKeyFrame clase para aumentar
gradualmente el grosor del borde. El ejemplo se utiliza LinearThicknessKeyFrame para crear un aumento
lineal suavizado entre los valores.
2. Al final de la siguiente medio segundo, utiliza una instancia de la DiscreteThicknessKeyFrame clase para
aumentar de repente el grosor del borde. Los fotogramas clave discretos como los derivan de
DiscreteThicknessKeyFrame crean saltos súbitos entre los valores, es decir, el movimiento de la animación
es brusco.
3. Durante los dos últimos segundos, utiliza una instancia de la SplineThicknessKeyFrame clase para reducir el
grosor del borde. Los fotogramas clave spline como los derivan de SplineThicknessKeyFrame crean una
transición variable entre los valores según los valores de la KeySpline propiedad. En este fotograma clave, la
animación se inicia lentamente y se va acelerando de forma exponencial hacia el final del segmento
temporal.
<!-- This example shows how to use the ThicknessAnimationUsingKeyFrames to create
an animation on the BorderThickness property of a Border. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.KeyFrameExamples.ThicknessAnimationUsingKeyFramesExample"
Name="myRootElement"
WindowTitle="ThicknessAnimationUsingKeyFrames Example">

<StackPanel Orientation="Vertical" HorizontalAlignment="Center">


<Border Background="#99FFFFFF" BorderBrush="#CCCCFF" BorderThickness="1"
Margin="0,60,0,20" Padding="20" >
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard>

<!-- Animating the BorderThickness property uses 3 KeyFrames. -->


<ThicknessAnimationUsingKeyFrames
Storyboard.TargetProperty="BorderThickness"
Duration="0:0:5" FillBehavior="HoldEnd" RepeatBehavior="Forever">
<ThicknessAnimationUsingKeyFrames.KeyFrames>

<!-- Using a LinearThicknessKeyFrame, thickness increases gradually


over the first half second of the animation. -->
<LinearThicknessKeyFrame KeyTime="0:0:0.5">
<LinearThicknessKeyFrame.Value>
<Thickness Left="8" Right="8" Top="6" Bottom="6" />
</LinearThicknessKeyFrame.Value>
</LinearThicknessKeyFrame>

<!-- Using a DiscreteThicknessKeyFrame, thickness increases suddenly


after the first second of the animation. -->
<DiscreteThicknessKeyFrame KeyTime="0:0:1">
<DiscreteThicknessKeyFrame.Value>
<Thickness Left="28" Right="28" Top="24" Bottom="24" />
</DiscreteThicknessKeyFrame.Value>
</DiscreteThicknessKeyFrame>

<!-- Using a SplineThicknessKeyFrame, thickness decreases slowly at first


and then suddenly contracts. This KeyFrame takes 2 seconds. -->
<SplineThicknessKeyFrame KeySpline="0.6,0.0 0.9,0.00" KeyTime="0:0:3">
<SplineThicknessKeyFrame.Value>
<Thickness Left="1" Right="1" Top="1" Bottom="8" />
</SplineThicknessKeyFrame.Value>
</SplineThicknessKeyFrame>

</ThicknessAnimationUsingKeyFrames.KeyFrames>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>

<TextBlock>
This example shows how to use the ThicknessAnimationUsingKeyFrames to create
an animation on the BorderThickness property of a Border.
</TextBlock>
</Border>

</StackPanel>
</Page>

Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave.

Vea también
LinearThicknessKeyFrame
DiscreteThicknessKeyFrame
SplineThicknessKeyFrame
Información general sobre animaciones de fotogramas clave
Temas de procedimientos de fotogramas clave
Animar el valor del grosor de un borde
Procedimiento Controlar la temporización de
animaciones de fotogramas clave
23/10/2019 • 12 minutes to read • Edit Online

En este ejemplo se muestra cómo controlar la temporización de fotogramas clave dentro de una animación de
fotogramas clave. Al igual que otras animaciones, animaciones de fotogramas clave tienen una Duration
propiedad. Además de especificar la duración de una animación, deberá especificar qué parte de esa duración se
asigna a cada uno de los fotogramas clave. Para asignar el tiempo, especifica un KeyTime para cada fotograma
clave en la animación.
El KeyTime para cada fotograma clave especifica cuando finaliza (no especificar el período de tiempo se reproduce
un fotograma clave). Puede especificar un KeyTime como un TimeSpan valor, como un porcentaje o como el
Uniform o Paced valor especial.

Ejemplo
En el ejemplo siguiente se usa un DoubleAnimationUsingKeyFrames para animar un rectángulo en la pantalla. Los
tiempos clave de los fotogramas clave se establecen con TimeSpan valores.
/*
This Rectangle is animated with KeyTimes using TimeSpan Values.
It moves horizontally to 100 in the first 3 seconds, 100 to 300 in
the next second, and 300 to 500 in the last 6 seconds.
*/

// Create the a rectangle.


Rectangle aRectangle = new Rectangle();
aRectangle.Fill = Brushes.Blue;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 5;
aRectangle.Width = 50;
aRectangle.Height = 50;

// Create a transform to move the rectangle


// across the screen.
TranslateTransform translateTransform1 =
new TranslateTransform();
aRectangle.RenderTransform = translateTransform1;

// Create a DoubleAnimationUsingKeyFrames
// to animate the transform.
DoubleAnimationUsingKeyFrames transformAnimation =
new DoubleAnimationUsingKeyFrames();
transformAnimation.Duration = TimeSpan.FromSeconds(10);

// Animate to 100 at 3 seconds.


transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(100, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3))));

// Animate to 300 at 4 seconds.


transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(300, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4))));

// Animate to 500 at 10 seconds.


transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(500, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(10))));

// Start the animation when the rectangle is loaded.


aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
translateTransform1.BeginAnimation(TranslateTransform.XProperty, transformAnimation);
};
'
' This Rectangle is animated with KeyTimes using TimeSpan Values.
' It moves horizontally to 100 in the first 3 seconds, 100 to 300 in
' the next second, and 300 to 500 in the last 6 seconds.
'

' Create the a rectangle.


Dim aRectangle As New Rectangle()
aRectangle.Fill = Brushes.Blue
aRectangle.Stroke = Brushes.Black
aRectangle.StrokeThickness = 5
aRectangle.Width = 50
aRectangle.Height = 50

' Create a transform to move the rectangle


' across the screen.
Dim translateTransform1 As New TranslateTransform()
aRectangle.RenderTransform = translateTransform1

' Create a DoubleAnimationUsingKeyFrames


' to animate the transform.
Dim transformAnimation As New DoubleAnimationUsingKeyFrames()
transformAnimation.Duration = TimeSpan.FromSeconds(10)

' Animate to 100 at 3 seconds.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(100,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3))))

' Animate to 300 at 4 seconds.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(300,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(4))))

' Animate to 500 at 10 seconds.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(500,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(10))))

' Start the animation when the rectangle is loaded.


AddHandler aRectangle.Loaded, Sub(sender As Object, e As RoutedEventArgs)
translateTransform1.BeginAnimation(TranslateTransform.XProperty, transformAnimation)
<!-- This Rectangle is animated with KeyTimes using TimeSpan Values.
It moves horizontally to 100 in the first 3 seconds, 100 to 300 in
the next second, and 300 to 500 in the last 6 seconds. -->
<Rectangle Fill="Blue" Stroke="Black" StrokeThickness="5"
Width="50" Height="50">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform1" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform1"
Storyboard.TargetProperty="X"
Duration="0:0:10">

<!-- These KeyTime properties are specified as TimeSpan values


which are in the form of "hours:minutes:seconds". -->
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:3" />
<LinearDoubleKeyFrame Value="300" KeyTime="0:0:4" />
<LinearDoubleKeyFrame Value="500" KeyTime="0:0:10" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

La siguiente ilustración se muestra cuando se alcanza el valor de cada fotograma clave.

El ejemplo siguiente muestra una animación que es idéntica, salvo que los tiempos clave de los fotogramas clave
se establecen con valores de porcentaje.
/*
This rectangle moves horizontally to 100 in the first 3 seconds,
100 to 300 in the next second, and 300 to 500 in the last 6 seconds.
*/

// Create the a rectangle.


Rectangle aRectangle = new Rectangle();
aRectangle.Fill = Brushes.Purple;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 5;
aRectangle.Width = 50;
aRectangle.Height = 50;

// Create a transform to move the rectangle


// across the screen.
TranslateTransform translateTransform2 =
new TranslateTransform();
aRectangle.RenderTransform = translateTransform2;

// Create a DoubleAnimationUsingKeyFrames
// to animate the transform.
DoubleAnimationUsingKeyFrames transformAnimation =
new DoubleAnimationUsingKeyFrames();
transformAnimation.Duration = TimeSpan.FromSeconds(10);

// Animate to 100 at 30% of the animation's duration.


transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(100, KeyTime.FromPercent(0.3)));

// Animate to 300 at 40% of the animation's duration.


transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(300, KeyTime.FromPercent(0.4)));

// Animate to 500 at 100% of the animation's duration.


transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(500, KeyTime.FromPercent(1.0)));

// Start the animation when the rectangle is loaded.


aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
translateTransform2.BeginAnimation(TranslateTransform.XProperty, transformAnimation);
};
'
' This rectangle moves horizontally to 100 in the first 3 seconds,
' 100 to 300 in the next second, and 300 to 500 in the last 6 seconds.
'

' Create the a rectangle.


Dim aRectangle As New Rectangle()
aRectangle.Fill = Brushes.Purple
aRectangle.Stroke = Brushes.Black
aRectangle.StrokeThickness = 5
aRectangle.Width = 50
aRectangle.Height = 50

' Create a transform to move the rectangle


' across the screen.
Dim translateTransform2 As New TranslateTransform()
aRectangle.RenderTransform = translateTransform2

' Create a DoubleAnimationUsingKeyFrames


' to animate the transform.
Dim transformAnimation As New DoubleAnimationUsingKeyFrames()
transformAnimation.Duration = TimeSpan.FromSeconds(10)

' Animate to 100 at 30% of the animation's duration.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(100, KeyTime.FromPercent(0.3)))

' Animate to 300 at 40% of the animation's duration.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(300, KeyTime.FromPercent(0.4)))

' Animate to 500 at 100% of the animation's duration.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(500, KeyTime.FromPercent(1.0)))

' Start the animation when the rectangle is loaded.


AddHandler aRectangle.Loaded, Sub(sender As Object, e As RoutedEventArgs)
translateTransform2.BeginAnimation(TranslateTransform.XProperty, transformAnimation)

<!-- This rectangle moves horizontally to 100 in the first 3 seconds,


100 to 300 in the next second, and 300 to 500 in the last 6 seconds.-->
<Rectangle Fill="Purple" Stroke="Black" StrokeThickness="5"
Width="50" Height="50">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform2" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform2"
Storyboard.TargetProperty="X"
Duration="0:0:10">

<!-- KeyTime properties are expressed as Percentages. -->


<LinearDoubleKeyFrame Value="100" KeyTime="30%" />
<LinearDoubleKeyFrame Value="300" KeyTime="40%" />
<LinearDoubleKeyFrame Value="500" KeyTime="100%" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

La siguiente ilustración se muestra cuando se alcanza el valor de cada fotograma clave.


El ejemplo siguiente se usa Uniform tiempo valores de clave.

/*
This rectangle is animated with KeyTimes using Uniform values.
Goes to 100 in the first 3.3 seconds, 100 to
300 in the next 3.3 seconds, 300 to 500 in the last 3.3 seconds.
*/

// Create the a rectangle.


Rectangle aRectangle = new Rectangle();
aRectangle.Fill = Brushes.Red;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 5;
aRectangle.Width = 50;
aRectangle.Height = 50;

// Create a transform to move the rectangle


// across the screen.
TranslateTransform translateTransform3 =
new TranslateTransform();
aRectangle.RenderTransform = translateTransform3;

// Create a DoubleAnimationUsingKeyFrames
// to animate the transform.
DoubleAnimationUsingKeyFrames transformAnimation =
new DoubleAnimationUsingKeyFrames();
transformAnimation.Duration = TimeSpan.FromSeconds(10);

/*
KeyTime properties are expressed with values of Uniform. When a key time is set to
"Uniform" the total allotted time of the animation is divided evenly between key frames.
In this example, the total duration of the animation is ten seconds and there are four
key frames each of which are set to "Uniform", therefore, the duration of each key frame
is 3.3 seconds (10/3).
*/

// Animate to 100.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(100, KeyTime.Uniform));

// Animate to 300.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(300, KeyTime.Uniform));

// Animate to 500.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(500, KeyTime.Uniform));

// Start the animation when the rectangle is loaded.


aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
translateTransform3.BeginAnimation(TranslateTransform.XProperty, transformAnimation);
};
'
' This rectangle is animated with KeyTimes using Uniform values.
' Goes to 100 in the first 3.3 seconds, 100 to
' 300 in the next 3.3 seconds, 300 to 500 in the last 3.3 seconds.
'

' Create the a rectangle.


Dim aRectangle As New Rectangle()
aRectangle.Fill = Brushes.Red
aRectangle.Stroke = Brushes.Black
aRectangle.StrokeThickness = 5
aRectangle.Width = 50
aRectangle.Height = 50

' Create a transform to move the rectangle


' across the screen.
Dim translateTransform3 As New TranslateTransform()
aRectangle.RenderTransform = translateTransform3

' Create a DoubleAnimationUsingKeyFrames


' to animate the transform.
Dim transformAnimation As New DoubleAnimationUsingKeyFrames()
transformAnimation.Duration = TimeSpan.FromSeconds(10)

'
' KeyTime properties are expressed with values of Uniform. When a key time is set to
' "Uniform" the total allotted time of the animation is divided evenly between key frames.
' In this example, the total duration of the animation is ten seconds and there are four
' key frames each of which are set to "Uniform", therefore, the duration of each key frame
' is 3.3 seconds (10/3).
'

' Animate to 100.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(100, KeyTime.Uniform))

' Animate to 300.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(300, KeyTime.Uniform))

' Animate to 500.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(500, KeyTime.Uniform))

' Start the animation when the rectangle is loaded.


AddHandler aRectangle.Loaded, Sub(sender As Object, e As RoutedEventArgs)
translateTransform3.BeginAnimation(TranslateTransform.XProperty, transformAnimation)
<!-- This rectangle is animated with KeyTimes using Uniform values.
Goes to 100 in the first 3.3 seconds, 100 to
300 in the next 3.3 seconds, 300 to 500 in the last 3.3 seconds. -->
<Rectangle Fill="Red" Stroke="Black" StrokeThickness="5"
Width="50" Height="50">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform3" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform3"
Storyboard.TargetProperty="X"
Duration="0:0:10">

<!-- KeyTime properties are expressed with values of Uniform. When a key time is set to
"Uniform" the total allotted time of the animation is divided evenly between key frames.
In this example, the total duration of the animation is ten seconds and there are four
key frames each of which are set to "Uniform", therefore, the duration of each key frame
is 3.3 seconds (10/3). -->
<LinearDoubleKeyFrame Value="100" KeyTime="Uniform" />
<LinearDoubleKeyFrame Value="300" KeyTime="Uniform" />
<LinearDoubleKeyFrame Value="500" KeyTime="Uniform" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

La siguiente ilustración se muestra cuando se alcanza el valor de cada fotograma clave.

El último ejemplo utiliza Paced tiempo valores de clave.


/*
This rectangle is animated with KeyTimes using Paced Values.
The rectangle moves between key frames at uniform rate except for first key frame
because using a Paced value on the first KeyFrame in a collection of frames gives a time of zero.
*/

// Create the a rectangle.


Rectangle aRectangle = new Rectangle();
aRectangle.Fill = Brushes.Orange;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 5;
aRectangle.Width = 50;
aRectangle.Height = 50;

// Create a transform to move the rectangle


// across the screen.
TranslateTransform translateTransform4 =
new TranslateTransform();
aRectangle.RenderTransform = translateTransform4;

// Create a DoubleAnimationUsingKeyFrames
// to animate the transform.
DoubleAnimationUsingKeyFrames transformAnimation =
new DoubleAnimationUsingKeyFrames();
transformAnimation.Duration = TimeSpan.FromSeconds(10);

/*
Use Paced values when a constant rate is desired.
The time allocated to a key frame with a KeyTime of "Paced" is
determined by the time allocated to the other key frames of the animation. This time is
calculated to attempt to give a "paced" or "constant velocity" for the animation.
*/

// Animate to 100.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(100, KeyTime.Paced));

// Animate to 300.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(300, KeyTime.Paced));

// Animate to 500.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(500, KeyTime.Paced));

// Start the animation when the rectangle is loaded.


aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
translateTransform4.BeginAnimation(TranslateTransform.XProperty, transformAnimation);
};
'
' This rectangle is animated with KeyTimes using Paced Values.
' The rectangle moves between key frames at uniform rate except for first key frame
' because using a Paced value on the first KeyFrame in a collection of frames gives a time of
zero.
'

' Create the a rectangle.


Dim aRectangle As New Rectangle()
aRectangle.Fill = Brushes.Orange
aRectangle.Stroke = Brushes.Black
aRectangle.StrokeThickness = 5
aRectangle.Width = 50
aRectangle.Height = 50

' Create a transform to move the rectangle


' across the screen.
Dim translateTransform4 As New TranslateTransform()
aRectangle.RenderTransform = translateTransform4

' Create a DoubleAnimationUsingKeyFrames


' to animate the transform.
Dim transformAnimation As New DoubleAnimationUsingKeyFrames()
transformAnimation.Duration = TimeSpan.FromSeconds(10)

'
' Use Paced values when a constant rate is desired.
' The time allocated to a key frame with a KeyTime of "Paced" is
' determined by the time allocated to the other key frames of the animation. This time is
' calculated to attempt to give a "paced" or "constant velocity" for the animation.
'

' Animate to 100.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(100, KeyTime.Paced))

' Animate to 300.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(300, KeyTime.Paced))

' Animate to 500.


transformAnimation.KeyFrames.Add(New LinearDoubleKeyFrame(500, KeyTime.Paced))

' Start the animation when the rectangle is loaded.


AddHandler aRectangle.Loaded, Sub(sender As Object, e As RoutedEventArgs)
translateTransform4.BeginAnimation(TranslateTransform.XProperty, transformAnimation)
<!-- This rectangle is animated with KeyTimes using Paced Values.
The rectangle moves between key frames at uniform rate except for first key frame
because using a Paced value on the first KeyFrame in a collection of frames gives a time of zero. -->
<Rectangle Fill="Orange" Stroke="Black" StrokeThickness="5"
Width="50" Height="50">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform4" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform4"
Storyboard.TargetProperty="X"
Duration="0:0:10">

<!-- Use Paced values when a constant rate is desired.


The time allocated to a key frame with a KeyTime of "Paced" is
determined by the time allocated to the other key frames of the animation. This time is
calculated to attempt to give a "paced" or "constant velocity" for the animation. -->
<LinearDoubleKeyFrame Value="100" KeyTime="Paced" />
<LinearDoubleKeyFrame Value="300" KeyTime="Paced" />
<LinearDoubleKeyFrame Value="500" KeyTime="Paced" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

La siguiente ilustración se muestra cuando se alcanza el valor de cada fotograma clave.

Por motivos de simplicidad, las versiones de código de este ejemplo usan animaciones locales, no guiones gráficos,
porque se aplica solo a una animación única a una sola propiedad, pero se pueden modificar los ejemplos para
usar guiones gráficos en su lugar. Para obtener un ejemplo que muestra cómo declarar un guión gráfico en el
código, consulte animar una propiedad utilizando un guión gráfico.
Para consultar el ejemplo completo, vea Ejemplo de animación mediante fotogramas clave. Para obtener más
información acerca de las animaciones de fotogramas clave, consulte el información general sobre animaciones de
fotogramas clave.

Vea también
Información general sobre animaciones de fotogramas clave
Información general sobre animaciones
Temas "Cómo..."
Temas "Cómo..." de animación de trazado
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección muestran cómo animar un objeto a lo largo de una ruta de acceso.

En esta sección
Animación de un objeto a lo largo de un trazado (animación doble)
Animación de un objeto a lo largo de un trazado (animación en punto)
Animación de un objeto a lo largo de un trazado (animación de matriz)
Animar un objeto a lo largo de un trazado (animación en matriz con acumulación de desplazamiento)
Girar un objeto utilizando un trazado geométrico (animación en matriz)
Girar un objeto utilizando un trazado geométrico

Referencia
PathAnimationSource
Storyboard

Vea también
Gráficos y multimedia
Información general sobre animaciones
Información general sobre animaciones de fotogramas clave
Cómo: Animar un objeto a lo largo de una
trayectoria (animación doble)
20/02/2020 • 5 minutes to read • Edit Online

En este ejemplo se muestra cómo usar la clase DoubleAnimationUsingPath para trasladar un objeto a lo largo de
un trazado definido por un PathGeometry.

Ejemplo
En el ejemplo siguiente se usan dos objetos DoubleAnimationUsingPath para desplace un rectángulo a lo largo de
un trazado geométrico:
La primera DoubleAnimationUsingPath anima el X de la TranslateTransform aplicada al rectángulo. Hace
que el rectángulo se mueva horizontalmente a lo largo del trazado.
El segundo DoubleAnimationUsingPath anima el Y de la TranslateTransform aplicada al rectángulo. Hace
que el rectángulo se mueva verticalmente a lo largo del trazado.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions">
<Page.Resources>

<!-- This is the geometry creates the animation path. Because


this example uses it multiple times, it's declared as a resource and
frozen to improve performance. -->
<PathGeometry x:Key="AnimationPath"
Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"
PresentationOptions:Freeze="True" />
</Page.Resources>

<Canvas Width="400" Height="400">

<!-- The object to animate. -->


<Rectangle
Width="30" Height="30" Fill="Blue">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="AnimatedTranslateTransform" />
</Rectangle.RenderTransform>

<Rectangle.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">

<!-- Animates the rectangle horizotally along the path. -->


<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="X"
PathGeometry="{StaticResource AnimationPath}"
Source="X"
Duration="0:0:5" />

<!-- Animates the rectangle vertically along the path. -->


<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="Y"
PathGeometry="{StaticResource AnimationPath}"
Source="Y"
Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
</Page>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SDKSample
{

public class DoubleAnimationUsingPathExample : Page


{
public DoubleAnimationUsingPathExample()
{

// Create a NameScope for the page so that


// we can use Storyboards.
NameScope.SetNameScope(this, new NameScope());

// Create a rectangle.
Rectangle aRectangle = new Rectangle();
aRectangle.Width = 30;
aRectangle.Height = 30;
aRectangle.Fill = Brushes.Blue;

// Create a transform. This transform


// will be used to move the rectangle.
TranslateTransform animatedTranslateTransform =
new TranslateTransform();

// Register the transform's name with the page


// so that they it be targeted by a Storyboard.
this.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform);

aRectangle.RenderTransform = animatedTranslateTransform;

// Create a Canvas to contain the rectangle


// and add it to the page.
Canvas mainPanel = new Canvas();
mainPanel.Width = 400;
mainPanel.Height = 400;
mainPanel.Children.Add(aRectangle);
this.Content = mainPanel;

// Create the animation path.


PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = new Point(10, 100);
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(new Point(35, 0));
pBezierSegment.Points.Add(new Point(135, 0));
pBezierSegment.Points.Add(new Point(160, 100));
pBezierSegment.Points.Add(new Point(180, 190));
pBezierSegment.Points.Add(new Point(285, 200));
pBezierSegment.Points.Add(new Point(310, 100));
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);

// Freeze the PathGeometry for performance benefits.


animationPath.Freeze();

// Create a DoubleAnimationUsingPath to move the


// rectangle horizontally along the path by animating
// its TranslateTransform.
DoubleAnimationUsingPath translateXAnimation =
new DoubleAnimationUsingPath();
translateXAnimation.PathGeometry = animationPath;
translateXAnimation.Duration = TimeSpan.FromSeconds(5);

// Set the Source property to X. This makes


// the animation generate horizontal offset values from
// the path information.
translateXAnimation.Source = PathAnimationSource.X;

// Set the animation to target the X property


// of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTargetName(translateXAnimation, "AnimatedTranslateTransform");
Storyboard.SetTargetProperty(translateXAnimation,
new PropertyPath(TranslateTransform.XProperty));
// Create a DoubleAnimationUsingPath to move the
// rectangle vertically along the path by animating
// its TranslateTransform.
DoubleAnimationUsingPath translateYAnimation =
new DoubleAnimationUsingPath();
translateYAnimation.PathGeometry = animationPath;
translateYAnimation.Duration = TimeSpan.FromSeconds(5);

// Set the Source property to Y. This makes


// the animation generate vertical offset values from
// the path information.
translateYAnimation.Source = PathAnimationSource.Y;

// Set the animation to target the Y property


// of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTargetName(translateYAnimation, "AnimatedTranslateTransform");
Storyboard.SetTargetProperty(translateYAnimation,
new PropertyPath(TranslateTransform.YProperty));

// Create a Storyboard to contain and apply the animations.


Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
pathAnimationStoryboard.Children.Add(translateXAnimation);
pathAnimationStoryboard.Children.Add(translateYAnimation);

// Start the animations when the rectangle is loaded.


aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
// Start the storyboard.
pathAnimationStoryboard.Begin(this);
};
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Namespace SDKSample

Public Class DoubleAnimationUsingPathExample


Inherits Page

Public Sub New()

' Create a NameScope for the page so that


' we can use Storyboards.
NameScope.SetNameScope(Me, New NameScope())

' Create a rectangle.


Dim aRectangle As New Rectangle()
aRectangle.Width = 30
aRectangle.Height = 30
aRectangle.Fill = Brushes.Blue

' Create a transform. This transform


' will be used to move the rectangle.
Dim animatedTranslateTransform As New TranslateTransform()

' Register the transform's name with the page


' so that they it be targeted by a Storyboard.
Me.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform)

aRectangle.RenderTransform = animatedTranslateTransform

' Create a Canvas to contain the rectangle


' and add it to the page.
Dim mainPanel As New Canvas()
mainPanel.Width = 400
mainPanel.Height = 400
mainPanel.Children.Add(aRectangle)
Me.Content = mainPanel

' Create the animation path.


Dim animationPath As New PathGeometry()
Dim pFigure As New PathFigure()
pFigure.StartPoint = New Point(10, 100)
Dim pBezierSegment As New PolyBezierSegment()
pBezierSegment.Points.Add(New Point(35, 0))
pBezierSegment.Points.Add(New Point(135, 0))
pBezierSegment.Points.Add(New Point(160, 100))
pBezierSegment.Points.Add(New Point(180, 190))
pBezierSegment.Points.Add(New Point(285, 200))
pBezierSegment.Points.Add(New Point(310, 100))
pFigure.Segments.Add(pBezierSegment)
animationPath.Figures.Add(pFigure)

' Freeze the PathGeometry for performance benefits.


animationPath.Freeze()

' Create a DoubleAnimationUsingPath to move the


' rectangle horizontally along the path by animating
' its TranslateTransform.
Dim translateXAnimation As New DoubleAnimationUsingPath()
translateXAnimation.PathGeometry = animationPath
translateXAnimation.Duration = TimeSpan.FromSeconds(5)

' Set the Source property to X. This makes


' the animation generate horizontal offset values from
' the path information.
translateXAnimation.Source = PathAnimationSource.X

' Set the animation to target the X property


' of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTargetName(translateXAnimation, "AnimatedTranslateTransform")
Storyboard.SetTargetProperty(translateXAnimation, New PropertyPath(TranslateTransform.XProperty))

' Create a DoubleAnimationUsingPath to move the


' rectangle vertically along the path by animating
' its TranslateTransform.
Dim translateYAnimation As New DoubleAnimationUsingPath()
translateYAnimation.PathGeometry = animationPath
translateYAnimation.Duration = TimeSpan.FromSeconds(5)

' Set the Source property to Y. This makes


' the animation generate vertical offset values from
' the path information.
translateYAnimation.Source = PathAnimationSource.Y

' Set the animation to target the Y property


' of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTargetName(translateYAnimation, "AnimatedTranslateTransform")
Storyboard.SetTargetProperty(translateYAnimation, New PropertyPath(TranslateTransform.YProperty))

' Create a Storyboard to contain and apply the animations.


Dim pathAnimationStoryboard As New Storyboard()
pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever
pathAnimationStoryboard.Children.Add(translateXAnimation)
pathAnimationStoryboard.Children.Add(translateYAnimation)
pathAnimationStoryboard.Children.Add(translateYAnimation)

' Start the animations when the rectangle is loaded.


AddHandler aRectangle.Loaded, Sub(sender As Object, e As RoutedEventArgs)
pathAnimationStoryboard.Begin(Me)

End Sub

End Class

End Namespace

Para obtener el ejemplo completo, consulte ejemplo de animación de trazado.


Otra manera de trasladar un objeto mediante una ruta de acceso geométrica es usar un objeto de
MatrixAnimationUsingPath. Para obtener un ejemplo, vea animar un objeto a lo largo de un trazado (animación en
matriz).

Consulte también
Información general sobre animaciones
Temas de procedimientos de animación de trazado
Cómo: Animar un objeto a lo largo de un trazado
(animación en punto)
20/02/2020 • 4 minutes to read • Edit Online

En este ejemplo se muestra cómo utilizar un objeto PointAnimationUsingPath para animar un Point a lo largo de
un trazado curvo.

Ejemplo
En el ejemplo siguiente se mueve una EllipseGeometry a lo largo de un trazado definido por un PathGeometry. La
propiedad Center de la geometría de elipse, que toma un valor Point, especifica su posición; para desplace la
geometría de la elipse, anime su propiedad Center. En el ejemplo se usa un PointAnimationUsingPath para animar
la propiedad Center del objeto EllipseGeometry.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions">
<Canvas Width="400" Height="400">

<Path Fill="Blue" Margin="15,15,15,15">


<Path.Data>

<!-- The EllipseGemetry specifies the shape and position of the Ellipse. The
Center property is animated, causing the Ellipse to animate across the screen-->
<EllipseGeometry x:Name="MyAnimatedEllipseGeometry"
Center="10,100" RadiusX="15" RadiusY="15" />
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard>

<!-- Animates the ellipse along the path. -->


<PointAnimationUsingPath
Storyboard.TargetName="MyAnimatedEllipseGeometry"
Storyboard.TargetProperty="Center"
Duration="0:0:5"
RepeatBehavior="Forever" >
<PointAnimationUsingPath.PathGeometry>
<PathGeometry
Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"
PresentationOptions:Freeze="True" />
</PointAnimationUsingPath.PathGeometry>
</PointAnimationUsingPath>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Canvas>
</Page>

using System;
using System.Windows;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SDKSample
{

public class PointAnimationUsingPathExample : Page


{

public PointAnimationUsingPathExample()
{

// Create a NameScope for the page so that


// we can use Storyboards.
NameScope.SetNameScope(this, new NameScope());

// Create the EllipseGeometry to animate.


EllipseGeometry animatedEllipseGeometry =
new EllipseGeometry(new Point(10, 100), 15, 15);

// Register the EllipseGeometry's name with


// the page so that it can be targeted by a
// storyboard.
this.RegisterName("AnimatedEllipseGeometry", animatedEllipseGeometry);

// Create a Path element to display the geometry.


Path ellipsePath = new Path();
ellipsePath.Data = animatedEllipseGeometry;
ellipsePath.Fill = Brushes.Blue;
ellipsePath.Margin = new Thickness(15);

// Create a Canvas to contain ellipsePath


// and add it to the page.
Canvas mainPanel = new Canvas();
mainPanel.Width = 400;
mainPanel.Height = 400;
mainPanel.Children.Add(ellipsePath);
this.Content = mainPanel;

// Create the animation path.


PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = new Point(10, 100);
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(new Point(35, 0));
pBezierSegment.Points.Add(new Point(135, 0));
pBezierSegment.Points.Add(new Point(160, 100));
pBezierSegment.Points.Add(new Point(180, 190));
pBezierSegment.Points.Add(new Point(285, 200));
pBezierSegment.Points.Add(new Point(310, 100));
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);

// Freeze the PathGeometry for performance benefits.


animationPath.Freeze();

// Create a PointAnimationgUsingPath to move


// the EllipseGeometry along the animation path.
PointAnimationUsingPath centerPointAnimation =
new PointAnimationUsingPath();
centerPointAnimation.PathGeometry = animationPath;
centerPointAnimation.Duration = TimeSpan.FromSeconds(5);
centerPointAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the animation to target the Center property


// of the EllipseGeometry named "AnimatedEllipseGeometry".
// of the EllipseGeometry named "AnimatedEllipseGeometry".
Storyboard.SetTargetName(centerPointAnimation, "AnimatedEllipseGeometry");
Storyboard.SetTargetProperty(centerPointAnimation,
new PropertyPath(EllipseGeometry.CenterProperty));

// Create a Storyboard to contain and apply the animation.


Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
pathAnimationStoryboard.AutoReverse = true;
pathAnimationStoryboard.Children.Add(centerPointAnimation);

// Start the Storyboard when ellipsePath is loaded.


ellipsePath.Loaded += delegate(object sender, RoutedEventArgs e)
{
// Start the storyboard.
pathAnimationStoryboard.Begin(this);
};
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Namespace SDKSample

Public Class PointAnimationUsingPathExample


Inherits Page

Public Sub New()

' Create a NameScope for the page so that


' we can use Storyboards.
NameScope.SetNameScope(Me, New NameScope())

' Create the EllipseGeometry to animate.


Dim animatedEllipseGeometry As New EllipseGeometry(New Point(10, 100), 15, 15)

' Register the EllipseGeometry's name with


' the page so that it can be targeted by a
' storyboard.
Me.RegisterName("AnimatedEllipseGeometry", animatedEllipseGeometry)

' Create a Path element to display the geometry.


Dim ellipsePath As New Path()
ellipsePath.Data = animatedEllipseGeometry
ellipsePath.Fill = Brushes.Blue
ellipsePath.Margin = New Thickness(15)

' Create a Canvas to contain ellipsePath


' and add it to the page.
Dim mainPanel As New Canvas()
mainPanel.Width = 400
mainPanel.Height = 400
mainPanel.Children.Add(ellipsePath)
Me.Content = mainPanel

' Create the animation path.


Dim animationPath As New PathGeometry()
Dim pFigure As New PathFigure()
pFigure.StartPoint = New Point(10, 100)
pFigure.StartPoint = New Point(10, 100)
Dim pBezierSegment As New PolyBezierSegment()
pBezierSegment.Points.Add(New Point(35, 0))
pBezierSegment.Points.Add(New Point(135, 0))
pBezierSegment.Points.Add(New Point(160, 100))
pBezierSegment.Points.Add(New Point(180, 190))
pBezierSegment.Points.Add(New Point(285, 200))
pBezierSegment.Points.Add(New Point(310, 100))
pFigure.Segments.Add(pBezierSegment)
animationPath.Figures.Add(pFigure)

' Freeze the PathGeometry for performance benefits.


animationPath.Freeze()

' Create a PointAnimationgUsingPath to move


' the EllipseGeometry along the animation path.
Dim centerPointAnimation As New PointAnimationUsingPath()
centerPointAnimation.PathGeometry = animationPath
centerPointAnimation.Duration = TimeSpan.FromSeconds(5)
centerPointAnimation.RepeatBehavior = RepeatBehavior.Forever

' Set the animation to target the Center property


' of the EllipseGeometry named "AnimatedEllipseGeometry".
Storyboard.SetTargetName(centerPointAnimation, "AnimatedEllipseGeometry")
Storyboard.SetTargetProperty(centerPointAnimation, New
PropertyPath(EllipseGeometry.CenterProperty))

' Create a Storyboard to contain and apply the animation.


Dim pathAnimationStoryboard As New Storyboard()
pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever
pathAnimationStoryboard.AutoReverse = True
pathAnimationStoryboard.Children.Add(centerPointAnimation)

' Start the Storyboard when ellipsePath is loaded.


AddHandler ellipsePath.Loaded, Sub(sender As Object, e As RoutedEventArgs)
pathAnimationStoryboard.Begin(Me)
End Sub

End Class

End Namespace

Para obtener el ejemplo completo, consulte ejemplo de animación de trazado.


La versión de código del ejemplo anterior usaba un Storyboard para animar el EllipseGeometry, aunque solo se
aplicó una animación. Una Storyboard suele ser la manera más fácil de aplicar varias animaciones porque estas
animaciones pueden controlarse mediante el mismo Storyboard. Sin embargo, una manera más fácil de aplicar
una animación única a una propiedad cuando se usa código es usar el método BeginAnimation. Para obtener un
ejemplo, vea Animar una propiedad sin utilizar un guión gráfico.

Consulte también
Ejemplo de animación de trazado
Información general sobre animaciones
Temas de procedimientos de animación de trazado
Cómo: Animar un objeto a lo largo de una
trayectoria (animación de matriz)
20/02/2020 • 4 minutes to read • Edit Online

En este ejemplo se muestra cómo usar la clase MatrixAnimationUsingPath para animar un objeto a lo largo de un
trazado definido por un PathGeometry.

Ejemplo
En el ejemplo siguiente se anima un objeto a lo largo de un trazado haciendo lo siguiente:
Aplica un MatrixTransform al objeto para moverlo.
Define la ruta de acceso mediante un PathGeometry.
Crea un MatrixAnimationUsingPath y lo usa para animar la propiedad Matrix de la MatrixTransform. El
MatrixAnimationUsingPath toma el PathGeometry y lo utiliza para generar valores Matrix.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions" Margin="20">
<Canvas Width="400" Height="400">

<!-- The Button that is animated across the screen by animating


the MatrixTransform applied to the button. -->
<Button MinWidth="100" Content="A Button">
<Button.RenderTransform>
<MatrixTransform x:Name="ButtonMatrixTransform" />
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard>
<MatrixAnimationUsingPath
Storyboard.TargetName="ButtonMatrixTransform"
Storyboard.TargetProperty="Matrix"
Duration="0:0:5"
RepeatBehavior="Forever" >
<MatrixAnimationUsingPath.PathGeometry>
<PathGeometry
Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"
PresentationOptions:Freeze="True" />
</MatrixAnimationUsingPath.PathGeometry>
</MatrixAnimationUsingPath>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
</Page>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SDKSample
{

/// <summary>
/// Shows how to animate an object along
/// a geometric path.
/// </summary>
public class MatrixAnimationUsingPathExample : Page
{

public MatrixAnimationUsingPathExample()
{
this.Margin = new Thickness(20);

// Create a NameScope for the page so that


// we can use Storyboards.
NameScope.SetNameScope(this, new NameScope());

// Create a button.
Button aButton = new Button();
aButton.MinWidth = 100;
aButton.Content = "A Button";

// Create a MatrixTransform. This transform


// will be used to move the button.
MatrixTransform buttonMatrixTransform = new MatrixTransform();
aButton.RenderTransform = buttonMatrixTransform;

// Register the transform's name with the page


// so that it can be targeted by a Storyboard.
this.RegisterName("ButtonMatrixTransform", buttonMatrixTransform);

// Create a Canvas to contain the button


// and add it to the page.
// Although this example uses a Canvas,
// any type of panel will work.
Canvas mainPanel = new Canvas();
mainPanel.Width = 400;
mainPanel.Height = 400;
mainPanel.Children.Add(aButton);
this.Content = mainPanel;

// Create the animation path.


PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = new Point(10, 100);
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(new Point(35, 0));
pBezierSegment.Points.Add(new Point(135, 0));
pBezierSegment.Points.Add(new Point(160, 100));
pBezierSegment.Points.Add(new Point(180, 190));
pBezierSegment.Points.Add(new Point(285, 200));
pBezierSegment.Points.Add(new Point(310, 100));
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);

// Freeze the PathGeometry for performance benefits.


animationPath.Freeze();

// Create a MatrixAnimationUsingPath to move the


// button along the path by animating
// its MatrixTransform.
MatrixAnimationUsingPath matrixAnimation =
new MatrixAnimationUsingPath();
matrixAnimation.PathGeometry = animationPath;
matrixAnimation.Duration = TimeSpan.FromSeconds(5);
matrixAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the animation to target the Matrix property


// of the MatrixTransform named "ButtonMatrixTransform".
Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform");
Storyboard.SetTargetProperty(matrixAnimation,
new PropertyPath(MatrixTransform.MatrixProperty));

// Create a Storyboard to contain and apply the animation.


Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.Children.Add(matrixAnimation);

// Start the storyboard when the button is loaded.


aButton.Loaded += delegate(object sender, RoutedEventArgs e)
{
// Start the storyboard.
pathAnimationStoryboard.Begin(this);
};
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Namespace SDKSample

''' <summary>
''' Shows how to animate an object along
''' a geometric path.
''' </summary>
Public Class MatrixAnimationUsingPathExample
Inherits Page

Public Sub New()


Me.Margin = New Thickness(20)

' Create a NameScope for the page so that


' we can use Storyboards.
NameScope.SetNameScope(Me, New NameScope())

' Create a button.


Dim aButton As New Button()
aButton.MinWidth = 100
aButton.Content = "A Button"

' Create a MatrixTransform. This transform


' will be used to move the button.
Dim buttonMatrixTransform As New MatrixTransform()
aButton.RenderTransform = buttonMatrixTransform

' Register the transform's name with the page


' so that it can be targeted by a Storyboard.
Me.RegisterName("ButtonMatrixTransform", buttonMatrixTransform)

' Create a Canvas to contain the button


' and add it to the page.
' Although this example uses a Canvas,
' any type of panel will work.
Dim mainPanel As New Canvas()
mainPanel.Width = 400
mainPanel.Height = 400
mainPanel.Children.Add(aButton)
Me.Content = mainPanel

' Create the animation path.


Dim animationPath As New PathGeometry()
Dim pFigure As New PathFigure()
pFigure.StartPoint = New Point(10, 100)
Dim pBezierSegment As New PolyBezierSegment()
pBezierSegment.Points.Add(New Point(35, 0))
pBezierSegment.Points.Add(New Point(135, 0))
pBezierSegment.Points.Add(New Point(160, 100))
pBezierSegment.Points.Add(New Point(180, 190))
pBezierSegment.Points.Add(New Point(285, 200))
pBezierSegment.Points.Add(New Point(310, 100))
pFigure.Segments.Add(pBezierSegment)
animationPath.Figures.Add(pFigure)

' Freeze the PathGeometry for performance benefits.


animationPath.Freeze()

' Create a MatrixAnimationUsingPath to move the


' button along the path by animating
' its MatrixTransform.
Dim matrixAnimation As New MatrixAnimationUsingPath()
matrixAnimation.PathGeometry = animationPath
matrixAnimation.Duration = TimeSpan.FromSeconds(5)
matrixAnimation.RepeatBehavior = RepeatBehavior.Forever

' Set the animation to target the Matrix property


' of the MatrixTransform named "ButtonMatrixTransform".
Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform")
Storyboard.SetTargetProperty(matrixAnimation, New PropertyPath(MatrixTransform.MatrixProperty))

' Create a Storyboard to contain and apply the animation.


Dim pathAnimationStoryboard As New Storyboard()
pathAnimationStoryboard.Children.Add(matrixAnimation)

' Start the storyboard when the button is loaded.


AddHandler aButton.Loaded, Sub(sender As Object, e As RoutedEventArgs)
pathAnimationStoryboard.Begin(Me)

End Sub
End Class
End Namespace

Para obtener el ejemplo completo, consulte ejemplo de animación de trazado. Para obtener más información
sobre las rutas de acceso geométricas, vea información general sobre geometría.

Consulte también
Información general sobre animaciones
Ejemplo de animación de trazado
Temas de procedimientos de animación de trazado
Cómo: Animar un objeto a lo largo de un trazado
(animación en matriz con acumulación de
desplazamiento)
20/02/2020 • 5 minutes to read • Edit Online

En este ejemplo se muestra cómo usar la clase MatrixAnimationUsingPath para animar un objeto a lo largo de un
trazado y hacer que la animación acumule sus valores de desplazamiento a medida que se repite.

Ejemplo
En el ejemplo siguiente se usa el objeto MatrixAnimationUsingPath para animar la propiedad Matrix de un
MatrixTransform aplicado a un botón. Como resultado, un botón se mueve a lo largo de un trazado curvo.
Además, en el ejemplo se establece la propiedad IsOffsetCumulative en true , lo que hace que el desplazamiento
de la matriz animada se acumule a medida que se repite la animación. Dado que el desplazamiento se acumula, el
botón se aleja por la pantalla cuando se repite la animación, en lugar de restablecerse a la posición inicial.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Margin="20"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions">

<Canvas Width="400" Height="400">

<!-- The Button that is animated across the screen by animating


the MatrixTransform applied to the button. -->
<Button MinWidth="100" Content="A Button">
<Button.RenderTransform>
<MatrixTransform x:Name="myMatrixTransform">
<MatrixTransform.Matrix >
<Matrix />
</MatrixTransform.Matrix>
</MatrixTransform>
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<MatrixAnimationUsingPath
Storyboard.TargetName="myMatrixTransform"
Storyboard.TargetProperty="Matrix"
IsOffsetCumulative="True"
Duration="0:0:5"
RepeatBehavior="2x">
<MatrixAnimationUsingPath.PathGeometry>
<PathGeometry
Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"
PresentationOptions:Freeze="True" />
</MatrixAnimationUsingPath.PathGeometry>
</MatrixAnimationUsingPath>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>

</Button>
</Canvas>
</Page>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SDKSample
{

/// <summary>
/// Shows how to use the MatrixAnimationUsingPath.IsOffsetCumulative
/// property to make a MatrixAnimatioinUsingPath accumulate
/// its values when it repeats.
/// </summary>
public class MatrixAnimationUsingPathExampleOffsetCumulative : Page
{

public MatrixAnimationUsingPathExampleOffsetCumulative()
{
this.Margin = new Thickness(20);

// Create a NameScope for the page so that


// we can use Storyboards.
NameScope.SetNameScope(this, new NameScope());

// Create a button.
Button aButton = new Button();
aButton.MinWidth = 100;
aButton.Content = "A Button";

// Create a MatrixTransform. This transform


// will be used to move the button.
MatrixTransform buttonMatrixTransform = new MatrixTransform();
aButton.RenderTransform = buttonMatrixTransform;

// Register the transform's name with the page


// so that it can be targeted by a Storyboard.
this.RegisterName("ButtonMatrixTransform", buttonMatrixTransform);

// Create a Canvas to contain the button


// and add it to the page.
// Although this example uses a Canvas,
// any type of panel will work.
Canvas mainPanel = new Canvas();
mainPanel.Width = 400;
mainPanel.Height = 400;
mainPanel.Children.Add(aButton);
this.Content = mainPanel;

// Create the animation path.


PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = new Point(10, 100);
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(new Point(35, 0));
pBezierSegment.Points.Add(new Point(135, 0));
pBezierSegment.Points.Add(new Point(160, 100));
pBezierSegment.Points.Add(new Point(180, 190));
pBezierSegment.Points.Add(new Point(285, 200));
pBezierSegment.Points.Add(new Point(310, 100));
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);

// Freeze the PathGeometry for performance benefits.


animationPath.Freeze();

// Create a MatrixAnimationUsingPath to move the


// button along the path by animating
// its MatrixTransform.
MatrixAnimationUsingPath matrixAnimation =
new MatrixAnimationUsingPath();
matrixAnimation.PathGeometry = animationPath;

// Set IsOffsetCumulative to true so that the animation


// values accumulate when its repeats.
matrixAnimation.IsOffsetCumulative = true;
matrixAnimation.Duration = TimeSpan.FromSeconds(5);
matrixAnimation.RepeatBehavior = new RepeatBehavior(2);

// Set the animation to target the Matrix property


// of the MatrixTransform named "ButtonMatrixTransform".
Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform");
Storyboard.SetTargetProperty(matrixAnimation,
new PropertyPath(MatrixTransform.MatrixProperty));

// Create a Storyboard to contain and apply the animation.


Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.Children.Add(matrixAnimation);
// Start the animation when the button is clicked.
aButton.Click += delegate(object sender, RoutedEventArgs e)
{
// Start the storyboard.
pathAnimationStoryboard.Begin(this);
};
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Namespace SDKSample

''' <summary>
''' Shows how to use the MatrixAnimationUsingPath.IsOffsetCumulative
''' property to make a MatrixAnimatioinUsingPath accumulate
''' its values when it repeats.
''' </summary>
Public Class MatrixAnimationUsingPathExampleOffsetCumulative
Inherits Page

Public Sub New()


Me.Margin = New Thickness(20)

' Create a NameScope for the page so that


' we can use Storyboards.
NameScope.SetNameScope(Me, New NameScope())

' Create a button.


Dim aButton As New Button()
aButton.MinWidth = 100
aButton.Content = "A Button"

' Create a MatrixTransform. This transform


' will be used to move the button.
Dim buttonMatrixTransform As New MatrixTransform()
aButton.RenderTransform = buttonMatrixTransform

' Register the transform's name with the page


' so that it can be targeted by a Storyboard.
Me.RegisterName("ButtonMatrixTransform", buttonMatrixTransform)

' Create a Canvas to contain the button


' and add it to the page.
' Although this example uses a Canvas,
' any type of panel will work.
Dim mainPanel As New Canvas()
mainPanel.Width = 400
mainPanel.Height = 400
mainPanel.Children.Add(aButton)
Me.Content = mainPanel

' Create the animation path.


Dim animationPath As New PathGeometry()
Dim pFigure As New PathFigure()
pFigure.StartPoint = New Point(10, 100)
Dim pBezierSegment As New PolyBezierSegment()
pBezierSegment.Points.Add(New Point(35, 0))
pBezierSegment.Points.Add(New Point(135, 0))
pBezierSegment.Points.Add(New Point(160, 100))
pBezierSegment.Points.Add(New Point(180, 190))
pBezierSegment.Points.Add(New Point(285, 200))
pBezierSegment.Points.Add(New Point(310, 100))
pFigure.Segments.Add(pBezierSegment)
animationPath.Figures.Add(pFigure)

' Freeze the PathGeometry for performance benefits.


animationPath.Freeze()

' Create a MatrixAnimationUsingPath to move the


' button along the path by animating
' its MatrixTransform.
Dim matrixAnimation As New MatrixAnimationUsingPath()
matrixAnimation.PathGeometry = animationPath

' Set IsOffsetCumulative to true so that the animation


' values accumulate when its repeats.
matrixAnimation.IsOffsetCumulative = True
matrixAnimation.Duration = TimeSpan.FromSeconds(5)
matrixAnimation.RepeatBehavior = New RepeatBehavior(2)

' Set the animation to target the Matrix property


' of the MatrixTransform named "ButtonMatrixTransform".
Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform")
Storyboard.SetTargetProperty(matrixAnimation, New PropertyPath(MatrixTransform.MatrixProperty))

' Create a Storyboard to contain and apply the animation.


Dim pathAnimationStoryboard As New Storyboard()
pathAnimationStoryboard.Children.Add(matrixAnimation)

' Start the animation when the button is clicked.


AddHandler aButton.Click, Sub(sender As Object, e As RoutedEventArgs)
pathAnimationStoryboard.Begin(Me)

End Sub
End Class
End Namespace

Tenga en cuenta que, aunque la propiedad IsOffsetCumulative hace que los valores de desplazamiento se
acumulen en las repeticiones, no hace que se acumulen los valores de rotación. Para que se acumulen los valores
de rotación, establezca las propiedades DoesRotateWithTangent y IsAngleCumulative de la animación en true .
Para obtener el ejemplo completo, consulte ejemplo de animación de trazado. Para ver un ejemplo en el que se
muestra cómo animar un valor Matrix a lo largo de un trazado sin acumulación de desplazamiento, vea animar un
objeto a lo largo de un trazado (animación en matriz).

Consulte también
Información general sobre animaciones
Temas de procedimientos de animación de trazado
Procedimiento Girar un objeto mediante un trazado
geométrico (animación en matriz)
23/10/2019 • 5 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un MatrixAnimationUsingPath y un MatrixTransform para girar (pivotar)
un objeto a lo largo de un trazado geométrico definido por un PathGeometry objeto.

Ejemplo
En el ejemplo siguiente se usa el MatrixAnimationUsingPath objeto que se va a animar el Matrix propiedad de un
MatrixTransform. El MatrixTransform se aplica a un botón y hace que se mueva a lo largo de un trazado curvo.
Dado que el DoesRotateWithTangent propiedad está establecida en true , el rectángulo gira a lo largo de la
tangente de la ruta de acceso.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions" Margin="20">
<Canvas Width="400" Height="400">

<!-- The Button that is animated across the screen by animating


the MatrixTransform applied to the button. -->
<Button MinWidth="100" Content="A Button">
<Button.RenderTransform>
<MatrixTransform x:Name="ButtonMatrixTransform">
<MatrixTransform.Matrix >
<Matrix />
</MatrixTransform.Matrix>
</MatrixTransform>
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard>
<MatrixAnimationUsingPath
Storyboard.TargetName="ButtonMatrixTransform"
Storyboard.TargetProperty="Matrix"
DoesRotateWithTangent="True"
Duration="0:0:5"
RepeatBehavior="Forever" >
<MatrixAnimationUsingPath.PathGeometry>
<PathGeometry
Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"
PresentationOptions:Freeze="True" />
</MatrixAnimationUsingPath.PathGeometry>
</MatrixAnimationUsingPath>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Canvas>
</Page>

using System;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SDKSample
{

/// <summary>
/// Shows how to animate an object along
/// a geometric path.
/// </summary>
public class MatrixAnimationUsingPathDoesRotateWithTangentExample : Page
{

public MatrixAnimationUsingPathDoesRotateWithTangentExample()
{
this.Margin = new Thickness(20);

// Create a NameScope for the page so that


// we can use Storyboards.
NameScope.SetNameScope(this, new NameScope());

// Create a button.
Button aButton = new Button();
aButton.MinWidth = 100;
aButton.Content = "A Button";

// Create a MatrixTransform. This transform


// will be used to move the button.
MatrixTransform buttonMatrixTransform = new MatrixTransform();
aButton.RenderTransform = buttonMatrixTransform;

// Register the transform's name with the page


// so that it can be targeted by a Storyboard.
this.RegisterName("ButtonMatrixTransform", buttonMatrixTransform);

// Create a Canvas to contain the button


// and add it to the page.
// Although this example uses a Canvas,
// any type of panel will work.
Canvas mainPanel = new Canvas();
mainPanel.Width = 400;
mainPanel.Height = 400;
mainPanel.Children.Add(aButton);
this.Content = mainPanel;

// Create the animation path.


PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = new Point(10, 100);
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(new Point(35, 0));
pBezierSegment.Points.Add(new Point(135, 0));
pBezierSegment.Points.Add(new Point(160, 100));
pBezierSegment.Points.Add(new Point(180, 190));
pBezierSegment.Points.Add(new Point(285, 200));
pBezierSegment.Points.Add(new Point(310, 100));
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);

// Freeze the PathGeometry for performance benefits.


animationPath.Freeze();

// Create a MatrixAnimationUsingPath to move the


// button along the path by animating
// its MatrixTransform.
// its MatrixTransform.
MatrixAnimationUsingPath matrixAnimation =
new MatrixAnimationUsingPath();
matrixAnimation.PathGeometry = animationPath;
matrixAnimation.Duration = TimeSpan.FromSeconds(5);
matrixAnimation.RepeatBehavior = RepeatBehavior.Forever;

// Set the animation's DoesRotateWithTangent property


// to true so that rotates the rectangle in addition
// to moving it.
matrixAnimation.DoesRotateWithTangent = true;

// Set the animation to target the Matrix property


// of the MatrixTransform named "ButtonMatrixTransform".
Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform");
Storyboard.SetTargetProperty(matrixAnimation,
new PropertyPath(MatrixTransform.MatrixProperty));

// Create a Storyboard to contain and apply the animation.


Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.Children.Add(matrixAnimation);

// Start the storyboard when the button is loaded.


aButton.Loaded += delegate(object sender, RoutedEventArgs e)
{
// Start the storyboard.
pathAnimationStoryboard.Begin(this);
};
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Namespace SDKSample

''' <summary>
''' Shows how to animate an object along
''' a geometric path.
''' </summary>
Public Class MatrixAnimationUsingPathDoesRotateWithTangentExample
Inherits Page

Public Sub New()


Me.Margin = New Thickness(20)

' Create a NameScope for the page so that


' we can use Storyboards.
NameScope.SetNameScope(Me, New NameScope())

' Create a button.


Dim aButton As New Button()
aButton.MinWidth = 100
aButton.Content = "A Button"

' Create a MatrixTransform. This transform


' will be used to move the button.
Dim buttonMatrixTransform As New MatrixTransform()
aButton.RenderTransform = buttonMatrixTransform

' Register the transform's name with the page


' Register the transform's name with the page
' so that it can be targeted by a Storyboard.
Me.RegisterName("ButtonMatrixTransform", buttonMatrixTransform)

' Create a Canvas to contain the button


' and add it to the page.
' Although this example uses a Canvas,
' any type of panel will work.
Dim mainPanel As New Canvas()
mainPanel.Width = 400
mainPanel.Height = 400
mainPanel.Children.Add(aButton)
Me.Content = mainPanel

' Create the animation path.


Dim animationPath As New PathGeometry()
Dim pFigure As New PathFigure()
pFigure.StartPoint = New Point(10, 100)
Dim pBezierSegment As New PolyBezierSegment()
pBezierSegment.Points.Add(New Point(35, 0))
pBezierSegment.Points.Add(New Point(135, 0))
pBezierSegment.Points.Add(New Point(160, 100))
pBezierSegment.Points.Add(New Point(180, 190))
pBezierSegment.Points.Add(New Point(285, 200))
pBezierSegment.Points.Add(New Point(310, 100))
pFigure.Segments.Add(pBezierSegment)
animationPath.Figures.Add(pFigure)

' Freeze the PathGeometry for performance benefits.


animationPath.Freeze()

' Create a MatrixAnimationUsingPath to move the


' button along the path by animating
' its MatrixTransform.
Dim matrixAnimation As New MatrixAnimationUsingPath()
matrixAnimation.PathGeometry = animationPath
matrixAnimation.Duration = TimeSpan.FromSeconds(5)
matrixAnimation.RepeatBehavior = RepeatBehavior.Forever

' Set the animation's DoesRotateWithTangent property


' to true so that rotates the rectangle in addition
' to moving it.
matrixAnimation.DoesRotateWithTangent = True

' Set the animation to target the Matrix property


' of the MatrixTransform named "ButtonMatrixTransform".
Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform")
Storyboard.SetTargetProperty(matrixAnimation, New PropertyPath(MatrixTransform.MatrixProperty))

' Create a Storyboard to contain and apply the animation.


Dim pathAnimationStoryboard As New Storyboard()
pathAnimationStoryboard.Children.Add(matrixAnimation)

' Start the storyboard when the button is loaded.


AddHandler aButton.Loaded, Sub(sender As Object, e As RoutedEventArgs)
pathAnimationStoryboard.Begin(Me)

End Sub
End Class
End Namespace

Para obtener un ejemplo completo, vea ejemplo de animación de trazado.


La versión del código del ejemplo anterior utiliza un Storyboard para animar el EllipseGeometry, aunque se
aplique solo a una animación. Una manera más fácil de aplicar una animación única a una propiedad en el código
es usar el BeginAnimation método. Para obtener un ejemplo, vea Animar una propiedad sin utilizar un guión
gráfico.

Vea también
Información general sobre animaciones
Temas de procedimientos de animación de trazado
Ejemplo de animación de trazado
Procedimiento Girar un objeto mediante un trazado
geométrico
23/10/2019 • 7 minutes to read • Edit Online

En este ejemplo se muestra cómo girar (pivotar) un objeto a lo largo de un trazado geométrico definido por un
PathGeometry objeto.

Ejemplo
El ejemplo siguiente utiliza tres DoubleAnimationUsingPath objetos que se va a mover un rectángulo a lo largo de
un trazado geométrico.
La primera DoubleAnimationUsingPath anima un RotateTransform que se aplica al rectángulo. La
animación genera valores de ángulo. Hace que el rectángulo gire (pivote) a lo largo de los contornos del
trazado.
Los otros dos objetos animan la X y Y valores de un TranslateTransform que se aplica al rectángulo. Hacen
que el rectángulo se mueva horizontal y verticalmente a lo largo del trazado.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions">
<Page.Resources>

<!-- This is the geometry creates the animation path. Because


this example uses it multiple times, it's declared as a resource and
frozen to improve performance. -->
<PathGeometry x:Key="AnimationPath"
Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"
PresentationOptions:Freeze="True" />
</Page.Resources>

<Canvas Width="400" Height="400">

<!-- The object to animate. -->


<Rectangle
Width="30" Height="30" Fill="Blue">
<Rectangle.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="AnimatedRotateTransform" />
<TranslateTransform x:Name="AnimatedTranslateTransform" />
</TransformGroup>
</Rectangle.RenderTransform>

<Rectangle.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever" AutoReverse="True" >

<!-- Generates angle values (in degrees) from


the path. This animation is used to
rotate the rectangle. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedRotateTransform"
Storyboard.TargetProperty="Angle"
PathGeometry="{StaticResource AnimationPath}"
Source="Angle"
Duration="0:0:5" />

<!-- Generates horizontal offset values from


the path. This animation is used to
animate the rectangle horizontally. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="X"
PathGeometry="{StaticResource AnimationPath}"
Source="X"
Duration="0:0:5" />

<!-- Generates vertical offset values from


the path. This animation is used to move
the rectangle vertically. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="Y"
PathGeometry="{StaticResource AnimationPath}"
Source="Y"
Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
</Page>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SDKSample
{

public class RotateAnimationUsingPathExample : Page


{

public RotateAnimationUsingPathExample()
{

// Create a NameScope for the page so that


// we can use Storyboards.
NameScope.SetNameScope(this, new NameScope());

// Create a rectangle.
Rectangle aRectangle = new Rectangle();
aRectangle.Width = 30;
aRectangle.Height = 30;
aRectangle.Fill = Brushes.Blue;

// Create some transforms. These transforms


// will be used to move and rotate the rectangle.
RotateTransform animatedRotateTransform =
new RotateTransform();
TranslateTransform animatedTranslateTransform =
new TranslateTransform();
// Register the transforms' names with the page
// so that they can be targeted by a Storyboard.
this.RegisterName("AnimatedRotateTransform", animatedRotateTransform);
this.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform);

// Create a TransformGroup to contain the transforms


// and apply the TransformGroup to the rectangle.
TransformGroup tGroup = new TransformGroup();
tGroup.Children.Add(animatedRotateTransform);
tGroup.Children.Add(animatedTranslateTransform);
aRectangle.RenderTransform = tGroup;

// Create a Canvas to contain the rectangle


// and add it to the page.
Canvas mainPanel = new Canvas();
mainPanel.Width = 400;
mainPanel.Height = 400;
mainPanel.Children.Add(aRectangle);
this.Content = mainPanel;

// Create the animation path.


PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = new Point(10, 100);
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(new Point(35, 0));
pBezierSegment.Points.Add(new Point(135, 0));
pBezierSegment.Points.Add(new Point(160, 100));
pBezierSegment.Points.Add(new Point(180, 190));
pBezierSegment.Points.Add(new Point(285, 200));
pBezierSegment.Points.Add(new Point(310, 100));
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);

// Freeze the PathGeometry for performance benefits.


animationPath.Freeze();

// Create a DoubleAnimationUsingPath to rotate the


// rectangle with the path by animating
// its RotateTransform.
DoubleAnimationUsingPath angleAnimation =
new DoubleAnimationUsingPath();
angleAnimation.PathGeometry = animationPath;
angleAnimation.Duration = TimeSpan.FromSeconds(5);

// Set the Source property to Angle. This makes


// the animation generate angle values from
// the path information.
angleAnimation.Source = PathAnimationSource.Angle;

// Set the animation to target the Angle property


// of the RotateTransform named "AnimatedRotateTransform".
Storyboard.SetTargetName(angleAnimation, "AnimatedRotateTransform");
Storyboard.SetTargetProperty(angleAnimation,
new PropertyPath(RotateTransform.AngleProperty));

// Create a DoubleAnimationUsingPath to move the


// rectangle horizontally along the path by animating
// its TranslateTransform.
DoubleAnimationUsingPath translateXAnimation =
new DoubleAnimationUsingPath();
translateXAnimation.PathGeometry = animationPath;
translateXAnimation.Duration = TimeSpan.FromSeconds(5);

// Set the Source property to X. This makes


// the animation generate horizontal offset values from
// the path information.
translateXAnimation.Source = PathAnimationSource.X;
// Set the animation to target the X property
// of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTargetName(translateXAnimation, "AnimatedTranslateTransform");
Storyboard.SetTargetProperty(translateXAnimation,
new PropertyPath(TranslateTransform.XProperty));

// Create a DoubleAnimationUsingPath to move the


// rectangle vertically along the path by animating
// its TranslateTransform.
DoubleAnimationUsingPath translateYAnimation =
new DoubleAnimationUsingPath();
translateYAnimation.PathGeometry = animationPath;
translateYAnimation.Duration = TimeSpan.FromSeconds(5);

// Set the Source property to Y. This makes


// the animation generate vertical offset values from
// the path information.
translateYAnimation.Source = PathAnimationSource.Y;

// Set the animation to target the Y property


// of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTargetName(translateYAnimation, "AnimatedTranslateTransform");
Storyboard.SetTargetProperty(translateYAnimation,
new PropertyPath(TranslateTransform.YProperty));

// Create a Storyboard to contain and apply the animations.


Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
pathAnimationStoryboard.AutoReverse = true;
pathAnimationStoryboard.Children.Add(angleAnimation);
pathAnimationStoryboard.Children.Add(translateXAnimation);
pathAnimationStoryboard.Children.Add(translateYAnimation);

// Start the animations when the rectangle is loaded.


aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
// Start the storyboard.
pathAnimationStoryboard.Begin(this);
};
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Namespace SDKSample

Public Class RotateAnimationUsingPathExample


Inherits Page

Public Sub New()

' Create a NameScope for the page so that


' we can use Storyboards.
NameScope.SetNameScope(Me, New NameScope())

' Create a rectangle.


Dim aRectangle As New Rectangle()
aRectangle.Width = 30
aRectangle.Height = 30
aRectangle.Fill = Brushes.Blue

' Create some transforms. These transforms


' will be used to move and rotate the rectangle.
Dim animatedRotateTransform As New RotateTransform()
Dim animatedTranslateTransform As New TranslateTransform()

' Register the transforms' names with the page


' so that they can be targeted by a Storyboard.
Me.RegisterName("AnimatedRotateTransform", animatedRotateTransform)
Me.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform)

' Create a TransformGroup to contain the transforms


' and apply the TransformGroup to the rectangle.
Dim tGroup As New TransformGroup()
tGroup.Children.Add(animatedRotateTransform)
tGroup.Children.Add(animatedTranslateTransform)
aRectangle.RenderTransform = tGroup

' Create a Canvas to contain the rectangle


' and add it to the page.
Dim mainPanel As New Canvas()
mainPanel.Width = 400
mainPanel.Height = 400
mainPanel.Children.Add(aRectangle)
Me.Content = mainPanel

' Create the animation path.


Dim animationPath As New PathGeometry()
Dim pFigure As New PathFigure()
pFigure.StartPoint = New Point(10, 100)
Dim pBezierSegment As New PolyBezierSegment()
pBezierSegment.Points.Add(New Point(35, 0))
pBezierSegment.Points.Add(New Point(135, 0))
pBezierSegment.Points.Add(New Point(160, 100))
pBezierSegment.Points.Add(New Point(180, 190))
pBezierSegment.Points.Add(New Point(285, 200))
pBezierSegment.Points.Add(New Point(310, 100))
pFigure.Segments.Add(pBezierSegment)
animationPath.Figures.Add(pFigure)

' Freeze the PathGeometry for performance benefits.


animationPath.Freeze()

' Create a DoubleAnimationUsingPath to rotate the


' rectangle with the path by animating
' its RotateTransform.
Dim angleAnimation As New DoubleAnimationUsingPath()
angleAnimation.PathGeometry = animationPath
angleAnimation.Duration = TimeSpan.FromSeconds(5)

' Set the Source property to Angle. This makes


' the animation generate angle values from
' the path information.
angleAnimation.Source = PathAnimationSource.Angle

' Set the animation to target the Angle property


' of the RotateTransform named "AnimatedRotateTransform".
Storyboard.SetTargetName(angleAnimation, "AnimatedRotateTransform")
Storyboard.SetTargetProperty(angleAnimation, New PropertyPath(RotateTransform.AngleProperty))

' Create a DoubleAnimationUsingPath to move the


' rectangle horizontally along the path by animating
' its TranslateTransform.
Dim translateXAnimation As New DoubleAnimationUsingPath()
translateXAnimation.PathGeometry = animationPath
translateXAnimation.Duration = TimeSpan.FromSeconds(5)
' Set the Source property to X. This makes
' the animation generate horizontal offset values from
' the path information.
translateXAnimation.Source = PathAnimationSource.X

' Set the animation to target the X property


' of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTargetName(translateXAnimation, "AnimatedTranslateTransform")
Storyboard.SetTargetProperty(translateXAnimation, New PropertyPath(TranslateTransform.XProperty))

' Create a DoubleAnimationUsingPath to move the


' rectangle vertically along the path by animating
' its TranslateTransform.
Dim translateYAnimation As New DoubleAnimationUsingPath()
translateYAnimation.PathGeometry = animationPath
translateYAnimation.Duration = TimeSpan.FromSeconds(5)

' Set the Source property to Y. This makes


' the animation generate vertical offset values from
' the path information.
translateYAnimation.Source = PathAnimationSource.Y

' Set the animation to target the Y property


' of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTargetName(translateYAnimation, "AnimatedTranslateTransform")
Storyboard.SetTargetProperty(translateYAnimation, New PropertyPath(TranslateTransform.YProperty))

' Create a Storyboard to contain and apply the animations.


Dim pathAnimationStoryboard As New Storyboard()
pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever
pathAnimationStoryboard.AutoReverse = True
pathAnimationStoryboard.Children.Add(angleAnimation)
pathAnimationStoryboard.Children.Add(translateXAnimation)
pathAnimationStoryboard.Children.Add(translateYAnimation)

' Start the animations when the rectangle is loaded.


AddHandler aRectangle.Loaded, Sub(sender As Object, e As RoutedEventArgs)
pathAnimationStoryboard.Begin(Me)

End Sub

End Class

End Namespace

Otra manera de girar un objeto utilizando un trazado geométrico es usar un MatrixAnimationUsingPath de objeto
y establecer su DoesRotateWithTangent propiedad true . Para obtener más información y un ejemplo, vea girar
un objeto utilizando un trazado geométrico (animación en matriz).
Para obtener un ejemplo completo, vea ejemplo de animación de trazado.

Vea también
Información general sobre animaciones
Ejemplo de animación de trazado
Temas de procedimientos de animación de trazado
Información general sobre multimedia
29/10/2019 • 13 minutes to read • Edit Online

Las características multimedia de Windows Presentation Foundation (WPF ) le permiten integrar audio y vídeo en
las aplicaciones para mejorar la experiencia del usuario. En este tema se presentan las características multimedia
de WPF.

API multimedia
Las clases MediaElement y MediaPlayer se utilizan para presentar contenido de audio o vídeo. Estas clases se
pueden controlar de manera interactiva o mediante un reloj. Estas clases pueden usar en el control de Microsoft
Windows Media Player 10 para la reproducción multimedia. La clase que se usa depende del escenario.
MediaElement es un UIElement compatible con el diseño y se puede consumir como el contenido de muchos
controles. También se puede usar en Lenguaje XAML (Extensible Application Markup Language) y en el código.
por otro lado, MediaPlayerestá diseñado para Drawing objetos y carece de compatibilidad con el diseño. Los
medios cargados con un MediaPlayer solo se pueden presentar mediante un VideoDrawing o interactuando
directamente con un DrawingContext. no se puede usar MediaPlayer en XAML.
Para más información sobre los objetos de dibujo y el contexto de dibujo, consulte Información general sobre
objetos Drawing.

NOTE
Al distribuir elementos multimedia con la aplicación, no puede usar un archivo multimedia como recurso del proyecto. En el
archivo de proyecto, debe establecer en su lugar el tipo de elemento multimedia en Content y establecer
CopyToOutputDirectory en PreserveNewest o Always .

Modos de reproducción multimedia


NOTE
Tanto MediaElement como MediaPlayer tienen miembros similares. Los vínculos de esta sección hacen referencia a los
miembros de la clase MediaElement. A menos que se indique específicamente, los miembros vinculados a en la clase
MediaElement también se pueden encontrar en la clase MediaPlayer.

Para entender la reproducción multimedia en Windows Presentation Foundation (WPF ), es preciso entender los
distintos modos en que se pueden reproducir los elementos multimedia. Tanto MediaElement como MediaPlayer
se pueden usar en dos modos de medios diferentes, el modo independiente y el modo de reloj. El modo
multimedia viene determinado por la propiedad Clock. Cuando Clock se null , el objeto multimedia está en
modo independiente. Cuando el Clock no es null, el objeto multimedia está en modo de reloj. De manera
predeterminada, los objetos multimedia están en modo independiente.
Modo independiente
En el modo independiente, el contenido multimedia controla la reproducción multimedia. El modo independiente
habilita las opciones siguientes:
Los Uri del medio se pueden especificar directamente.
La reproducción multimedia se puede controlar directamente.
Las propiedades Position y SpeedRatio del elemento multimedia se pueden modificar.
Los elementos multimedia se cargan estableciendo la propiedad Source del objeto MediaElement o llamando al
método Open del objeto MediaPlayer.
Para controlar la reproducción multimedia en el modo independiente, se pueden usar los métodos de control del
objeto multimedia. Los métodos de control disponibles son Play, Pause, Closey Stop. Por MediaElement, el control
interactivo que usa estos métodos solo está disponible cuando el LoadedBehavior está establecido en Manual.
Estos métodos no están disponible cuando el objeto multimedia está en el modo de reloj.
Consulte Control de un MediaElement (Reproducir, Pausar, Detener, Volumen y Velocidad) para ver un ejemplo
del modo independiente.
Modo de reloj
En el modo de reloj, una MediaTimeline controla la reproducción multimedia. El modo de reloj tiene las
características siguientes:
El Uri del elemento multimedia se establece indirectamente a través de un MediaTimeline.
El reloj puede controlar la reproducción multimedia. No se pueden usar los métodos de control del objeto
multimedia.
Los elementos multimedia se cargan estableciendo la propiedad Source de un objeto MediaTimeline,
creando el reloj desde la escala de tiempo y asignando el reloj al objeto multimedia. Los elementos
multimedia también se cargan de esta manera cuando una MediaTimeline dentro de un Storyboard tiene
como destino una MediaElement.
Para controlar la reproducción multimedia en el modo de reloj, se deben usar los métodos de control de
ClockController. Un ClockController se obtiene de la propiedad ClockController de la MediaClock. Si intenta usar
los métodos de control de un objeto MediaElement o MediaPlayer mientras está en modo de reloj, se producirá
una InvalidOperationException.
Consulte Información general sobre animaciones para más información sobre los relojes y las escalas de tiempo.
Consulte Control de un control MediaElement mediante un guión gráfico para ver un ejemplo del modo de reloj.

Clase MediaElement
Agregar medios a una aplicación es tan sencillo como agregar un control de MediaElement al interfaz de usuario
(UI) de la aplicación y proporcionar un Uri al medio que desea incluir. Todos los tipos de medios admitidos por
Microsoft Windows Media Player 10 se admiten en Windows Presentation Foundation (WPF ). En el ejemplo
siguiente se muestra un uso simple del MediaElement en Lenguaje XAML (Extensible Application Markup
Language).

<!-- This page shows a simple usage of MediaElement -->


<Page x:Class="MediaElementExample.SimpleUsage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SimpleUsage"
>
<StackPanel Margin="20">
<MediaElement Source="media/numbers-aud.wmv" />
</StackPanel>
</Page>

En este ejemplo, el elemento multimedia se reproduce automáticamente en cuanto se carga. Cuando el elemento
multimedia termina de reproducirse se cierra y se liberan todos los recursos multimedia (incluso la memoria de
vídeo). Éste es el comportamiento predeterminado del objeto MediaElement y se controla mediante las
propiedades LoadedBehavior y UnloadedBehavior.
Control de MediaElement
Las propiedades LoadedBehavior y UnloadedBehavior controlan el comportamiento de la MediaElement cuando
IsLoaded es true o false , respectivamente. El MediaState las propiedades se establecen para que afecten al
comportamiento de la reproducción multimedia. Por ejemplo, la LoadedBehavior predeterminada es Play y se
Closela UnloadedBehavior predeterminada. Esto significa que, tan pronto como se carga el MediaElement y se
completa el prelanzamiento, el medio comienza a reproducirse. Cuando se completa la reproducción, el elemento
multimedia se cierra y se liberan todos los recursos multimedia.
Las propiedades LoadedBehavior y UnloadedBehavior no son la única manera de controlar la reproducción
multimedia. En el modo de reloj, el reloj puede controlar el MediaElement y los métodos de control interactivos
tienen control cuando se Manualla LoadedBehavior. MediaElement controla esta competición para el control
mediante la evaluación de las siguientes prioridades.
1. UnloadedBehaviorOperador Vigente cuando el elemento multimedia está descargado. Esto garantiza que
todos los recursos multimedia se liberan de forma predeterminada, incluso cuando un MediaClock está
asociado a la MediaElement.
2. MediaClockOperador En contexto, cuando el contenido multimedia tiene una Clock. Si el medio se
descarga, el MediaClock surtirá efecto mientras se Manualel UnloadedBehavior. El modo de reloj siempre
invalida el comportamiento cargado del MediaElement.
3. LoadedBehaviorOperador Vigente cuando el elemento multimedia está cargado.
4. Métodos de control interactivos. Se aplica cuando se Manualla LoadedBehavior. Los métodos de control
disponibles son Play, Pause, Closey Stop.
Visualización de MediaElement
Para mostrar una MediaElement debe tener contenido para representarse y tendrá sus propiedades ActualWidth
y ActualHeight establecidas en cero hasta que se cargue el contenido. Para contenido de solo audio, estas
propiedades siempre son cero. En el caso de contenido de vídeo, una vez que se ha generado el evento
MediaOpened, el ActualWidth y ActualHeight informarán del tamaño del medio cargado. Esto significa que hasta
que se cargue el medio, el MediaElement no ocupará ningún espacio físico en el interfaz de usuario (UI) a menos
que se establezcan las propiedades Width o Height.
El establecimiento de las propiedades Width y Height hará que los elementos multimedia se expandan para
rellenar el área proporcionada para el MediaElement. Para conservar la relación de aspecto original del elemento
multimedia, debe establecerse la propiedad Width o Height, pero no ambas. Establecer las propiedades Width y
Height hará que los elementos multimedia presenten en un tamaño de elemento fijo que puede no ser deseable.
Para evitar tener un elemento de tamaño fijo, Windows Presentation Foundation (WPF ) puede preprocesar el
elemento multimedia. Esto se hace estableciendo el LoadedBehavior en Play o Pause. En un estado Pause, el
elemento multimedia se preprocesará y presentará el primer fotograma. En un estado Play, los elementos
multimedia se preprocesarán y comenzarán a reproducirse.

Clase MediaPlayer
Mientras que la clase MediaElement es un elemento de marco, la clase MediaPlayer está diseñada para utilizarse
en objetos Drawing. Los objetos de dibujo se usan cuando se pueden sacrificar las características del nivel de
marco para obtener ventajas de rendimiento o cuando se necesitan Freezable características. MediaPlayer le
permite aprovechar estas características a la vez que proporciona contenido multimedia en las aplicaciones. Como
MediaElement, MediaPlayer se puede usar en modo independiente o de reloj, pero no tiene los Estados de
descarga y carga del objeto MediaElement. Esto reduce la complejidad del control de reproducción de la
MediaPlayer.
Control de MediaPlayer
Dado que MediaPlayer no tiene estado, hay solo dos maneras de controlar la reproducción multimedia.
1. Métodos de control interactivos. En contexto, en el modo independiente ( null propiedadClock).
2. MediaClockOperador En contexto, cuando el contenido multimedia tiene una Clock.
Visualización de MediaPlayer
Técnicamente, no se puede mostrar un MediaPlayer porque no tiene ninguna representación física. Sin embargo,
se puede usar para presentar elementos multimedia en un Drawing mediante la clase VideoDrawing. En el
ejemplo siguiente se muestra el uso de un VideoDrawing para mostrar los elementos multimedia.

//
// Create a VideoDrawing.
//
MediaPlayer player = new MediaPlayer();

player.Open(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));

VideoDrawing aVideoDrawing = new VideoDrawing();

aVideoDrawing.Rect = new Rect(0, 0, 100, 100);

aVideoDrawing.Player = player;

// Play the video once.


player.Play();

Vea la información General sobre objetos de dibujo para obtener más información sobre los objetos de Drawing.

Vea también
DrawingGroup
Diseño
Temas "Cómo..."
Temas "Cómo..." de audio y vídeo
23/10/2019 • 2 minutes to read • Edit Online

Los temas siguientes muestran cómo usar el MediaElement para integrar el contenido de audio y vídeo en sus
aplicaciones.

En esta sección
Controlar un MediaElement (Reproducir, Pausar, Detener, Volumen y Velocidad)
Controlar un control MediaElement mediante un guión gráfico
Desencadenar la reproducción de medios con un evento de usuario
Repetir reproducción multimedia
Reproducir medios con animaciones
Usar transformaciones en un control MediaElement

Referencia
MediaElement
MediaPlayer
MediaTimeline

Secciones relacionadas
Gráficos y multimedia
Procedimiento Controlar un control MediaElement
(Reproducir, Pausar, Detener, Volumen y Velocidad)
23/10/2019 • 5 minutes to read • Edit Online

En el ejemplo siguiente se muestra cómo controlar la reproducción de medios MediaElementmediante. En el


ejemplo se crea un reproductor multimedia sencillo que permite reproducir, pausar, detener y saltar hacia atrás y
hacia delante en el medio, así como ajustar el volumen y la proporción de velocidad.

Ejemplo
El código siguiente crea la interfaz de usuario.

NOTE
La LoadedBehavior propiedad de MediaElement debe establecerse en Manual para poder detener, pausar y reproducir los
medios interactivamente.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MediaElementExample" >

<StackPanel Background="Black">

<!-- To interactively stop, pause, and play the media, the LoadedBehavior
property of the MediaElement must be set to "Manual". -->
<MediaElement Source="media\numbers.wmv" Name="myMediaElement"
Width="450" Height="250" LoadedBehavior="Manual" UnloadedBehavior="Stop" Stretch="Fill"
MediaOpened="Element_MediaOpened" MediaEnded="Element_MediaEnded"/>

<StackPanel HorizontalAlignment="Center" Width="450" Orientation="Horizontal">

<!-- Play button. -->


<Image Source="images\UI_play.gif" MouseDown="OnMouseDownPlayMedia" Margin="5" />

<!-- Pause button. -->


<Image Source="images\UI_pause.gif" MouseDown="OnMouseDownPauseMedia" Margin="5" />

<!-- Stop button. -->


<Image Source="images\UI_stop.gif" MouseDown="OnMouseDownStopMedia" Margin="5" />

<!-- Volume slider. This slider allows a Volume range between 0 and 1. -->
<TextBlock Foreground="White" VerticalAlignment="Center" Margin="5" >Volume</TextBlock>
<Slider Name="volumeSlider" VerticalAlignment="Center" ValueChanged="ChangeMediaVolume"
Minimum="0" Maximum="1" Value="0.5" Width="70"/>

<!-- Volume slider. This slider allows you to change the speed of the media playback. -->
<TextBlock Foreground="White" Margin="5" VerticalAlignment="Center">Speed</TextBlock>
<Slider Name="speedRatioSlider" VerticalAlignment="Center" ValueChanged="ChangeMediaSpeedRatio"
Value="1" Width="70" />

<!-- Seek to slider. Ths slider allows you to jump to different parts of the media playback. -->
<TextBlock Foreground="White" Margin="5" VerticalAlignment="Center">Seek To</TextBlock>
<Slider Name="timelineSlider" Margin="5" ValueChanged="SeekToMediaPosition" Width="70"/>

</StackPanel>
</StackPanel>
</Page>

Ejemplo
El código siguiente implementa la funcionalidad de los controles de interfaz de usuario de ejemplo. Los
Playmétodos Pause, yStop se usan para reproducir, pausar y detener el medio respectivamente. Cambiar la
Position propiedad MediaElement de le permite omitir el contenido multimedia. Por último, Volume las
SpeedRatio propiedades y se usan para ajustar el volumen y la velocidad de reproducción del medio.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Input;

namespace SDKSample
{

public partial class MediaElementExample : Page


{
// Play the media.
void OnMouseDownPlayMedia(object sender, MouseButtonEventArgs args)
{

// The Play method will begin the media if it is not currently active or
// resume media if it is paused. This has no effect if the media is
// already running.
myMediaElement.Play();

// Initialize the MediaElement property values.


InitializePropertyValues();
}

// Pause the media.


void OnMouseDownPauseMedia(object sender, MouseButtonEventArgs args)
{

// The Pause method pauses the media if it is currently running.


// The Play method can be used to resume.
myMediaElement.Pause();
}

// Stop the media.


void OnMouseDownStopMedia(object sender, MouseButtonEventArgs args)
{

// The Stop method stops and resets the media to be played from
// the beginning.
myMediaElement.Stop();
}

// Change the volume of the media.


private void ChangeMediaVolume(object sender, RoutedPropertyChangedEventArgs<double> args)
{
myMediaElement.Volume = (double)volumeSlider.Value;
}

// Change the speed of the media.


private void ChangeMediaSpeedRatio(object sender, RoutedPropertyChangedEventArgs<double> args)
{
myMediaElement.SpeedRatio = (double)speedRatioSlider.Value;
}

// When the media opens, initialize the "Seek To" slider maximum value
// to the total number of miliseconds in the length of the media clip.
private void Element_MediaOpened(object sender, EventArgs e)
{
timelineSlider.Maximum = myMediaElement.NaturalDuration.TimeSpan.TotalMilliseconds;
}

// When the media playback is finished. Stop() the media to seek to media start.
private void Element_MediaEnded(object sender, EventArgs e)
{
myMediaElement.Stop();
}

// Jump to different parts of the media (seek to).


private void SeekToMediaPosition(object sender, RoutedPropertyChangedEventArgs<double> args)
{
int SliderValue = (int)timelineSlider.Value;

// Overloaded constructor takes the arguments days, hours, minutes, seconds, milliseconds.
// Create a TimeSpan with miliseconds equal to the slider value.
TimeSpan ts = new TimeSpan(0, 0, 0, 0, SliderValue);
myMediaElement.Position = ts;
}

void InitializePropertyValues()
{
{
// Set the media's starting Volume and SpeedRatio to the current value of the
// their respective slider controls.
myMediaElement.Volume = (double)volumeSlider.Value;
myMediaElement.SpeedRatio = (double)speedRatioSlider.Value;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Documents
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports System.Windows.Data
Imports System.Windows.Media
Imports System.Windows.Input

Namespace SDKSample

Partial Class MediaElementExample


Inherits Page

' Play the media.


Sub OnMouseDownPlayMedia(ByVal sender As Object, ByVal args As MouseButtonEventArgs)

' The Play method will begin the media if it is not currently active or
' resume media if it is paused. This has no effect if the media is
' already running.
myMediaElement.Play()

' Initialize the MediaElement property values.


InitializePropertyValues()

End Sub

' Pause the media.


Sub OnMouseDownPauseMedia(ByVal sender As Object, ByVal args As MouseButtonEventArgs)

' The Pause method pauses the media if it is currently running.


' The Play method can be used to resume.
myMediaElement.Pause()

End Sub

' Stop the media.


Sub OnMouseDownStopMedia(ByVal sender As Object, ByVal args As MouseButtonEventArgs)

' The Stop method stops and resets the media to be played from
' the beginning.
myMediaElement.Stop()

End Sub

' Change the volume of the media.


Private Sub ChangeMediaVolume(ByVal sender As Object, ByVal args As RoutedPropertyChangedEventArgs(Of
Double))
myMediaElement.Volume = System.Convert.ToDouble(volumeSlider.Value)

End Sub

' Change the speed of the media.


Private Sub ChangeMediaSpeedRatio(ByVal sender As Object, ByVal args As
RoutedPropertyChangedEventArgs(Of Double))
myMediaElement.SpeedRatio = System.Convert.ToDouble(speedRatioSlider.Value)
End Sub

' When the media opens, initialize the "Seek To" slider maximum value
' to the total number of miliseconds in the length of the media clip.
Private Sub Element_MediaOpened(ByVal sender As Object, ByVal args As RoutedEventArgs)
timelineSlider.Maximum = myMediaElement.NaturalDuration.TimeSpan.TotalMilliseconds
End Sub

' When the media playback is finished. Stop() the media to seek to media start.
Private Sub Element_MediaEnded(ByVal sender As Object, ByVal args As RoutedEventArgs)
myMediaElement.Stop()
End Sub

' Jump to different parts of the media (seek to).


Private Sub SeekToMediaPosition(ByVal sender As Object, ByVal args As
RoutedPropertyChangedEventArgs(Of Double))
Dim SliderValue As Integer = CType(timelineSlider.Value, Integer)

' Overloaded constructor takes the arguments days, hours, minutes, seconds, milliseconds.
' Create a TimeSpan with miliseconds equal to the slider value.
Dim ts As New TimeSpan(0, 0, 0, 0, SliderValue)
myMediaElement.Position = ts
End Sub

' Set the media's starting Volume and SpeedRatio to the current value of the
' their respective slider controls.
Private Sub InitializePropertyValues()
myMediaElement.Volume = System.Convert.ToDouble(volumeSlider.Value)
myMediaElement.SpeedRatio = System.Convert.ToDouble(speedRatioSlider.Value)
End Sub
End Class
End Namespace 'SDKSample

Vea también
Controlar un control MediaElement mediante un guión gráfico
Procedimiento Controlar un control MediaElement
mediante un guión gráfico
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo controlar un MediaElement mediante el uso de un MediaTimeline en un


Storyboard.

Ejemplo
Cuando se usa un MediaTimeline en un Storyboard para controlar la temporización de un MediaElement, la
funcionalidad es idéntica a la funcionalidad de otros Timeline objetos, como animaciones. Por ejemplo, un
MediaTimeline usa Timeline propiedades como el BeginTime propiedad para especificar cuándo se debe iniciar
un MediaElement (iniciar la reproducción multimedia). También usa el Duration propiedad para especificar cuánto
tiempo el MediaElement está activo (duración de reproducción multimedia). Para obtener más información sobre
el uso de Timeline los objetos que tienen un Storyboard, consulte Storyboards Overview.
En este ejemplo se muestra cómo crear un Reproductor de medios sencillo que usa un MediaTimeline para
controlar la reproducción. El Reproductor multimedia incluye reproducir, pausar, reanudar y detener los botones.
El Reproductor también tiene un Slider control que actúa como una barra de progreso.
En el ejemplo siguiente se crea el interfaz de usuario (UI) para el Reproductor de medios.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MediaTimelineExample" >

<StackPanel Background="Black">

<MediaElement Name="myMediaElement" MediaOpened="Element_MediaOpened"


Width="260" Height="150" Stretch="Fill" />

<!-- Button controls for play, pause, resume, and stop. -->
<StackPanel HorizontalAlignment="Center" Width="260" Orientation="Horizontal">
<Image Name="PlayButton" Source="images\UI_play.gif" Margin="30,10,10,10" />
<Image Name="PauseButton" Source="images\UI_pause.gif" Margin="10" />
<Image Name="ResumeButton" Source="images\UI_resume.gif" Margin="10" />
<Image Name="StopButton" Source="images\UI_stop.gif" Margin="10" />
</StackPanel>

<!-- Ths slider shows the progress of the media. -->


<Slider Name="timelineSlider" Margin="5" Width="250" HorizontalAlignment="Center"/>

<StackPanel.Triggers>
<EventTrigger RoutedEvent="Image.MouseDown" SourceName="PlayButton">
<EventTrigger.Actions>
<BeginStoryboard Name= "myBegin">

<Storyboard SlipBehavior="Slip">

<!-- The MediaTimeline controls the timing of the video and acts like other Timeline objects.
For example, although the video clip (numbers.wmv) lasts longer, playback ends after six
seconds because that is the duration of the MediaTimeline (Duration="0:0:6"). -->
<MediaTimeline Source="media\numbers.wmv" Storyboard.TargetName="myMediaElement"
BeginTime="0:0:0" Duration="0:0:6" CurrentTimeInvalidated="MediaTimeChanged" />

</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>

<!-- These triggers impliment the functionality of the Pause, Resume


and Stop buttons.-->
<EventTrigger RoutedEvent="Image.MouseDown" SourceName="PauseButton">
<EventTrigger.Actions>
<PauseStoryboard BeginStoryboardName="myBegin" />
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Image.MouseDown" SourceName="ResumeButton">
<EventTrigger.Actions>
<ResumeStoryboard BeginStoryboardName="myBegin" />
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Image.MouseDown" SourceName="StopButton">
<EventTrigger.Actions>
<StopStoryboard BeginStoryboardName="myBegin" />
</EventTrigger.Actions>
</EventTrigger>
</StackPanel.Triggers>

</StackPanel>
</Page>

El ejemplo siguiente crea la funcionalidad de la barra de progreso.


using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace SDKSample
{

public partial class MediaTimelineExample : Page


{
// When the media opens, initialize the "Seek To" slider maximum value
// to the total number of miliseconds in the length of the media clip.
private void Element_MediaOpened(object sender, EventArgs e)
{
timelineSlider.Maximum = myMediaElement.NaturalDuration.TimeSpan.TotalMilliseconds;
}

private void MediaTimeChanged(object sender, EventArgs e)


{
timelineSlider.Value = myMediaElement.Position.TotalMilliseconds;
}
}
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media

Namespace SDKSample

Partial Class MediaTimelineExample


Inherits Page
' When the media opens, initialize the "Seek To" slider maximum value
' to the total number of miliseconds in the length of the media clip.
Private Sub Element_MediaOpened(ByVal sender As Object, ByVal e As RoutedEventArgs)
timelineSlider.Maximum = myMediaElement.NaturalDuration.TimeSpan.TotalMilliseconds

End Sub

Private Sub MediaTimeChanged(ByVal sender As Object, ByVal e As EventArgs)


timelineSlider.Value = myMediaElement.Position.TotalMilliseconds

End Sub
End Class
End Namespace 'SDKSample

Vea también
MediaElement
MediaTimeline
Storyboard
Controlar un MediaElement (Reproducir, Pausar, Detener, Volumen y Velocidad)
Información general sobre objetos Storyboard
Información general sobre animaciones de fotogramas clave
Información general sobre animaciones
Temas "Cómo..."
Gráficos y multimedia
Procedimiento Desencadenar la reproducción de
medios con un evento de usuario
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo sincronizar la reproducción de medios con un evento.

Ejemplo
En el ejemplo siguiente se usa el MediaElement control y el MediaTimeline clase para reproducir un sonido que se
produce cuando el usuario hace clic en un Button.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel>

<!-- The MediaElement control plays the sound. -->


<MediaElement Name="myMediaElement" />

<Button>Click to Hear a Sound!


<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>

<!-- Sound wave from this source is played when the button is clicked.-->
<MediaTimeline Source="C:\WINDOWS\Media\ringin.wav" Storyboard.TargetName="myMediaElement" />

</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>

</StackPanel>
</Page>

Vea también
MediaElement
MediaTimeline
RoutedEvent
Storyboard
Temas "Cómo..."
Gráficos y multimedia
Procedimiento Repetir la reproducción de elementos
multimedia
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo reproducir contenido multimedia indefinidamente, es decir, establecer el
contenido multimedia de manera que se reproduzca en un bucle infinito.

Ejemplo
En el ejemplo siguiente se usa MediaElement y MediaTimeline en un Storyboard para reproducir un clip
multimedia en un bucle infinito.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel>

<!-- The MediaElement control plays the sound. -->


<MediaElement Name="myMediaElement" >
<MediaElement.Triggers>
<EventTrigger RoutedEvent="MediaElement.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>

<!-- The MediaTimeline has a RepeatBehavior="Forever" which makes the media play
over and over indefinitely.-->
<MediaTimeline Source="media\tada.wav" Storyboard.TargetName="myMediaElement"
RepeatBehavior="Forever" />

</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</MediaElement.Triggers>
</MediaElement>

</StackPanel>
</Page>

Vea también
MediaElement
MediaTimeline
Storyboard
Temas "Cómo..."
Gráficos y multimedia
Procedimiento Reproducir elementos multimedia con
animaciones
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo reproducir archivos multimedia y animaciones al mismo tiempo mediante la
MediaTimeline y DoubleAnimationUsingKeyFrames clases en el mismo Storyboard.

Ejemplo
Puede usar uno o varios MediaTimeline objetos en un Storyboard junto con otros usuarios Timeline objetos, como
animaciones.
El ejemplo siguiente se establece la SlipBehavior propiedad de la Storyboard en un valor de Slip , que especifica
que la animación no avanza hasta que avanza la multimedia (el vídeo en este ejemplo). Esta funcionalidad puede
ser necesaria si se retrasa la reproducción multimedia debido al tiempo de carga.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Canvas>

<!-- Upper right hand Canvas contains the animations. -->


<Border BorderBrush="Black" BorderThickness="1" Canvas.Left="250">
<Canvas Width="250" Height="250" Background="White" >

<!-- The two Path elements below create the purple and gold rings
which are animated while the media is played. -->
<Path Stroke="Purple" StrokeThickness="5">
<Path.Data>
<EllipseGeometry x:Name="MyEllipseGeometry"
Center="125,125" RadiusX="15" RadiusY="10" />
</Path.Data>
</Path>
<Path Stroke="Gold" StrokeThickness="5">
<Path.Data>
<EllipseGeometry x:Name="MyEllipseGeometry2"
Center="125,125" RadiusX="10" RadiusY="15" />
</Path.Data>
</Path>
</Canvas>
</Border>

<!-- Upper left hand Canvas contains the video. -->


<Canvas Width="250" Height="250" Background="Green">
<MediaElement Name="myvideo" Width="250" Height="250"
Canvas.Left="0" Canvas.Top="0">
<MediaElement.Triggers>
<EventTrigger RoutedEvent="MediaElement.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>

<!-- This Storyboard contains both media (video in this example) and animations. Note
the SlipBehavior value of "Slip" specifies that the animation does not progress
until the media progresses. This might be desirable if media playback is delayed
because of loading time. -->
<Storyboard SlipBehavior="Slip">

<!-- The MediaTimeline controls the timing of the video and acts like other Timeline
objects.
For example, although the video clip (numbers.wmv) lasts longer, playback ends after six
For example, although the video clip (numbers.wmv) lasts longer, playback ends after six
seconds because that is the duration of the MediaTimeline (Duration="0:0:6"). -->
<MediaTimeline Source="media\numbers.wmv" BeginTime="0:0:0" Duration="0:0:10"/>

<!-- The animations below animate the ellipses in the right hand pane. These animations are
timed to correspond to the counting in the video. -->

<!-- Animate the RadiusY property of the purple ellipse. -->


<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="MyEllipseGeometry"
Storyboard.TargetProperty="RadiusY"
RepeatBehavior="10x">
<DoubleAnimationUsingKeyFrames.KeyFrames>
<LinearDoubleKeyFrame Value="80" KeyTime="0:0:0.4" />
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0" KeyTime="0:0:1" />
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>

<!-- Animate the RadiusX property of the gold ellipse. -->


<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="MyEllipseGeometry2"
Storyboard.TargetProperty="RadiusX"
RepeatBehavior="10x">
<DoubleAnimationUsingKeyFrames.KeyFrames>
<LinearDoubleKeyFrame Value="80" KeyTime="0:0:0.4" />
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0" KeyTime="0:0:1" />
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>

</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</MediaElement.Triggers>
</MediaElement>
</Canvas>

</Canvas>
</Page>

Vea también
MediaTimeline
DoubleAnimationUsingKeyFrames
Storyboard
SlipBehavior
Temas "Cómo..."
Información general sobre objetos Storyboard
Información general sobre animaciones de fotogramas clave
Información general sobre animaciones
Gráficos y multimedia
Procedimiento Usar transformaciones en un control
MediaElement
23/10/2019 • 2 minutes to read • Edit Online

En este ejemplo se muestra cómo usar un RotateTransform en un MediaElement.

Ejemplo
En el marcado siguiente, el MediaElement se gira mediante un RotateTransform.

<MediaElement Source="media/numbers-aud.wmv">
<MediaElement.LayoutTransform>
<TransformGroup>
<RotateTransform Angle="305" />
</TransformGroup>
</MediaElement.LayoutTransform>
</MediaElement>
Programación de capas visuales
23/10/2019 • 2 minutes to read • Edit Online

El Visual objeto es un núcleo WPF objeto, cuyo rol principal es proporcionar compatibilidad con la representación.
Controles de interfaz de usuario, como Button y TextBox, derivan de la Visual clase y usarla para conservar sus
datos de representación.

En esta sección
Realizar pruebas de posicionamiento en la capa visual
Usar objetos DrawingVisual
Tutorial: Hospedar objetos visuales en una aplicación Win32
Temas "Cómo..."

Vea también
Visual
VisualTreeHelper
DrawingVisual
Información general sobre la representación de gráficos en WPF
Gráficos y multimedia
Realizar pruebas de posicionamiento en la capa
visual
20/02/2020 • 23 minutes to read • Edit Online

En este tema se proporciona información general sobre la funcionalidad de prueba de posicionamiento que
proporciona la capa visual. La compatibilidad con la prueba de posicionamiento le permite determinar si un valor
de geometría o punto se encuentra dentro del contenido representado de un Visual, lo que le permite
implementar el comportamiento de la interfaz de usuario, como un rectángulo de selección para seleccionar
varios objetos.

Escenarios de pruebas de posicionamiento


La clase UIElement proporciona el método InputHitTest, que permite realizar una prueba de posicionamiento con
un elemento mediante un valor de coordenadas determinado. En muchos casos, el método InputHitTest
proporciona la funcionalidad deseada para implementar la prueba de posicionamiento de los elementos. Sin
embargo, hay varios escenarios en los que puede necesitar implementar pruebas de posicionamiento en la capa
visual.
Pruebas de posicionamiento en objetos que no son deUIElement: esto se aplica si se realiza la prueba de
posicionamiento de objetos noUIElement, como objetos de DrawingVisual o de gráficos.
Pruebas de posicionamiento con la utilización de una geometría: esto se aplica si necesita realizar una
prueba de posicionamiento con un objeto de geometría en lugar usar el valor de coordenadas de un
punto.
Pruebas de posicionamiento frente a varios objetos: esto se aplica cuando es necesario realizar pruebas de
posicionamiento frente a varios objetos, tales como objetos superpuestos. Puede obtener resultados para
todos los elementos visuales que corten una geometría o un punto, no solamente para el primero.
Omitir UIElement Directiva de prueba de posicionamiento: esto se aplica cuando es necesario pasar por
alto la Directiva de prueba de posicionamiento UIElement, que tiene en cuenta tales factores como si un
elemento está deshabilitado o invisible.

NOTE
Para obtener un ejemplo de código completo que muestra la prueba de posicionamiento en la capa visual, vea Ejemplo de
prueba de posicionamiento con DrawingVisuals y Ejemplo de prueba de posicionamiento de interoperabilidad con Win32.

Compatibilidad con la prueba de posicionamiento


El propósito de los métodos de HitTest en la clase VisualTreeHelper es determinar si un valor de coordenadas de
geometría o de punto está dentro del contenido representado de un objeto determinado, como un control o un
elemento gráfico. Por ejemplo, podría utilizar la prueba de posicionamiento para determinar si un clic del mouse
dentro del rectángulo delimitador de un objeto pertenece a la geometría de un círculo. También puede optar por
invalidar la implementación predeterminada de la prueba de posicionamiento, para realizar cálculos propios en
las pruebas de posicionamiento.
La ilustración siguiente muestra la relación entre la región de un objeto no rectangular y su rectángulo
delimitador.
Diagrama de región de prueba de posicionamiento válida

Prueba de posicionamiento y orden z


La capa visual de Windows Presentation Foundation (WPF ) admite la prueba de posicionamiento frente a todos
los objetos situados bajo un punto o una geometría, no solamente para el objeto de nivel superior. Los resultados
se devuelven en un orden z. Sin embargo, el objeto visual que se pasa como parámetro al método HitTest
determina qué parte del árbol visual será la prueba de posicionamiento. Puede realizar la prueba de
posicionamiento frente al árbol visual completo o frente a cualquier parte de él.
En la ilustración siguiente, el objeto de círculo está encima del objeto cuadrado y del triangular. Si solo está
interesado en la prueba de posicionamiento del objeto visual cuyo valor de orden z es el más alto, puede
establecer la enumeración de la prueba de posicionamiento visual para que devuelva Stop del
HitTestResultCallback para detener el recorrido de la prueba de posicionamiento después del primer elemento.

Diagrama del orden z de un árbol visual


Si desea enumerar todos los objetos visuales bajo un punto o geometría específicos, devuelva Continue del
HitTestResultCallback. Esto significa que puede realizar pruebas de posicionamiento para objetos visuales que
estén bajo otros objetos, aunque estén completamente ocultos. Vea el ejemplo de código en la sección "Utilizar
una devolución de llamada de resultados de pruebas de posicionamiento" para obtener más información.

NOTE
Un objeto visual transparente también se puede someter a una prueba de posicionamiento.

Uso de la prueba de posicionamiento predeterminada


Puede identificar si un punto está dentro de la geometría de un objeto visual, utilizando el método HitTest para
especificar un objeto visual y un valor de coordenadas de punto con el que se va a realizar la prueba. El
parámetro de objeto visual identifica el punto inicial en el árbol visual para la búsqueda de la prueba de
posicionamiento. Si se encuentra un objeto visual en el árbol visual cuya geometría contiene la coordenada, se
establece en la propiedad VisualHit de un objeto HitTestResult. A continuación, el HitTestResult se devuelve
desde el método HitTest. Si el punto no está incluido en el subárbol visual en el que se está realizando la prueba
de posicionamiento, HitTest devuelve null .
NOTE
La prueba de posicionamiento predeterminada devuelve el objeto de nivel superior en el orden z. Para identificar todos los
objetos visuales, incluso aquellos que puedan estar ocultos, de forma total o parcial, utilice una devolución de llamada de
resultado de prueba de posicionamiento.

El valor de la coordenada que se pasa como parámetro de punto para el método HitTest tiene que ser relativo al
espacio de coordenadas del objeto visual con el que se realiza la prueba de posicionamiento. Por ejemplo, si ha
anidado objetos visuales definidos en (100, 100) en el espacio de coordenadas del elemento primario, la prueba
de posicionamiento de un elemento secundario visual en (0, 0) es equivalente a la prueba de posicionamiento en
(100, 100) en el espacio de coordenadas del elemento primario.
En el código siguiente se muestra cómo configurar controladores de eventos de mouse para un UIElement
objeto que se usa para capturar eventos utilizados para la prueba de posicionamiento.

// Respond to the left mouse button down event by initiating the hit test.
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);

// Perform the hit test against a given portion of the visual object tree.
HitTestResult result = VisualTreeHelper.HitTest(myCanvas, pt);

if (result != null)
{
// Perform action on hit visual object.
}
}

' Respond to the left mouse button down event by initiating the hit test.
Private Overloads Sub OnMouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Retrieve the coordinate of the mouse position.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))

' Perform the hit test against a given portion of the visual object tree.
Dim result As HitTestResult = VisualTreeHelper.HitTest(myCanvas, pt)

If result IsNot Nothing Then


' Perform action on hit visual object.
End If
End Sub

Cómo afecta el árbol visual a la prueba de posicionamiento


El punto inicial en el árbol visual determina qué objetos se devuelven durante la enumeración de objetos de la
prueba de posicionamiento. Si tiene varios objetos que desea someter a la prueba de posicionamiento, el objeto
visual utilizado como punto inicial en el árbol visual debe ser el antecesor común de todos los objetos de interés.
Por ejemplo, si estuviera interesado en la prueba de posicionamiento tanto del elemento de botón como del
elemento visual de dibujo del diagrama siguiente, tendría que establecer el punto inicial del árbol visual en el
antecesor común de ambos. En este caso, el elemento de lienzo es el antecesor común del elemento de botón y
del elemento visual de dibujo.
Diagrama de una jerarquía de árbol visual

NOTE
La propiedad IsHitTestVisible obtiene o establece un valor que declara si un objeto derivado de UIElementse puede
devolver como resultado de una prueba de posicionamiento de alguna parte de su contenido representado. Esto permite
modificar de manera selectiva el árbol visual para determinar qué objetos visuales están implicados en una prueba de
posicionamiento.

Uso de una devolución de llamada de resultados de prueba de


posicionamiento
Puede enumerar todos los objetos visuales de un árbol visual cuya geometría contenga un valor de coordenadas
especificado. Esto permite identificar todos los objetos visuales, incluso aquellos que puedan estar ocultos, de
forma parcial o total, por otros objetos visuales. Para enumerar los objetos visuales de un árbol visual, use el
método HitTest con una función de devolución de llamada de la prueba de posicionamiento. El sistema llama a la
función de devolución de llamada de la prueba de posicionamiento cuando el valor de coordenadas especificado
esté contenido en un objeto visual.
Durante la enumeración de resultados de pruebas de posicionamiento no se debe realizar ninguna operación
que modifique el árbol visual. Agregar o quitar un objeto del árbol visual mientras se recorre puede producir un
comportamiento imprevisible. Puede modificar de forma segura el árbol visual después de que el método HitTest
devuelva. Es posible que desee proporcionar una estructura de datos, como un ArrayList, para almacenar valores
durante la enumeración de resultados de pruebas de posicionamiento.

// Respond to the right mouse button down event by setting up a hit test results callback.
private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);

// Clear the contents of the list used for hit test results.
hitResultsList.Clear();

// Set up a callback to receive the hit test result enumeration.


VisualTreeHelper.HitTest(myCanvas, null,
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(pt));

// Perform actions on the hit test results list.


if (hitResultsList.Count > 0)
{
Console.WriteLine("Number of Visuals Hit: " + hitResultsList.Count);
}
}
' Respond to the right mouse button down event by setting up a hit test results callback.
Private Overloads Sub OnMouseRightButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Retrieve the coordinate of the mouse position.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))

' Clear the contents of the list used for hit test results.
hitResultsList.Clear()

' Set up a callback to receive the hit test result enumeration.


VisualTreeHelper.HitTest(myCanvas, Nothing, New HitTestResultCallback(AddressOf MyHitTestResult), New
PointHitTestParameters(pt))

' Perform actions on the hit test results list.


If hitResultsList.Count > 0 Then
Console.WriteLine("Number of Visuals Hit: " & hitResultsList.Count)
End If
End Sub

El método de devolución de llamada de la prueba de posicionamiento define las acciones que se realizan cuando
se identifica una prueba de posicionamiento en un objeto visual determinado del árbol visual. Después de
realizar las acciones, se devuelve un valor HitTestResultBehavior que determina si se debe continuar la
enumeración de otros objetos visuales o no.

// Return the result of the hit test to the callback.


public HitTestResultBehavior MyHitTestResult(HitTestResult result)
{
// Add the hit test result to the list that will be processed after the enumeration.
hitResultsList.Add(result.VisualHit);

// Set the behavior to return visuals at all z-order levels.


return HitTestResultBehavior.Continue;
}

' Return the result of the hit test to the callback.


Public Function MyHitTestResult(ByVal result As HitTestResult) As HitTestResultBehavior
' Add the hit test result to the list that will be processed after the enumeration.
hitResultsList.Add(result.VisualHit)

' Set the behavior to return visuals at all z-order levels.


Return HitTestResultBehavior.Continue
End Function

NOTE
El orden de enumeración de los objetos visuales de la posición es el orden z. El objeto visual de orden z de nivel superior es
el primer objeto enumerado. Los demás objetos visuales enumerados están en orden z decreciente. Este orden de
enumeración corresponde al orden de representación de elementos visuales.

Puede detener la enumeración de objetos visuales en cualquier momento en la función de devolución de llamada
de la prueba de posicionamiento devolviendo Stop.

// Set the behavior to stop enumerating visuals.


return HitTestResultBehavior.Stop;
' Set the behavior to stop enumerating visuals.
Return HitTestResultBehavior.Stop

Uso de una devolución de llamada de filtro de prueba de


posicionamiento
Puede utilizar un filtro opcional de la prueba de posicionamiento para restringir los objetos que se pasan en los
resultados de pruebas de posicionamiento. Esto permite omitir, en los resultados de pruebas de posicionamiento,
las partes del árbol visual que no desee procesar. Para implementar un filtro de prueba de posicionamiento, se
define una función de devolución de llamada de filtro de prueba de posicionamiento y se pasa como un valor de
parámetro al llamar al método HitTest.

// Respond to the mouse wheel event by setting up a hit test filter and results enumeration.
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);

// Clear the contents of the list used for hit test results.
hitResultsList.Clear();

// Set up a callback to receive the hit test result enumeration.


VisualTreeHelper.HitTest(myCanvas,
new HitTestFilterCallback(MyHitTestFilter),
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(pt));

// Perform actions on the hit test results list.


if (hitResultsList.Count > 0)
{
ProcessHitTestResultsList();
}
}

' Respond to the mouse wheel event by setting up a hit test filter and results enumeration.
Private Overloads Sub OnMouseWheel(ByVal sender As Object, ByVal e As MouseWheelEventArgs)
' Retrieve the coordinate of the mouse position.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))

' Clear the contents of the list used for hit test results.
hitResultsList.Clear()

' Set up a callback to receive the hit test result enumeration.


VisualTreeHelper.HitTest(myCanvas, New HitTestFilterCallback(AddressOf MyHitTestFilter), New
HitTestResultCallback(AddressOf MyHitTestResult), New PointHitTestParameters(pt))

' Perform actions on the hit test results list.


If hitResultsList.Count > 0 Then
ProcessHitTestResultsList()
End If
End Sub

Si no desea proporcionar la función de devolución de llamada de filtro de prueba de posicionamiento opcional,


pase un valor null como su parámetro para el método HitTest.
// Set up a callback to receive the hit test result enumeration,
// but no hit test filter enumeration.
VisualTreeHelper.HitTest(myCanvas,
null, // No hit test filtering.
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(pt));

' Set up a callback to receive the hit test result enumeration,


' but no hit test filter enumeration.
VisualTreeHelper.HitTest(myCanvas, Nothing, New HitTestResultCallback(AddressOf MyHitTestResult), New
PointHitTestParameters(pt)) ' No hit test filtering.

Eliminar un árbol visual


La función de devolución de llamada de filtro de prueba de posicionamiento permite enumerar todos los objetos
visuales cuyo contenido representado contenga las coordenadas que especifique. No obstante, es posible que
desee omitir determinadas ramas del árbol visual, porque no le interese procesarlas en la función de devolución
de llamada de los resultados de pruebas de posicionamiento. El valor devuelto de la función de devolución de
llamada del filtro de la prueba de posicionamiento determina el tipo de acción que debe realizar la enumeración
de los objetos visuales. Por ejemplo, si devuelve el valor, ContinueSkipSelfAndChildren, puede quitar el objeto
visual actual y sus elementos secundarios de la enumeración de resultados de pruebas de posicionamiento. Esto
significa que la función de devolución de llamada de los resultados de pruebas de posicionamiento no verá estos
objetos en su enumeración. Cuando se eliminan objetos del árbol visual, se reduce el número de procesos
durante el paso de enumeración de resultados de pruebas de posicionamiento. En el ejemplo de código
siguiente, el filtro omite las etiquetas y sus descendientes y realiza pruebas de posicionamiento con todos los
demás objetos.

// Filter the hit test values for each object in the enumeration.
public HitTestFilterBehavior MyHitTestFilter(DependencyObject o)
{
// Test for the object value you want to filter.
if (o.GetType() == typeof(Label))
{
// Visual object and descendants are NOT part of hit test results enumeration.
return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
}
else
{
// Visual object is part of hit test results enumeration.
return HitTestFilterBehavior.Continue;
}
}
' Filter the hit test values for each object in the enumeration.
Public Function MyHitTestFilter(ByVal o As DependencyObject) As HitTestFilterBehavior
' Test for the object value you want to filter.
If o.GetType() Is GetType(Label) Then
' Visual object and descendants are NOT part of hit test results enumeration.
Return HitTestFilterBehavior.ContinueSkipSelfAndChildren
Else
' Visual object is part of hit test results enumeration.
Return HitTestFilterBehavior.Continue
End If
End Function

NOTE
Se llamará a la devolución de llamada de filtro de la prueba de posicionamiento en aquellos casos en que no se llame a la
devolución de llamada de resultados de pruebas de posicionamiento.

Invalidación de la prueba de posicionamiento predeterminada


Puede invalidar la compatibilidad con la prueba de posicionamiento predeterminada de un objeto visual
invalidando el método de HitTestCore. Esto significa que cuando se invoca el método HitTest, se llama a la
implementación invalidada de HitTestCore. Se llama al método de invalidación cuando una prueba de
posicionamiento está dentro del rectángulo delimitador del objeto visual, aunque las coordenadas estén fuera del
contenido representado de dicho objeto.

// Override default hit test support in visual object.


protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
Point pt = hitTestParameters.HitPoint;

// Perform custom actions during the hit test processing,


// which may include verifying that the point actually
// falls within the rendered content of the visual.

// Return hit on bounding rectangle of visual object.


return new PointHitTestResult(this, pt);
}

' Override default hit test support in visual object.


Protected Overrides Overloads Function HitTestCore(ByVal hitTestParameters As PointHitTestParameters) As
HitTestResult
Dim pt As Point = hitTestParameters.HitPoint

' Perform custom actions during the hit test processing,


' which may include verifying that the point actually
' falls within the rendered content of the visual.

' Return hit on bounding rectangle of visual object.


Return New PointHitTestResult(Me, pt)
End Function

Pueden darse ocasiones en que desee realizar la prueba de posicionamiento tanto respecto al rectángulo
delimitador como respecto al contenido representado de un objeto visual. Al usar el valor del parámetro
PointHitTestParameters en el método HitTestCore invalidado como el parámetro para el HitTestCoredel método
base, puede realizar acciones basadas en un acierto del rectángulo delimitador de un objeto visual y, a
continuación, realizar una segunda prueba de posicionamiento con el contenido representado del objeto visual.
// Override default hit test support in visual object.
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
// Perform actions based on hit test of bounding rectangle.
// ...

// Return results of base class hit testing,


// which only returns hit on the geometry of visual objects.
return base.HitTestCore(hitTestParameters);
}

' Override default hit test support in visual object.


Protected Overrides Overloads Function HitTestCore(ByVal hitTestParameters As PointHitTestParameters) As
HitTestResult
' Perform actions based on hit test of bounding rectangle.
' ...

' Return results of base class hit testing,


' which only returns hit on the geometry of visual objects.
Return MyBase.HitTestCore(hitTestParameters)
End Function

Consulte también
HitTest
HitTestResult
HitTestResultCallback
HitTestFilterCallback
IsHitTestVisible
Prueba de posicionamiento mediante el ejemplo DrawingVisuals
Prueba de posicionamiento con el ejemplo de interoperación de Win32
Geometría de una prueba de posicionamiento en un objeto Visual
Realizar pruebas de posicionamiento mediante un contenedor host Win32
Usar objetos DrawingVisual
23/10/2019 • 8 minutes to read • Edit Online

En este tema se proporciona información general sobre cómo DrawingVisual usar objetos en WPF la capa visual.

Objeto DrawingVisual
DrawingVisual Es una clase de dibujo ligera que se utiliza para representar formas, imágenes o texto. Esta clase
se considera ligera porque no proporciona control de diseño ni control de eventos, lo que mejora su rendimiento.
Por esta razón, los dibujos son ideales para fondos e imágenes prediseñadas.

Contenedor host de objetos DrawingVisual


Para usar DrawingVisual objetos, debe crear un contenedor host para los objetos. El objeto contenedor host
debe derivar de FrameworkElement la clase, que proporciona el diseño y la compatibilidad con el DrawingVisual
control de eventos que la clase no tiene. El objeto contenedor host no muestra ninguna propiedad visible, puesto
que su finalidad principal es contener objetos secundarios. Sin embargo, Visibility la propiedad del contenedor
host debe establecerse en Visible; de lo contrario, ninguno de sus elementos secundarios será visible.
Cuando se crea un objeto contenedor host para objetos visuales, es necesario almacenar las referencias de
objeto visual en un VisualCollection. Use el Add método para agregar un objeto visual al contenedor host. En el
ejemplo siguiente, se crea un objeto contenedor host y se agregan tres objetos visuales a su VisualCollection.

// Create a host visual derived from the FrameworkElement class.


// This class provides layout, event handling, and container support for
// the child visual objects.
public class MyVisualHost : FrameworkElement
{
// Create a collection of child visual objects.
private VisualCollection _children;

public MyVisualHost()
{
_children = new VisualCollection(this);
_children.Add(CreateDrawingVisualRectangle());
_children.Add(CreateDrawingVisualText());
_children.Add(CreateDrawingVisualEllipses());

// Add the event handler for MouseLeftButtonUp.


this.MouseLeftButtonUp += new
System.Windows.Input.MouseButtonEventHandler(MyVisualHost_MouseLeftButtonUp);
}
' Create a host visual derived from the FrameworkElement class.
' This class provides layout, event handling, and container support for
' the child visual objects.
Public Class MyVisualHost
Inherits FrameworkElement
' Create a collection of child visual objects.
Private _children As VisualCollection

Public Sub New()


_children = New VisualCollection(Me)
_children.Add(CreateDrawingVisualRectangle())
_children.Add(CreateDrawingVisualText())
_children.Add(CreateDrawingVisualEllipses())

' Add the event handler for MouseLeftButtonUp.


AddHandler MouseLeftButtonUp, AddressOf MyVisualHost_MouseLeftButtonUp
End Sub

NOTE
Para obtener el código completo del que se ha extraído el ejemplo de código anterior, vea Ejemplo Hit Test Using
DrawingVisuals.

Crear objetos DrawingVisual


Cuando se crea un DrawingVisual objeto, no tiene ningún contenido de dibujo. Puede Agregar texto, gráficos o
contenido de imagen recuperando el objeto DrawingContext y dibujando en él. Se DrawingContext devuelve una
RenderOpen llamada al método de un DrawingVisual objeto.
Para dibujar un rectángulo en DrawingContext, utilice el DrawRectangle método del DrawingContext objeto.
Existen métodos similares para dibujar otros tipos de contenido. Cuando haya terminado de dibujar el contenido
en DrawingContext, Close llame al método para cerrar DrawingContext y conservar el contenido.
En el ejemplo siguiente, se DrawingVisual crea un objeto y se dibuja un rectángulo en su. DrawingContext

// Create a DrawingVisual that contains a rectangle.


private DrawingVisual CreateDrawingVisualRectangle()
{
DrawingVisual drawingVisual = new DrawingVisual();

// Retrieve the DrawingContext in order to create new drawing content.


DrawingContext drawingContext = drawingVisual.RenderOpen();

// Create a rectangle and draw it in the DrawingContext.


Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));
drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null,
rect);

// Persist the drawing content.


drawingContext.Close();

return drawingVisual;
}
' Create a DrawingVisual that contains a rectangle.
Private Function CreateDrawingVisualRectangle() As DrawingVisual
Dim drawingVisual As New DrawingVisual()

' Retrieve the DrawingContext in order to create new drawing content.


Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()

' Create a rectangle and draw it in the DrawingContext.


Dim rect As New Rect(New Point(160, 100), New Size(320, 80))
drawingContext.DrawRectangle(Brushes.LightBlue, CType(Nothing, Pen), rect)

' Persist the drawing content.


drawingContext.Close()

Return drawingVisual
End Function

Crear invalidaciones para los miembros FrameworkElement


El objeto contenedor host es responsable de administrar su colección de objetos visuales. Esto requiere que el
contenedor host implemente invalidaciones de miembros para FrameworkElement la clase derivada.
En la lista siguiente se describen los dos miembros que debe invalidar:
GetVisualChild: Devuelve un elemento secundario en el índice especificado de la colección de elementos
secundarios.
VisualChildrenCount: Obtiene el número de elementos secundarios visuales de este elemento.
En el ejemplo siguiente, se implementan las invalidaciones de los dos FrameworkElement miembros.

// Provide a required override for the VisualChildrenCount property.


protected override int VisualChildrenCount
{
get { return _children.Count; }
}

// Provide a required override for the GetVisualChild method.


protected override Visual GetVisualChild(int index)
{
if (index < 0 || index >= _children.Count)
{
throw new ArgumentOutOfRangeException();
}

return _children[index];
}
' Provide a required override for the VisualChildrenCount property.
Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
Get
Return _children.Count
End Get
End Property

' Provide a required override for the GetVisualChild method.


Protected Overrides Function GetVisualChild(ByVal index As Integer) As Visual
If index < 0 OrElse index >= _children.Count Then
Throw New ArgumentOutOfRangeException()
End If

Return _children(index)
End Function

Proporcionar compatibilidad con las pruebas de posicionamiento


El objeto contenedor host puede proporcionar control de eventos incluso si no muestra ninguna propiedad
visible; sin embargo, su Visibility propiedad debe establecerse en Visible. Esto permite crear una rutina de control
de eventos para el contenedor host que pueda interceptar los eventos del mouse, tales como soltar el botón
izquierdo. La rutina de control de eventos puede, a continuación, implementar la HitTest prueba de
posicionamiento invocando el método. El parámetro del HitTestResultCallback método hace referencia a un
procedimiento definido por el usuario que puede usar para determinar la acción resultante de una prueba de
posicionamiento.
En el ejemplo siguiente, se implementa la compatibilidad con las pruebas de posicionamiento para el objeto
contenedor host y sus elementos secundarios.

// Capture the mouse event and hit test the coordinate point value against
// the child visual objects.
void MyVisualHost_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
// Retrieve the coordinates of the mouse button event.
System.Windows.Point pt = e.GetPosition((UIElement)sender);

// Initiate the hit test by setting up a hit test result callback method.
VisualTreeHelper.HitTest(this, null, new HitTestResultCallback(myCallback), new
PointHitTestParameters(pt));
}

// If a child visual object is hit, toggle its opacity to visually indicate a hit.
public HitTestResultBehavior myCallback(HitTestResult result)
{
if (result.VisualHit.GetType() == typeof(DrawingVisual))
{
if (((DrawingVisual)result.VisualHit).Opacity == 1.0)
{
((DrawingVisual)result.VisualHit).Opacity = 0.4;
}
else
{
((DrawingVisual)result.VisualHit).Opacity = 1.0;
}
}

// Stop the hit test enumeration of objects in the visual tree.


return HitTestResultBehavior.Stop;
}
' Capture the mouse event and hit test the coordinate point value against
' the child visual objects.
Private Sub MyVisualHost_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Retrieve the coordinates of the mouse button event.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))

' Initiate the hit test by setting up a hit test result callback method.
VisualTreeHelper.HitTest(Me, Nothing, New HitTestResultCallback(AddressOf myCallback), New
PointHitTestParameters(pt))
End Sub

' If a child visual object is hit, toggle its opacity to visually indicate a hit.
Public Function myCallback(ByVal result As HitTestResult) As HitTestResultBehavior
If result.VisualHit.GetType() Is GetType(DrawingVisual) Then
If (CType(result.VisualHit, DrawingVisual)).Opacity = 1.0 Then
CType(result.VisualHit, DrawingVisual).Opacity = 0.4
Else
CType(result.VisualHit, DrawingVisual).Opacity = 1.0
End If
End If

' Stop the hit test enumeration of objects in the visual tree.
Return HitTestResultBehavior.Stop
End Function

Vea también
DrawingVisual
HitTest
Información general sobre la representación de gráficos en WPF
Realizar pruebas de posicionamiento en la capa visual
Tutorial: Hospedar objetos visuales en una aplicación
Win32
10/01/2020 • 11 minutes to read • Edit Online

Windows Presentation Foundation (WPF ) proporciona un entorno rico para crear aplicaciones. Sin embargo, si
tiene una inversión sustancial en código Win32, podría ser más eficaz agregar WPF funcionalidad a la aplicación
en lugar de volver a escribir el código. Para proporcionar compatibilidad con Win32 y WPF subsistemas de
gráficos utilizados simultáneamente en una aplicación, WPF proporciona un mecanismo para hospedar objetos
en una ventana de Win32.
En este tutorial se describe cómo escribir una aplicación de ejemplo, una prueba de posicionamiento con el
ejemplo de interoperación de Win32, que hospeda WPF objetos visuales en una ventana de Win32.

Requisitos de
En este tutorial se da por supuesto que está familiarizado con la programación de WPF y Win32. Para obtener
una introducción básica a la programación de WPF, vea Tutorial: mi primera aplicación de escritorio WPF. Para
ver una introducción a la programación de Win32, consulte cualquiera de los numerosos libros sobre el tema, en
determinadas ventanas de programación , de Charles Petzold.

NOTE
En el tutorial se incluye una serie de ejemplos de código del ejemplo asociado. Sin embargo, para una mejor lectura, no se
incluye el código de ejemplo completo. Para obtener el código de ejemplo completo, vea prueba de posicionamiento con el
ejemplo de interoperación de Win32.

Crear la ventana host de Win32


La clave para hospedar objetos de WPF en una ventana de Win32 es la clase HwndSource. Esta clase ajusta el
WPF objetos en una ventana de Win32, lo que permite que se incorporen en el interfaz de usuario (UI) como una
ventana secundaria.
En el ejemplo siguiente se muestra el código para crear el objeto HwndSource como la ventana contenedor de
Win32 para los objetos visuales. Para establecer el estilo, la posición y otros parámetros de la ventana de Win32,
use el objeto HwndSourceParameters.
// Constant values from the "winuser.h" header file.
internal const int WS_CHILD = 0x40000000,
WS_VISIBLE = 0x10000000;

internal static void CreateHostHwnd(IntPtr parentHwnd)


{
// Set up the parameters for the host hwnd.
HwndSourceParameters parameters = new HwndSourceParameters("Visual Hit Test", _width, _height);
parameters.WindowStyle = WS_VISIBLE | WS_CHILD;
parameters.SetPosition(0, 24);
parameters.ParentWindow = parentHwnd;
parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);

// Create the host hwnd for the visuals.


myHwndSource = new HwndSource(parameters);

// Set the hwnd background color to the form's background color.


myHwndSource.CompositionTarget.BackgroundColor = System.Windows.Media.Brushes.OldLace.Color;
}

' Constant values from the "winuser.h" header file.


Friend Const WS_CHILD As Integer = &H40000000, WS_VISIBLE As Integer = &H10000000

Friend Shared Sub CreateHostHwnd(ByVal parentHwnd As IntPtr)


' Set up the parameters for the host hwnd.
Dim parameters As New HwndSourceParameters("Visual Hit Test", _width, _height)
parameters.WindowStyle = WS_VISIBLE Or WS_CHILD
parameters.SetPosition(0, 24)
parameters.ParentWindow = parentHwnd
parameters.HwndSourceHook = New HwndSourceHook(AddressOf ApplicationMessageFilter)

' Create the host hwnd for the visuals.


myHwndSource = New HwndSource(parameters)

' Set the hwnd background color to the form's background color.
myHwndSource.CompositionTarget.BackgroundColor = System.Windows.Media.Brushes.OldLace.Color
End Sub

NOTE
No se puede establecer el valor de la propiedad ExtendedWindowStyle en WS_EX_TRANSPARENT. Esto significa que la
ventana de Win32 de host no puede ser transparente. Por esta razón, el color de fondo de la ventana de Win32 del host se
establece en el mismo color de fondo que su ventana primaria.

Agregar objetos visuales a la ventana host de Win32


Una vez que haya creado una ventana contenedor de Win32 de host para los objetos visuales, puede agregarle
objetos visuales. Querrá asegurarse de que las transformaciones de los objetos visuales, como las animaciones,
no se extienden más allá de los límites del rectángulo delimitador de la ventana de Win32 del host.
En el ejemplo siguiente se muestra el código para crear el objeto de HwndSource y agregarle objetos visuales.

NOTE
La propiedad RootVisual del objeto HwndSource se establece en el primer objeto visual agregado a la ventana host de
Win32. El objeto visual raíz define el nodo de nivel superior del árbol de objetos visuales. Los objetos visuales subsiguientes
agregados a la ventana de Win32 de host se agregan como objetos secundarios.
public static void CreateShape(IntPtr parentHwnd)
{
// Create an instance of the shape.
MyShape myShape = new MyShape();

// Determine whether the host container window has been created.


if (myHwndSource == null)
{
// Create the host container window for the visual objects.
CreateHostHwnd(parentHwnd);

// Associate the shape with the host container window.


myHwndSource.RootVisual = myShape;
}
else
{
// Assign the shape as a child of the root visual.
((ContainerVisual)myHwndSource.RootVisual).Children.Add(myShape);
}
}

Public Shared Sub CreateShape(ByVal parentHwnd As IntPtr)


' Create an instance of the shape.
Dim myShape As New MyShape()

' Determine whether the host container window has been created.
If myHwndSource Is Nothing Then
' Create the host container window for the visual objects.
CreateHostHwnd(parentHwnd)

' Associate the shape with the host container window.


myHwndSource.RootVisual = myShape
Else
' Assign the shape as a child of the root visual.
CType(myHwndSource.RootVisual, ContainerVisual).Children.Add(myShape)
End If
End Sub

Implementar el filtro de mensajes de Win32


La ventana host de Win32 para los objetos visuales requiere un procedimiento de filtro de mensajes de ventana
para controlar los mensajes que se envían a la ventana desde la cola de la aplicación. El procedimiento de ventana
recibe mensajes del sistema Win32. Pueden ser mensajes de entrada o mensajes de administración de ventanas.
Si lo desea, puede administrar un mensaje en el procedimiento de ventana o bien pasar el mensaje al sistema
para su procesamiento predeterminado.
El objeto HwndSource que definió como elemento primario de los objetos visuales debe hacer referencia al
procedimiento de filtro de mensajes de ventana que proporcione. Al crear el objeto de HwndSource, establezca la
propiedad HwndSourceHook para hacer referencia al procedimiento de ventana.

parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);

parameters.HwndSourceHook = New HwndSourceHook(AddressOf ApplicationMessageFilter)

En el ejemplo siguiente se muestra el código para controlar los mensajes que se emiten al soltar el botón
primario y secundario del ratón. El valor de la coordenada de la posición de posicionamiento del mouse se
encuentra en el valor del parámetro lParam .
// Constant values from the "winuser.h" header file.
internal const int WM_LBUTTONUP = 0x0202,
WM_RBUTTONUP = 0x0205;

internal static IntPtr ApplicationMessageFilter(


IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages passed to the visual.
switch (message)
{
// Handle the left and right mouse button up messages.
case WM_LBUTTONUP:
case WM_RBUTTONUP:
System.Windows.Point pt = new System.Windows.Point();
pt.X = (uint)lParam & (uint)0x0000ffff; // LOWORD = x
pt.Y = (uint)lParam >> 16; // HIWORD = y
MyShape.OnHitTest(pt, message);
break;
}

return IntPtr.Zero;
}

' Constant values from the "winuser.h" header file.


Friend Const WM_LBUTTONUP As Integer = &H202, WM_RBUTTONUP As Integer = &H205

Friend Shared Function ApplicationMessageFilter(ByVal hwnd As IntPtr, ByVal message As Integer, ByVal wParam
As IntPtr, ByVal lParam As IntPtr, ByRef handled As Boolean) As IntPtr
' Handle messages passed to the visual.
Select Case message
' Handle the left and right mouse button up messages.
Case WM_LBUTTONUP, WM_RBUTTONUP
Dim pt As New System.Windows.Point()
pt.X = CUInt(lParam) And CUInt(&HFFFF) ' LOWORD = x
pt.Y = CUInt(lParam) >> 16 ' HIWORD = y
MyShape.OnHitTest(pt, message)
End Select

Return IntPtr.Zero
End Function

Procesar mensajes de Win32


El código del ejemplo siguiente muestra cómo se realiza una prueba de posicionamiento en la jerarquía de
objetos visuales contenidos en la ventana host de Win32. Puede identificar si un punto está dentro de la
geometría de un objeto visual, utilizando el método HitTest para especificar el objeto visual raíz y el valor de la
coordenada con respecto a la prueba de posicionamiento. En este caso, el objeto visual raíz es el valor de la
propiedad RootVisual del objeto HwndSource.
// Constant values from the "winuser.h" header file.
public const int WM_LBUTTONUP = 0x0202,
WM_RBUTTONUP = 0x0205;

// Respond to WM_LBUTTONUP or WM_RBUTTONUP messages by determining which visual object was clicked.
public static void OnHitTest(System.Windows.Point pt, int msg)
{
// Clear the contents of the list used for hit test results.
hitResultsList.Clear();

// Determine whether to change the color of the circle or to delete the shape.
if (msg == WM_LBUTTONUP)
{
MyWindow.changeColor = true;
}
if (msg == WM_RBUTTONUP)
{
MyWindow.changeColor = false;
}

// Set up a callback to receive the hit test results enumeration.


VisualTreeHelper.HitTest(MyWindow.myHwndSource.RootVisual,
null,
new HitTestResultCallback(CircleHitTestResult),
new PointHitTestParameters(pt));

// Perform actions on the hit test results list.


if (hitResultsList.Count > 0)
{
ProcessHitTestResultsList();
}
}

' Constant values from the "winuser.h" header file.


Public Const WM_LBUTTONUP As Integer = &H0202, WM_RBUTTONUP As Integer = &H0205

' Respond to WM_LBUTTONUP or WM_RBUTTONUP messages by determining which visual object was clicked.
Public Shared Sub OnHitTest(ByVal pt As System.Windows.Point, ByVal msg As Integer)
' Clear the contents of the list used for hit test results.
hitResultsList.Clear()

' Determine whether to change the color of the circle or to delete the shape.
If msg = WM_LBUTTONUP Then
MyWindow.changeColor = True
End If
If msg = WM_RBUTTONUP Then
MyWindow.changeColor = False
End If

' Set up a callback to receive the hit test results enumeration.


VisualTreeHelper.HitTest(MyWindow.myHwndSource.RootVisual, Nothing, New HitTestResultCallback(AddressOf
CircleHitTestResult), New PointHitTestParameters(pt))

' Perform actions on the hit test results list.


If hitResultsList.Count > 0 Then
ProcessHitTestResultsList()
End If
End Sub

Para obtener más información sobre las pruebas de posicionamiento en objetos visuales, vea pruebas de
posicionamiento en la capa visual.

Vea también
HwndSource
Prueba de posicionamiento con el ejemplo de interoperación de Win32
Realizar pruebas de posicionamiento en la capa visual
Temas "Cómo..." sobre programación de capas
visuales
23/10/2019 • 2 minutes to read • Edit Online

Los temas de esta sección muestran cómo utilizar la capa visual de composición de la prueba de posicionamiento y
de bajo nivel.

En esta sección
Obtener el desplazamiento de un objeto visual
Enumerar el contenido de un dibujo de un objeto visual
Geometría de una prueba de posicionamiento en un objeto Visual
Realizar una prueba de posicionamiento usando Geometry como parámetro
Realizar pruebas de posicionamiento mediante un contenedor host Win32
Representar un intervalo para cada fotograma mediante CompositionTarget

Vea también
Visual
VisualTreeHelper
DrawingVisual
Información general sobre la representación de gráficos en WPF
Gráficos y multimedia
Procedimiento Obtener el desplazamiento de un
objeto visual
23/10/2019 • 4 minutes to read • Edit Online

Estos ejemplos muestran cómo recuperar el valor de desplazamiento de un objeto visual que es relativo a su
elemento primario, o cualquier antecesor o descendiente.

Ejemplo
El ejemplo de marcado siguiente se muestra un TextBlock que se define con Margin valor 4.

<TextBlock Name="myTextBlock" Margin="4" Text="Hello, world" />

En el ejemplo de código siguiente se muestra cómo utilizar el GetOffset método para recuperar el desplazamiento
de la TextBlock. Los valores de desplazamiento se encuentran en el valor devuelto Vector valor.

// Return the offset vector for the TextBlock object.


Vector vector = VisualTreeHelper.GetOffset(myTextBlock);

// Convert the vector to a point value.


Point currentPoint = new Point(vector.X, vector.Y);

' Return the offset vector for the TextBlock object.


Dim vector As Vector = VisualTreeHelper.GetOffset(myTextBlock)

' Convert the vector to a point value.


Dim currentPoint As New Point(vector.X, vector.Y)

El desplazamiento tiene en cuenta la Margin valor. En este caso, X es 4, y Y es 4.


El valor de desplazamiento devuelto es relativo al elemento primario de la Visual. Si desea devolver un valor de
desplazamiento no es relativo al elemento primario de un Visual, utilice el TransformToAncestor método.

Obtener el desplazamiento relativo a un antecesor


El ejemplo de marcado siguiente se muestra un TextBlock que está anidada dentro de dos StackPanel objetos.

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel Margin="16">
<StackPanel Margin="8">
<TextBlock Name="myTextBlock" Margin="4" Text="Hello, world" />
</StackPanel>
</StackPanel>
</Window>

La siguiente ilustración muestra los resultados del marcado.


TextBlock anidado dentro de dos objetos StackPanel
En el ejemplo de código siguiente se muestra cómo utilizar el TransformToAncestor método para recuperar el
desplazamiento de la TextBlock en relación con la que contiene Window. Los valores de desplazamiento se
encuentran en el valor devuelto GeneralTransform valor.

// Return the general transform for the specified visual object.


GeneralTransform generalTransform1 = myTextBlock.TransformToAncestor(this);

// Retrieve the point value relative to the parent.


Point currentPoint = generalTransform1.Transform(new Point(0, 0));

' Return the general transform for the specified visual object.
Dim generalTransform1 As GeneralTransform = myTextBlock.TransformToAncestor(Me)

' Retrieve the point value relative to the parent.


Dim currentPoint As Point = generalTransform1.Transform(New Point(0, 0))

El desplazamiento tiene en cuenta la Margin valores para todos los objetos dentro de la que contiene Window. En
este caso, X es 28 (16 + 8 + 4), y Y es 28.
El valor de desplazamiento devuelto es relativo al antecesor de la Visual. Si desea devolver un valor de
desplazamiento es relativo a los descendientes de un Visual, utilice el TransformToDescendant método.

Obtener el desplazamiento relativo a un descendiente


El ejemplo de marcado siguiente se muestra un TextBlock que está dentro de un StackPanel objeto.

<StackPanel Name="myStackPanel" Margin="8">


<TextBlock Name="myTextBlock" Margin="4" Text="Hello, world" />
</StackPanel>

En el ejemplo de código siguiente se muestra cómo utilizar el TransformToDescendant método para recuperar el
desplazamiento de la StackPanel en relación con su elemento secundario TextBlock. Los valores de desplazamiento
se encuentran en el valor devuelto GeneralTransform valor.

// Return the general transform for the specified visual object.


GeneralTransform generalTransform1 = myStackPanel.TransformToDescendant(myTextBlock);

// Retrieve the point value relative to the child.


Point currentPoint = generalTransform1.Transform(new Point(0, 0));

' Return the general transform for the specified visual object.
Dim generalTransform1 As GeneralTransform = myStackPanel.TransformToDescendant(myTextBlock)

' Retrieve the point value relative to the child.


Dim currentPoint As Point = generalTransform1.Transform(New Point(0, 0))
El desplazamiento tiene en cuenta el Margin para todos los objetos. En este caso, X es -4, y Y es -4. Los valores de
desplazamiento son valores negativos, puesto que el objeto primario es un desplazamiento negativo respecto a su
objeto secundario.

Vea también
Visual
VisualTreeHelper
Información general sobre la representación de gráficos en WPF
Procedimiento Enumerar el contenido de un dibujo
de un objeto visual
23/10/2019 • 2 minutes to read • Edit Online

El Drawing objeto proporciona un modelo de objetos para enumerar el contenido de Visualun objeto.

Ejemplo
En el ejemplo siguiente se GetDrawing usa el método para DrawingGroup recuperar el valor Visual de un y
enumerarlo.

NOTE
Cuando se enumera el contenido del objeto visual, se recuperan Drawing los objetos y no la representación subyacente de
los datos de representación como una lista de instrucciones de gráficos vectoriales. Para más información, consulte
Información general sobre la representación de gráficos en WPF.

public void RetrieveDrawing(Visual v)


{
DrawingGroup drawingGroup = VisualTreeHelper.GetDrawing(v);
EnumDrawingGroup(drawingGroup);
}

// Enumerate the drawings in the DrawingGroup.


public void EnumDrawingGroup(DrawingGroup drawingGroup)
{
DrawingCollection dc = drawingGroup.Children;

// Enumerate the drawings in the DrawingCollection.


foreach (Drawing drawing in dc)
{
// If the drawing is a DrawingGroup, call the function recursively.
if (drawing is DrawingGroup group)
{
EnumDrawingGroup(group);
}
else if (drawing is GeometryDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is ImageDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is GlyphRunDrawing)
{
// Perform action based on drawing type.
}
else if (drawing is VideoDrawing)
{
// Perform action based on drawing type.
}
}
}
Vea también
Drawing
DrawingGroup
VisualTreeHelper
Información general sobre objetos Drawing
Información general sobre la representación de gráficos en WPF
Procedimiento Geometría de una prueba de
posicionamiento en un objeto visual
23/10/2019 • 3 minutes to read • Edit Online

En este ejemplo se muestra cómo realizar una prueba de posicionamiento en un objeto visual que se compone de
uno Geometry o más objetos.

Ejemplo
En el ejemplo siguiente se muestra cómo recuperar DrawingGroup de un objeto visual que utiliza el GetDrawing
método. Después, se realiza una prueba de posicionamiento en el contenido representado de cada dibujo de
DrawingGroup para determinar qué geometría se alcanzó.

NOTE
En la mayoría de los casos, se HitTest usaría el método para determinar si un punto forma una intersección con el contenido
representado de un visual.

// Determine if a geometry within the visual was hit.


static public void HitTestGeometryInVisual(Visual visual, Point pt)
{
// Retrieve the group of drawings for the visual.
DrawingGroup drawingGroup = VisualTreeHelper.GetDrawing(visual);
EnumDrawingGroup(drawingGroup, pt);
}

// Enumerate the drawings in the DrawingGroup.


static public void EnumDrawingGroup(DrawingGroup drawingGroup, Point pt)
{
DrawingCollection drawingCollection = drawingGroup.Children;

// Enumerate the drawings in the DrawingCollection.


foreach (Drawing drawing in drawingCollection)
{
// If the drawing is a DrawingGroup, call the function recursively.
if (drawing.GetType() == typeof(DrawingGroup))
{
EnumDrawingGroup((DrawingGroup)drawing, pt);
}
else if (drawing.GetType() == typeof(GeometryDrawing))
{
// Determine whether the hit test point falls within the geometry.
if (((GeometryDrawing)drawing).Geometry.FillContains(pt))
{
// Perform action based on hit test on geometry.
}
}
}
}
' Determine if a geometry within the visual was hit.
Public Shared Sub HitTestGeometryInVisual(ByVal visual As Visual, ByVal pt As Point)
' Retrieve the group of drawings for the visual.
Dim drawingGroup As DrawingGroup = VisualTreeHelper.GetDrawing(visual)
EnumDrawingGroup(drawingGroup, pt)
End Sub

' Enumerate the drawings in the DrawingGroup.


Public Shared Sub EnumDrawingGroup(ByVal drawingGroup As DrawingGroup, ByVal pt As Point)
Dim drawingCollection As DrawingCollection = drawingGroup.Children

' Enumerate the drawings in the DrawingCollection.


For Each drawing As Drawing In drawingCollection
' If the drawing is a DrawingGroup, call the function recursively.
If drawing.GetType() Is GetType(DrawingGroup) Then
EnumDrawingGroup(CType(drawing, DrawingGroup), pt)
ElseIf drawing.GetType() Is GetType(GeometryDrawing) Then
' Determine whether the hit test point falls within the geometry.
If (CType(drawing, GeometryDrawing)).Geometry.FillContains(pt) Then
' Perform action based on hit test on geometry.
End If
End If

Next drawing
End Sub

El FillContains método es un método sobrecargado que permite realizar una prueba de posicionamiento mediante
un especificado Point o Geometry. Si se traza una geometría, el trazo puede extenderse fuera del límite del relleno.
En ese caso, puede que desee llamar StrokeContains a además de a. FillContains
También puede proporcionar un ToleranceType que se usa para los propósitos del aplanamiento de Bézier.

NOTE
Esta muestra no tiene en cuenta ninguna transformación o recorte que pueda aplicarse a la geometría. Además, este
ejemplo no funcionará con un control con estilo, puesto que no tiene los dibujos asociados a él.

Vea también
Realizar pruebas de posicionamiento en la capa visual
Realizar una prueba de posicionamiento usando Geometry como parámetro
Procedimiento Realizar una prueba de
posicionamiento mediante el uso de Geometry como
parámetro
23/10/2019 • 4 minutes to read • Edit Online

En este ejemplo se muestra cómo realizar una prueba de posicionamiento en un objeto visual Geometry utilizando
como parámetro de prueba de posicionamiento.

Ejemplo
En el ejemplo siguiente se muestra cómo configurar una prueba de posicionamiento GeometryHitTestParameters
mediante para HitTest el método. El Point valor que se pasa OnMouseDown al método se usa para crear un
Geometry objeto con el fin de expandir el intervalo de la prueba de posicionamiento.

// Respond to the mouse button down event by setting up a hit test results callback.
private void OnMouseDown(object sender, MouseButtonEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);

// Expand the hit test area by creating a geometry centered on the hit test point.
EllipseGeometry expandedHitTestArea = new EllipseGeometry(pt, 10.0, 10.0);

// Clear the contents of the list used for hit test results.
hitResultsList.Clear();

// Set up a callback to receive the hit test result enumeration.


VisualTreeHelper.HitTest(myControl, null,
new HitTestResultCallback(MyHitTestResultCallback),
new GeometryHitTestParameters(expandedHitTestArea));

// Perform actions on the hit test results list.


if (hitResultsList.Count > 0)
{
ProcessHitTestResultsList();
}
}
' Respond to the mouse button down event by setting up a hit test results callback.
Private Overloads Sub OnMouseDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Retrieve the coordinate of the mouse position.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))

' Expand the hit test area by creating a geometry centered on the hit test point.
Dim expandedHitTestArea As New EllipseGeometry(pt, 10.0, 10.0)

' Clear the contents of the list used for hit test results.
hitResultsList.Clear()

' Set up a callback to receive the hit test result enumeration.


VisualTreeHelper.HitTest(myControl, Nothing, New HitTestResultCallback(AddressOf MyHitTestResultCallback),
New GeometryHitTestParameters(expandedHitTestArea))

' Perform actions on the hit test results list.


If hitResultsList.Count > 0 Then
ProcessHitTestResultsList()
End If
End Sub

La IntersectionDetail propiedad de GeometryHitTestResult proporciona información sobre los resultados de una


prueba de Geometry posicionamiento que utiliza como parámetro de prueba de posicionamiento. La siguiente
ilustración muestra la relación entre la geometría de la prueba de posicionamiento (círculo azul) y el contenido
representado del objeto visual de destino (cuadrado rojo).

En el ejemplo siguiente se muestra cómo implementar una devolución de llamada de Geometry la prueba de
posicionamiento cuando se usa un parámetro de prueba de posicionamiento. El result parámetro se convierte
en un GeometryHitTestResult objeto para recuperar el valor de la IntersectionDetail propiedad. El valor de
propiedad le permite determinar si el Geometry parámetro de la prueba de posicionamiento está incluido total o
parcialmente en el contenido representado del destino de la prueba de posicionamiento. En este caso, el código de
ejemplo solo está agregando los resultados de la prueba de posicionamiento a la lista para elementos visuales que
estén totalmente entro del límite de destino.
// Return the result of the hit test to the callback.
public HitTestResultBehavior MyHitTestResultCallback(HitTestResult result)
{
// Retrieve the results of the hit test.
IntersectionDetail intersectionDetail = ((GeometryHitTestResult)result).IntersectionDetail;

switch (intersectionDetail)
{
case IntersectionDetail.FullyContains:

// Add the hit test result to the list that will be processed after the enumeration.
hitResultsList.Add(result.VisualHit);

return HitTestResultBehavior.Continue;

case IntersectionDetail.Intersects:

// Set the behavior to return visuals at all z-order levels.


return HitTestResultBehavior.Continue;

case IntersectionDetail.FullyInside:

// Set the behavior to return visuals at all z-order levels.


return HitTestResultBehavior.Continue;

default:
return HitTestResultBehavior.Stop;
}
}

' Return the result of the hit test to the callback.


Public Function MyHitTestResultCallback(ByVal result As HitTestResult) As HitTestResultBehavior
' Retrieve the results of the hit test.
Dim intersectionDetail As IntersectionDetail = (CType(result, GeometryHitTestResult)).IntersectionDetail

Select Case intersectionDetail


Case IntersectionDetail.FullyContains

' Add the hit test result to the list that will be processed after the enumeration.
hitResultsList.Add(result.VisualHit)

Return HitTestResultBehavior.Continue

Case IntersectionDetail.Intersects

' Set the behavior to return visuals at all z-order levels.


Return HitTestResultBehavior.Continue

Case IntersectionDetail.FullyInside

' Set the behavior to return visuals at all z-order levels.


Return HitTestResultBehavior.Continue

Case Else
Return HitTestResultBehavior.Stop
End Select
End Function

NOTE
No HitTestResult se debe llamar a la devolución de llamada cuando el Emptydetalle de la intersección es.
Vea también
Realizar pruebas de posicionamiento en la capa visual
Geometría de una prueba de posicionamiento en un objeto Visual
Cómo: Realizar pruebas de posicionamiento
mediante un contenedor host Win32
20/02/2020 • 4 minutes to read • Edit Online

Puede crear objetos visuales en una ventana de Win32 proporcionando un contenedor de ventana host para los
objetos visuales. Para proporcionar control de eventos para los objetos visuales contenidos, proceso los mensajes
que se pasan al bucle de filtro de mensajes del contenedor de la ventana del host. Consulte Tutorial: hospedar
objetos visuales en una aplicación Win32 para obtener más información sobre cómo hospedar objetos visuales en
una ventana de Win32.

Ejemplo
En el código siguiente se muestra cómo configurar los controladores de eventos del mouse para una ventana de
Win32 que se usa como contenedor host para objetos visuales.

// Constant values from the "winuser.h" header file.


internal const int WM_LBUTTONUP = 0x0202,
WM_RBUTTONUP = 0x0205;

internal static IntPtr ApplicationMessageFilter(


IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages passed to the visual.
switch (message)
{
// Handle the left and right mouse button up messages.
case WM_LBUTTONUP:
case WM_RBUTTONUP:
System.Windows.Point pt = new System.Windows.Point();
pt.X = (uint)lParam & (uint)0x0000ffff; // LOWORD = x
pt.Y = (uint)lParam >> 16; // HIWORD = y
MyShape.OnHitTest(pt, message);
break;
}

return IntPtr.Zero;
}

' Constant values from the "winuser.h" header file.


Friend Const WM_LBUTTONUP As Integer = &H202, WM_RBUTTONUP As Integer = &H205

Friend Shared Function ApplicationMessageFilter(ByVal hwnd As IntPtr, ByVal message As Integer, ByVal wParam
As IntPtr, ByVal lParam As IntPtr, ByRef handled As Boolean) As IntPtr
' Handle messages passed to the visual.
Select Case message
' Handle the left and right mouse button up messages.
Case WM_LBUTTONUP, WM_RBUTTONUP
Dim pt As New System.Windows.Point()
pt.X = CUInt(lParam) And CUInt(&HFFFF) ' LOWORD = x
pt.Y = CUInt(lParam) >> 16 ' HIWORD = y
MyShape.OnHitTest(pt, message)
End Select

Return IntPtr.Zero
End Function
En el ejemplo siguiente se muestra cómo configurar una prueba de posicionamiento en respuesta a la captura de
eventos de mouse concretos.

// Constant values from the "winuser.h" header file.


public const int WM_LBUTTONUP = 0x0202,
WM_RBUTTONUP = 0x0205;

// Respond to WM_LBUTTONUP or WM_RBUTTONUP messages by determining which visual object was clicked.
public static void OnHitTest(System.Windows.Point pt, int msg)
{
// Clear the contents of the list used for hit test results.
hitResultsList.Clear();

// Determine whether to change the color of the circle or to delete the shape.
if (msg == WM_LBUTTONUP)
{
MyWindow.changeColor = true;
}
if (msg == WM_RBUTTONUP)
{
MyWindow.changeColor = false;
}

// Set up a callback to receive the hit test results enumeration.


VisualTreeHelper.HitTest(MyWindow.myHwndSource.RootVisual,
null,
new HitTestResultCallback(CircleHitTestResult),
new PointHitTestParameters(pt));

// Perform actions on the hit test results list.


if (hitResultsList.Count > 0)
{
ProcessHitTestResultsList();
}
}

' Constant values from the "winuser.h" header file.


Public Const WM_LBUTTONUP As Integer = &H0202, WM_RBUTTONUP As Integer = &H0205

' Respond to WM_LBUTTONUP or WM_RBUTTONUP messages by determining which visual object was clicked.
Public Shared Sub OnHitTest(ByVal pt As System.Windows.Point, ByVal msg As Integer)
' Clear the contents of the list used for hit test results.
hitResultsList.Clear()

' Determine whether to change the color of the circle or to delete the shape.
If msg = WM_LBUTTONUP Then
MyWindow.changeColor = True
End If
If msg = WM_RBUTTONUP Then
MyWindow.changeColor = False
End If

' Set up a callback to receive the hit test results enumeration.


VisualTreeHelper.HitTest(MyWindow.myHwndSource.RootVisual, Nothing, New HitTestResultCallback(AddressOf
CircleHitTestResult), New PointHitTestParameters(pt))

' Perform actions on the hit test results list.


If hitResultsList.Count > 0 Then
ProcessHitTestResultsList()
End If
End Sub

El objeto HwndSource presenta Windows Presentation Foundation (WPF ) contenido dentro de una ventana de
Win32. El valor de la propiedad RootVisual del objeto HwndSource representa el nodo de nivel superior de la
jerarquía de árbol visual.
Para obtener el ejemplo completo de los objetos de prueba de posicionamiento mediante un contenedor host de
Win32, vea prueba de posicionamiento con el ejemplo de interoperación de Win32.

Consulte también
HwndSource
Realizar pruebas de posicionamiento en la capa visual
Tutorial: Hospedar objetos visuales en una aplicación Win32
Procedimiento Representar un intervalo para cada
fotograma mediante CompositionTarget
23/10/2019 • 6 minutes to read • Edit Online

El motor de animación WPF proporciona muchas características para crear animaciones basadas en fotogramas.
Sin embargo, hay escenarios de aplicación en el los que necesita un control específico sobre la representación
según el fotograma. El CompositionTarget objeto proporciona la capacidad de crear animaciones personalizadas
basadas en una devolución de llamada por fotograma.
CompositionTargetes una clase estática que representa la superficie de presentación en la que se dibuja la
aplicación. El Rendering evento se desencadena cada vez que se dibuja la escena de la aplicación. La velocidad de
los fotogramas de representación es el número de veces que se dibuja la escena por segundo.

NOTE
Para obtener un ejemplo de código CompositionTargetcompleto con, vea usar el ejemplo de CompositionTarget.

Ejemplo
El Rendering evento se desencadena durante WPF el proceso de representación. En el ejemplo siguiente se
muestra cómo registrar EventHandler un delegado en el Rendering método estático CompositionTargeten.

// Add an event handler to update canvas background color just before it is rendered.
CompositionTarget.Rendering += UpdateColor;

' Add an event handler to update canvas background color just before it is rendered.
AddHandler CompositionTarget.Rendering, AddressOf UpdateColor

Puede utilizar el método de controlador de eventos de representación para crear contenido de dibujo
personalizado. Se llama a este método de control de eventos una vez por cada fotograma. Cada vez que WPF
serializa los datos de representación conservados en el árbol visual hasta el gráfico de escena de composición, se
llama a este método de control de eventos. Además, si los cambios en el árbol visual fuerzan actualizaciones en el
gráfico de escena de composición, también se llama al método de controlador de eventos. Observe que se llama a
su método de controlador de eventos después de calcular el diseño. Sin embargo, puede modificar el diseño en su
método de controlador de eventos, lo que significa que el diseño se calcula una vez más antes de su
representación.
En el ejemplo siguiente se muestra cómo puede proporcionar un dibujo personalizado CompositionTarget en un
método de control de eventos. En este caso, el color de fondo de Canvas se dibuja con un valor de color basado en
la posición de la coordenada del mouse. Si mueve el mouse dentro de Canvas, cambia el color de fondo. Además,
se calcula la velocidad de fotogramas media, según el tiempo transcurrido actual y el número total de fotogramas
representados.
// Called just before frame is rendered to allow custom drawing.
protected void UpdateColor(object sender, EventArgs e)
{
if (_frameCounter++ == 0)
{
// Starting timing.
_stopwatch.Start();
}

// Determine frame rate in fps (frames per second).


long frameRate = (long)(_frameCounter / this._stopwatch.Elapsed.TotalSeconds);
if (frameRate > 0)
{
// Update elapsed time, number of frames, and frame rate.
myStopwatchLabel.Content = _stopwatch.Elapsed.ToString();
myFrameCounterLabel.Content = _frameCounter.ToString();
myFrameRateLabel.Content = frameRate.ToString();
}

// Update the background of the canvas by converting MouseMove info to RGB info.
byte redColor = (byte)(_pt.X / 3.0);
byte blueColor = (byte)(_pt.Y / 2.0);
myCanvas.Background = new SolidColorBrush(Color.FromRgb(redColor, 0x0, blueColor));
}

' Called just before frame is rendered to allow custom drawing.


Protected Sub UpdateColor(ByVal sender As Object, ByVal e As EventArgs)

If _frameCounter = 0 Then
' Starting timing.
_stopwatch.Start()
End If
_frameCounter = _frameCounter + 1

' Determine frame rate in fps (frames per second).


Dim frameRate As Long = CLng(Fix(_frameCounter / Me._stopwatch.Elapsed.TotalSeconds))
If frameRate > 0 Then
' Update elapsed time, number of frames, and frame rate.
myStopwatchLabel.Content = _stopwatch.Elapsed.ToString()
myFrameCounterLabel.Content = _frameCounter.ToString()
myFrameRateLabel.Content = frameRate.ToString()
End If

' Update the background of the canvas by converting MouseMove info to RGB info.
Dim redColor As Byte = CByte(_pt.X / 3.0)
Dim blueColor As Byte = CByte(_pt.Y / 2.0)
myCanvas.Background = New SolidColorBrush(Color.FromRgb(redColor, &H0, blueColor))
End Sub

Es posible que descubra que el dibujo personalizado se ejecuta a distintas velocidades en equipos diferentes. Esto
es porque el dibujo personalizado no depende de la velocidad de los fotogramas. En función del sistema que se
esté ejecutando y de la carga de trabajo de ese Rendering sistema, el evento se puede llamar un número diferente
de veces por segundo. Para información sobre el establecimiento de una capacidad de hardware gráfico y el
rendimiento de un dispositivo que ejecute una aplicación WPF, vea Niveles de representación de gráficos.
La adición o eliminación de un EventHandler delegado de representación mientras se activa el evento se retrasará
hasta que finalice la activación del evento. Esto es coherente con la MulticastDelegateforma en que se administran
los eventos basados en en Common Language Runtime (CLR ). Tenga en cuenta que no se garantiza que los
eventos de representación se llamen en un orden determinado. Si tiene varios EventHandler delegados que
dependen de un orden determinado, debe registrar un solo Rendering evento y multiplexar los delegados en el
orden correcto.
Vea también
CompositionTarget
Información general sobre la representación de gráficos en WPF

También podría gustarte