Главная » Разработка для Windows Phone 7 » Синтаксис разметки контура Windows Phone 7

0

Silverlight поддерживает некоторого рода «мини-язык», который позволяет описывать весь PathGeometry в строке. В этом языке объекты PathFigure и PathSegment замещены буквами (такие как M, что означает Move (Перемещение), L – Line (Линия), A – Arc (Дуга), и C – Cubic Bezier (Кубическая кривая Безье)). Каждый новый PathFigure начинается с команды Move. Этот синтаксис описан в разделе Graphics (Графические элементы) в онлайн-документации по Silverlight.

Рассмотрим пример:

<Grid Background="LightCyan"> <Path Stroke="Maroon"

StrokeThickness="4"

Data="M 160 140  L 150 50 220

103

M 320 140  L 330 50 260

103

M 215 230  L 40 200

M 215 240  L 40 240

M 215 250  L 40 280

M 265 230  L 440 200

M 265 240  L 440 240

M 265 250      L 440 280 M 240 100

A 100 100                   0 0 1 240 300

A 100 100                   0 0 1 240 100 M 180 170

A 40 40 0                   0 1 220 170

A 40 40 0                   0 1 180 170 M 300 170

A 40 40 0                   0 1 260 170

A 40 40 0                   0 1 300 170" />

</Grid>

Самым сложным является синтаксис описания дуги. Он начинается с задания размера эллипса, за которым следуют угол поворота и два флага: 1 для IsLargeArc и 1 для Clockwise. В конце задаются координаты точки. Для отрисовки замкнутой окружности ее разделяют на две половины и используют две команды Arc (или два объекта ArcSegment).

Геометрические элементы могут использоваться не только для рисования, но и для вырезания. Рассмотрим знаменитое изображение KeyholeOnTheMoon (Взгляд на Луну через замочную скважину):

В данном приложении используется свойство Clip (Вырезанное изображение) типа Geometry. Свойство Clip описано классом FrameworkElement и позволяет сделать визуально непрямоугольным любой элемент или элемент управления, а благодаря Path Markup Syntax (Синтаксис разметки контура) эта задача становится совершенно тривиальной:

Проект Silverlight: KeyholeOnTheMoon Файл: MainPage.xaml (фрагмент)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0r Background="{StaticResource PhoneAccentBrush}"> <Image Source="Images/BuzzAldrinOnTheMoon.png" Stretch="None"

Clip="M 120 95 L 90 265 L 220 265 L 190 95 A 50 50 0 1 0 120 95" />

</Grid>

Я также использовал Silverlight Path Markup Syntax в приложении Analog Clock (Аналоговые часы). Вот как они выглядят:

Визуальное представление образовано пятью элементами Path. Кривые на часовой и минутной стрелках – это сплайны Безье. Штриховые метки циферблата – это отрисованные пунктиром дуговые сегменты.

XAML-файл определяет Style, применяемый ко всем пяти элементам Path: Проект Silverlight: AnalogClock Файл: MainPage.xaml (фрагмент)

<phone:PhoneApplicationPage.Resources> <Style x:Key="pathStyle" TargetType="Path"> <Setter Property="Fill" Value="{StaticResource PhoneAccentColor}" /> <Setter Property="Stroke" Value="{StaticResource PhoneForegroundColor}" /> <Setter Property="StrokeThickness" Value="2" /> <Setter Property="StrokeStartLineCap" Value="Round" /> <Setter Property="StrokeEndLineCap" Value="Round" /> <Setter Property="StrokeLineJoin" Value="Round" /> <Setter Property="StrokeDashCap" Value="Round" /> </Style>

</phone:PhoneApplicationPage.Resources>

Чтобы не усложнять, я выбрал произвольную систему координат. Графические элементы часов отрисовываются, исходя из предположения о том, что ширина и высота циферблата составляет 200 пикселов, и центр располагается в точке (0, 0). Таким образом, мы имеем диапазон допустимых значений слева направо (по оси Х) от -100 до 100 и сверху вниз (по оси Y) – от -100 до 100.

Частично эти произвольные координаты часов определены явно заданными Width и Height вложенного Grid:

Проект Silverlight: AnalogClock Файл: MainPage.xaml (фрагмент)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" SizeChanged="OnContentPanelSizeChanged">

