Silverlight предоставляет разработчикам унифицированную модель программирования для реализации ожиданий веб-пользователей, которая включает графику, анимацию и мультимедиа.
В этой статье описываются способы создания приложений на базе Silverlight с графикой, анимацией и мультимедиа. В данной статье мы поговорим об использовании двумерных (2-D) классов Transform в Silverlight для поворота, масштабирования, наклона и перемещения (перевода) объектов.
Transform определяет способ сопоставления или преобразования точек из одного координатного пространства в другое. Это сопоставление описано преобразованием Matrix, которое представляет собой коллекцию из трех строк с тремя столбцами, содержащую значения типа Double.Silverlight использует матрицы, основанные на строках. Векторы представляют собой векторы-строки, а не векторы-столбцы.
В следующей таблице показана структура матрицы Silverlight.
Значение по умолчанию: 1,0
|
Значение по умолчанию: 0,0
|
0.0
|
Значение по умолчанию: 0,0
|
Значение по умолчанию: 1,0
|
0.0
|
Значение по умолчанию: 0,0
|
Значение по умолчанию: 0,0
|
1.0
|
Управляя значениями матрицы, можно поворачивать, масштабировать, наклонять и перемещать объект. Например, изменив значения в первом столбце третьей строки (значение OffsetX) на 100, можно переместить объект на 100 единиц вдоль оси X. Изменив значение во втором столбце второй строки на 3, можно растянуть объект в высоту в три раза относительно текущего размера. Если изменить оба значения, объект переместится на 100 единиц вдоль оси X и растянется в высоту с коэффициентом 3. Поскольку Silverlight поддерживает только аффинные преобразования, значения в правом столбце всегда остаются равными 0, 0, 1.
Несмотря на то, что Silverlight предоставляет возможность непосредственно управлять значениями матрицы, в Silverlight также имеется несколько классов Transform, позволяющих преобразовывать объект, не зная структуру базовой матрицы. Например, класс ScaleTransform позволяет масштабировать объект с помощью определения его свойств ScaleX и ScaleY вместо управления матрицей преобразования. Аналогично класс RotateTransform позволяет повернуть объект, просто задав его свойство Angle.
Silverlight предоставляет следующие двумерные классы Transform для стандартных операций преобразования.
Класс
|
Описание
|
Поворачивает элемент на значение, заданное в Angle.
| |
Для совершения более сложных преобразований Silverlight предоставляет следующие три класса:
Класс
|
Описание
|
Используйте этот класс, чтобы применить несколько преобразований к одному и тому же объекту (например, наклон и вращение). Этот класс применяет несколько преобразований в предпочтительном порядке и поэтому обычно является наилучшим способом применения нескольких преобразований.
| |
Как в случае с CompositeTransform, можно использовать этот класс для применения нескольких преобразований; тем не менее, класс CompositeTransform является предпочтительным средством для этого, если не требуется применить преобразования в определенном порядке или применить различные центральные точки для различных преобразований.
| |
Создает настраиваемые преобразования, не предоставленные другими классами Transform. При использовании MatrixTransform происходит непосредственное управление матрицей.
|
В своём примере я использую основные преобразования, такие как RotateTransform, ScaleTransform, SkewTransform и MatrixTransform. Наболее сложное из них, это последнее преобразование.
MatrixTransform используется для создания пользовательских преобразований, не предоставленных классами RotateTransform, ScaleTransform, SkewTransform и TranslateTransform.
Двухмерная плоскость x-y использует для преобразований матрицу 3 x 3. Аффинные преобразования с матричным представлением можно умножать для получения линейных преобразований, таких как поворот и отклонение (сдвиг), следующих за переносом.
Последний столбец аффинного преобразования с матричным представлением равен (0, 0, 1); поэтому необходимо лишь задать члены первых двух столбцов.
Члены в последней строке, OffsetX и OffsetY, представляют значения преобразования.
Обычно методы и свойства задают матрицу преобразования как вектор, имеющий только шесть членов; эти члены таковы:
(M11, M12, M21, M22, OffsetX, OffsetY)
Можно сместить локальную позицию (0,0) для объекта на Canvas с помощью свойств Canvas..::..Left и Canvas..::..Top, но это не считается преобразованием; в этом случае объект сохраняет собственную локальную (0,0) позицию для преобразования.
Ну на этом хватит теории, давайте приступим к практике. Давайте рассмотрим пример, который рисует одну и ту же фигуру (улыбающееся существо) используя различные преобразования.
<Window x:Class="TransformationDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="240" Width="700">
<StackPanel Orientation="Horizontal">
<Canvas Margin="5" Background="Green" Height="120" Width="120">
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5" />
</Canvas.LayoutTransform>
<Path Canvas.Top="0" Canvas.Left="0" Stroke="Black" >
<Path.Fill>
<RadialGradientBrush GradientOrigin="0.2,0.2">
<GradientStop Offset="0" Color="LightBlue" />
<GradientStop Offset="0.6" Color="Blue" />
<GradientStop Offset="1.0" Color="DarkBlue" />
</RadialGradientBrush>
</Path.Fill>
<Path.Data>
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="60,60" RadiusX="60" RadiusY="40" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry Rect="20,60 85 50" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Ellipse Canvas.Left="30" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
<Ellipse Canvas.Left="40" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
<Ellipse Canvas.Left="65" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
<Ellipse Canvas.Left="75" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
<Path Name="mouth" Stroke="Red" StrokeThickness="4" Data="M 40,74 Q 57,95 80,74 " />
</Canvas>
<Canvas Background="Red" Height="120" Width="120">
<Canvas.LayoutTransform>
<RotateTransform Angle="40" />
</Canvas.LayoutTransform>
<Path Canvas.Top="0" Canvas.Left="0" Stroke="Black" >
<Path.Fill>
<RadialGradientBrush GradientOrigin="0.2,0.2">
<GradientStop Offset="0" Color="LightBlue" />
<GradientStop Offset="0.6" Color="Blue" />
<GradientStop Offset="1.0" Color="DarkBlue" />
</RadialGradientBrush>
</Path.Fill>
<Path.Data>
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="60,60" RadiusX="60" RadiusY="40" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry Rect="20,60 85 50" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Ellipse Canvas.Left="30" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
<Ellipse Canvas.Left="40" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
<Ellipse Canvas.Left="65" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
<Ellipse Canvas.Left="75" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
<Path Stroke="Red" StrokeThickness="4" Data="M 40,74 Q 57,95 80,74 " />
</Canvas>
<Canvas Background="BlanchedAlmond" Height="120" Width="120">
<Canvas.LayoutTransform>
<SkewTransform AngleX="20" AngleY="25" />
</Canvas.LayoutTransform>
<Path Canvas.Top="0" Canvas.Left="0" Stroke="Black" >
<Path.Fill>
<RadialGradientBrush GradientOrigin="0.2,0.2">
<GradientStop Offset="0" Color="LightBlue" />
<GradientStop Offset="0.6" Color="Blue" />
<GradientStop Offset="1.0" Color="DarkBlue" />
</RadialGradientBrush>
</Path.Fill>
<Path.Data>
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="60,60" RadiusX="60" RadiusY="40" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry Rect="20,60 85 50" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Ellipse Canvas.Left="30" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
<Ellipse Canvas.Left="40" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
<Ellipse Canvas.Left="65" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
<Ellipse Canvas.Left="75" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
<Path Stroke="Red" StrokeThickness="4" Data="M 40,74 Q 57,95 80,74 " />
</Canvas>
<Canvas Background="Aqua" Height="120" Width="120">
<Canvas.LayoutTransform>
<MatrixTransform>
<MatrixTransform.Matrix>
<Matrix M11="0.8" M22="1.9" M12="1.3" M21="0.4" />
</MatrixTransform.Matrix>
</MatrixTransform>
</Canvas.LayoutTransform>
<Path Canvas.Top="0" Canvas.Left="0" Stroke="Black" >
<Path.Fill>
<RadialGradientBrush GradientOrigin="0.2,0.2">
<GradientStop Offset="0" Color="LightBlue" />
<GradientStop Offset="0.6" Color="Blue" />
<GradientStop Offset="1.0" Color="DarkBlue" />
</RadialGradientBrush>
</Path.Fill>
<Path.Data>
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="60,60" RadiusX="60" RadiusY="40" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry Rect="20,60 85 50" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Ellipse Canvas.Left="30" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
<Ellipse Canvas.Left="40" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
<Ellipse Canvas.Left="65" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
<Ellipse Canvas.Left="75" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
<Path Stroke="Red" StrokeThickness="4" Data="M 40,74 Q 57,95 80,74 " />
</Canvas>
</StackPanel>
</Window>
|
Вот то, что получилось у меня, надеюсь у вас получилось ещё лучше J
Комментариев нет:
Отправить комментарий