<!– Отрисовываем часы на Grid с центром в точке (0, 0) –> <Grid Width="2 0 0" Height="2 0 0">

<Grid.RenderTransform> <TransformGroup>

<ScaleTransform x:Name="scaleClock" /> <TranslateTransform X="100" Y="100" /> </TransformGroup> </Grid.RenderTransform>

</Grid> </Grid>

Трансформация TranslateTransform смещает весь Grid вправо и вниз. Например, верхний левый угол, который располагался в точке (-100, -100), смещается в точку с координатами (0, 0); а точка с координатами (100, 100) перемещается в точку с координатами (200, 200).

Обратите внимание на обработчик событий SizeChanged, заданный в обычной сетке для содержимого. В коде для ScaleTransform, который применятся к вложенному Grid, используется фактический размер области содержимого. Это приводит произвольно выбранный размер в 200 пикселов к фактическому размеру:

Проект Silverlight: AnalogClock Файл: MainPage.xaml.cs (фрагмент)

void OnContentPanelSizeChanged(object sender, SizeChangedEventArgs args) {

double scale = Math.Min(args.NewSize.Width, args.NewSize.Height) / 200; scaleClock.ScaleX = scale; scaleClock.ScaleY = scale;

}

Рассмотрим пять контуров:

Проект Silverlight: AnalogClock Файл: MainPage.xaml (фрагмент)

<!– Деления на циферблате (маленькие и большие). –>

<Path Data="M 0 -90 A 90 90 0 1 1 0 90

A 90 90 0 1 1 0 -90" Style="{StaticResource pathStyle}" Fill="{x:Null}" StrokeDashArray="0 3.14159" StrokeThickness="3" />

<Path Data="M 0 -90 A 90 90 0 1 1 0 90

A 90 90 0 1 1 0 -90" Style="{StaticResource pathStyle}" Fill="{x:Null}" StrokeDashArray="0 7.854" StrokeThickness="6" />

<!– Часовая стрелка, указывающая на 12 часов. –>

<Path Data="M 0 -60 C 0 -30, 20 -30, 5 -20 L 5 0

C 5 7.5, -5 7.5, -5 0 L -5 -20 C -20 -30, 0 -30 0 -60" Style="{StaticResource pathStyle}"> <Path.RenderTransform>

<RotateTransform x:Name="rotateHour" /> </Path.RenderTransform>

</Path>

<!– Минутная стрелка, указывающая на 12 часов. –>

<Path Data="M 0 -80 C 0 -75, 0 -70, 2.5 -60 L 2.5 0

C 2.5 5, -2.5 5, -2.5 0 L -2.5 -60 C 0 -70, 0 -75, 0 -80" Style="{StaticResource pathStyle}"> <Path.RenderTransform>

<RotateTransform x:Name="rotateMinute" /> </Path.RenderTransform> </Path>

<!– Секундная стрелка, указывающая на 12 часов. –> <Path Data="M 0 10 L 0 -80"

Style="{StaticResource pathStyle}"> <Path.RenderTransform>

<RotateTransform x:Name="rotateSecond" /> </Path.RenderTransform> </Path>

Параметры StrokeDashArray первых двух элементов Path тщательно просчитаны для создания шаблона делений на циферблате для 1 и 5 секунд. В качестве значений свойств RenderTransform остальных трех элементов Path заданы объекты RotateTransform. Эти объекты RotateTransform задаются повторно каждую секунду из файла выделенного кода:

Проект Silverlight: AnalogClock Файл: MainPage.xaml.cs (фрагмент)

public partial class MainPage : PhoneApplicationPage {

public MainPage() {

InitializeComponent();

DispatcherTimer tmr = new DispatcherTimer(); tmr.Interval = TimeSpan.FromSeconds(1); tmr.Tick += new EventHandler(OnTimerTick); tmr.Start();

}

void OnTimerTick(object sender, EventArgs args) {

DateTime dt = DateTime.Now; rotateSecond.Angle = 6 * dt.Second;

rotateMinute.Angle = 6 * dt.Minute + rotateSecond.Angle / 60; rotateHour.Angle = 30 * (dt.Hour % 12) + rotateMinute.Angle / 12;

}

}

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

  • Комментарии