Основы XAML

Интерактивность

Разбить на страницы
Показывать лекцию целиком

Silverlight и JavaScript

Silverlight поддерживает базовый набор функций JavaScript, описание которого приводится в разделе "JavaScript API for Silverlight Reference" (http://msdn.microsoft.com/en-us/library/bb979679(VS.95).aspx). Можно ожидать, что последующие версии Silverlight будут включать в себя все больший набор возможностей JavaScript.

Связывание произвольной JavaScript функции с определенным событием осуществляется так:

MouseLeftButtonDown="myFunction"

Здесь MouseLeftButtonDown - событие, возникающее при нажатии левой кнопки мыши, а myFunction – имя функции, которая должна запускаться при возникновении этого события. В XAML-коде эта связка задается в описании элемента:

<Canvas
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="200" Height="100"
  Background="White"
  x:Name="Page">
  <Rectangle Width="100" Height="30" 
   Canvas.Left="50" Canvas.Top="40" 
    Fill="yellow" RadiusY="10" RadiusX="10" 
    Stroke="green" StrokeThickness="5" 
    MouseLeftButtonDown="myFunction"/>
</Canvas>

Названия событий является зарезервированными, более того, регистр также учитывается. Перечень событий приводится в разделе " Events Reference" (http://msdn.microsoft.com/en-us/library/bb980189(VS.95).aspx). Функция myFunction определяется в специальном файле "Page.xaml.js", который находится в папке проекта (рис. 8.1):

(рис 8.1) Файл "Page.xaml.js".

Внутри функции определяется функциональность, например появление простейшего диалогового окна:

function myFunction () {
  alert ("Привет, Silverlight и JavaScript!");
}

В результате, при нажатии на прямоугольник, в браузере появляется диалоговое окно (рис. 8.2):

(рис 8.2) Простейший пример взаимодействия Silverlight и JavaScript

Использование JavaScript в Silverlight-проектах – отличный способ определить функциональность на стороне клиента. Это означает, что при выполнении различных действий пользователь не будет ждать перезагрузки страницы, так как выполнение JavaScript не требует обращения к серверу.

В табл. 8.1приводится несколько других несложных примеров.

Silverlight и JavaScript
Код Вид в браузере
8.1.1
Page.xaml:
<Canvas
xmlns="http://schemas.microsoft.com/
client/2007"
xmlns:x="http://schemas.microsoft.com/
winfx/2006/xaml"
Width="200" Height="100"
Background="White"
x:Name="Page">

    
 <Rectangle Canvas.Left="5" 
Canvas.Top="5" Width="190" 
Height="90"
 Fill="Transparent"  
 Stroke="green" 
StrokeThickness="2"/>
   
<Rectangle x:Name="myRectangle" 
Canvas.Left="20" 
Canvas.Top="20" 
Width="100" Height="50" 
 Fill="Orange" 
 MouseEnter="DoMouseEnter" 
MouseLeave="DoMouseLeave"/>
  
</Canvas>

Page.xaml.js:

function DoMouseEnter(sender, mouseEventArgs)
{   
 sender.findName("myRectangle").
Fill="Red";
}
function DoMouseLeave(sender, mouseEventArgs)
{   
 sender.findName("myRectangle").
Fill="Orange";
}
Описание
При наведении курсора на прямоугольник он становится красным. При выходе курсора из области прямоугольника цвет становится прежним
Код Вид в браузере
8.1.2
Page.xaml:
<Canvas
xmlns="http://schemas.microsoft.com/
client/2007"
xmlns:x="http://schemas.microsoft.com/
winfx/2006/xaml"
Width="310" Height="50"
Background="White"
x:Name="Page">

    
 <Rectangle Canvas.Left="5" 
Canvas.Top="5" Width="300" 
Height="40"
 Fill="Transparent"  
 Stroke="green"
 StrokeThickness="2"/>
   


 <TextBlock
 Canvas.Left="12" 
 Canvas.Top="12" 
 FontSize="14"
 Foreground="Orange"
 x:Name="myTextBlock" 
MouseEnter="DoMouseEnter" 
MouseLeftButtonDown="
DoMouseLeftButtonDown" 
MouseLeftButtonUp="
DoMouseLeftButtonUp" 
MouseLeave="DoMouseLeave"
Text="Наведите мышь и щелкните!" />  
 
  
</Canvas>

Page.xaml.js:

function DoMouseEnter(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
FontSize="20";
}
function DoMouseLeftButtonDown(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
Foreground="Red";
}

function DoMouseLeftButtonUp(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
Foreground="Orange";
}
function DoMouseLeave(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
FontSize="14";
}
Описание
При наведении курсора текст увеличивается, при нажатии левой кнопки мыши он становится красным
Код Вид в браузере
8.1.3
Page.xaml:
<Canvas
xmlns="http://schemas.microsoft.com/
client/2007"
xmlns:x="http://schemas.microsoft.com/
winfx/2006/xaml"
Width="300" Height="120"
Background="White"
x:Name="Page">    
 <Rectangle Canvas.Left="5"
 Canvas.Top="5" Width="290" 
Height="110"
 Fill="Transparent"  
 Stroke="green" 
StrokeThickness="2"/>
 
 <!-- Кнопка с подписью-->
  
<Ellipse x:Name="myEllipse"
 Width="152" Height="41" 
Canvas.Left="73"
 Canvas.Top="55" Fill="Pink"
 Stroke="Red" 
 StrokeThickness="5" 
MouseEnter="DoMouseEnter" 
MouseLeave="DoMouseLeave" />
 
  <TextBlock
 Canvas.Left="112" 
 Canvas.Top="68" 
 FontSize="11"
 Text="Изменить цвет"
MouseEnter="DoMouseEnter" 
MouseLeave="DoMouseLeave" />  
  
<!--Изменяемая надпись-->

 <TextBlock
 Canvas.Left="100" 
 Canvas.Top="12" 
 FontSize="14"
 Foreground="Blue"
 x:Name="myTextBlock" 
 Text="XAML-графика" />   
 
  
</Canvas>

Page.xaml.js:

function DoMouseEnter(sender, mouseEventArgs)
{   
sender.findName("myTextBlock").
Foreground="Red";
}
function DoMouseLeave(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
Foreground="Blue";
}
Описание
При наведении курсора мыши на кнопку цвет надписи меняется. Для получения этой функциональности обработка событий привязывается как к эллипсу, так и к расположенному на нем текстовому элементу
Код Вид в браузере
8.1.4
Page.xaml:
<Canvas
xmlns="http://schemas.microsoft.com/
client/2007"
xmlns:x="http://schemas.microsoft.com/
winfx/2006/xaml"
Width="300" Height="120"
Background="White"
x:Name="Page">    
 <Rectangle Canvas.Left="5" 
Canvas.Top="5" Width="290"
 Height="110"
 Fill="Transparent"  
Stroke="green" 
StrokeThickness="2"/>

 <!-- Кнопка с подписью-->
  
<Ellipse x:Name="myEllipse" 
Width="152" 
Height="41" Canvas.Left="73"
 Canvas.Top="55" Fill="Pink" 
Stroke="Red" 
StrokeThickness="5" 
MouseEnter="DoMouseEnter" 
MouseLeave="DoMouseLeave" />
 
  <TextBlock
 Canvas.Left="112" 
 Canvas.Top="68" 
 FontSize="11"
 Text="Изменить цвет"
MouseEnter="DoMouseEnter" 
MouseLeave="DoMouseLeave" />  
  
<!--Изменяемая надпись-->

 <TextBlock
 Canvas.Left="100" 
 Canvas.Top="12" 
 FontSize="14"
 Foreground="Blue"
 x:Name="myTextBlock" 
 Text="XAML-графика" />   
 
  
</Canvas>

Page.xaml.js:

function DoMouseEnter(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
Foreground="Red";
 sender.findName("myTextBlock").
FontSize="24";
}
function DoMouseLeave(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
Foreground="Blue";
 sender.findName("myTextBlock").
FontSize="14";
}
Описание
Изменение цвета и размера шрифта при наведении курсора
Код Вид в браузере
8.1.5
Page.xaml:
<Canvas
xmlns="http://schemas.microsoft.com/
client/2007"
xmlns:x="http://schemas.microsoft.com/
winfx/2006/xaml"
Width="300" Height="120"
Background="White"
x:Name="Page">    
 <Rectangle Canvas.Left="5" 
Canvas.Top="5" Width="290" 
Height="110"
 Fill="Transparent"  
Stroke="green" 
StrokeThickness="2"/>
 
 <!-- Кнопка с подписью-->
  
<Ellipse x:Name="myEllipse" 
Width="152" Height="41" 
Canvas.Left="73"
 Canvas.Top="55" Fill="Pink" 
Stroke="Red" 
StrokeThickness="5" 
MouseLeftButtonDown=
"DoMouseLeftButtonDown" 
MouseLeftButtonUp=
"DoMouseLeftButtonUp" />  

 
  <TextBlock
 Canvas.Left="112" 
 Canvas.Top="68" 
 FontSize="11"
 Text="Изменить цвет"
MouseLeftButtonDown=
"DoMouseLeftButtonDown" 
MouseLeftButtonUp=
"DoMouseLeftButtonUp" />  
  
<!--Изменяемая надпись-->

 <TextBlock
 Canvas.Left="100" 
 Canvas.Top="12" 
 FontSize="14"
 Foreground="Blue"
 x:Name="myTextBlock" 
 Text="XAML-графика" />   
 
  
</Canvas>

Page.xaml.js:

function DoMouseLeftButtonDown(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
Foreground="Red";
 sender.findName("myTextBlock").
FontSize=24;
}
function DoMouseLeftButtonUp(sender, mouseEventArgs)
{   
 sender.findName("myTextBlock").
Foreground="Blue";
 sender.findName("myTextBlock").
FontSize=14;
}
Описание
Изменение цвета и размера шрифта при нажатии левой кнопки мыши
Код Вид в браузере
8.1.6
Page.xaml:
<Canvas
xmlns="http://schemas.microsoft.com/
client/2007"
xmlns:x="http://schemas.microsoft.com/
winfx/2006/xaml"
Width="300" Height="120"
Background="White"
x:Name="Page"   
 GotFocus="onGotFocus"
  LostFocus="onLostFocus">
   
 <Rectangle Canvas.Left="5" 
Canvas.Top="5" Width="290" 
Height="110"
 Fill="Transparent"  
Stroke="green" 
StrokeThickness="2"/>


<!-- Текущий адрес-->
  
<Ellipse x:Name="myEllipse" 
Width="152" Height="41"
 Canvas.Left="73"
 Canvas.Top="18"
  Fill="Pink" 
Stroke="Red" 
StrokeThickness="5" 
MouseLeftButtonDown="currLocation" 
 />  
 
  <TextBlock
 Canvas.Left="135" 
 Canvas.Top="31" 
 FontSize="11"
 Text="ГДЕ Я?"
MouseLeftButtonDown="currLocation" 
 />
 
 <!-- Новый адрес -->
 
  <Ellipse x:Name="myEllipse_Copy1"
 Width="152" Height="41" 
Canvas.Left="73"
 Canvas.Top="66" Fill="Pink" 
Stroke="Red" StrokeThickness="5" 
    MouseLeftButtonDown="newLocation" 
 />
  <TextBlock
    Canvas.Left="122" 
    Canvas.Top="79" 
    FontSize="11"
    Text="ИНТУИТ.РУ"
    MouseLeftButtonDown="newLocation" 
 />  
 
  
</Canvas>

Page.xaml.js:


function currLocation()
{
alert(window.location)
}
function newLocation()
{
window.location="http://www.intuit.ru/"
}
Получение текущего адреса и переход на заданную ссылку. Эта функциональность получена с помощью свойства location объекта window самого JavaScript. Пример демонстрирует возможность создания гиперссылок
Описание

Использование JavaScript в XAML – достаточно увлекательное занятие. Для тех, кто знаком с JavaScript, здесь открывается новое поле деятельности. К сожалению, многие возможности еще не до конца реализованы в Silverlight (на момент написания курса), поэтому нельзя сказать, что старые подходы и концепции можно вообще без всяких изменений переносить в новые приложения.

Silverlight и C#

Применение языка C# в Silverlight-приложениях – самое ожидаемое действие для .NET программистов. Фактически, это одно из важнейших преимущество технологии – разрабатывать мультимедийные сайты теперь можно без необходимости менять технологии и среду разработки. Создадим простое приложение, в котором анимация XAML будет изменяться с помощью C#. Запускаем Visual Studio 2008, создаем новый проект "SilverlightCSahrp" типа "Silverlight Application" (рис. 8.3):

(рис 8.3) Создание нового Silverlight-приложения в среде Visual Studio .NET 2008

Появившейся XAML-код изменим следующим образом:

<UserControl x:Class="SilverlightCSharp.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       Width="800" Height="600">
    <Canvas x:Name="LayoutRoot" Background="White">

        </Canvas>
</UserControl>

Вместо элемента Grid будем использовать привычный Canvas. Добавим XAML-код кнопки, которая носит привычное название Button:

<Button Width="150" Height="50" Canvas.Left="50" 
Canvas.Top="250" Content="Изменить текст" 
x:Name="myButton" ></Button>

В принципе, добавлять элементы можно и перетаскиванием их из панели Toolbox. В любом случае, появляется кнопка, встроенное оформление которой вполне придает ей "трехмерный" вид. Для создания обработчика события Click достаточно ввести первые буквы – IntelliSense предложит вставить подходящее значение (рис. 8.4):

(рис 8.4) Применение IntelliSense для написания события Click

Сразу после вставки среда предлагает создать новый обработчик события (Event Handler) (рис. 8.5):

(рис 8.5) Создания обработчика события

Нажав клавишу Enter, получаем шаблон на C# для метода myButton_Click – точь-в-точь, как в Windows или ASP.NET приложениях. Для перехода к созданному методу можно открыть файл Page.xaml.cs в окне Solution Explorer. Впрочем, среда предлагает более быстрый способ – щелкнуть правой кнопкой мыши на названии метода и выбрать пункт контекстного меню "Navigate to Event Handler" (рис. 8.6):

(рис 8.6) Переход к коду на C# с помощью меню "Navigate to Event Handler".

Файл Page.xaml.cs содержит класс Page, в котором размещается метод (рис. 8.7):

(рис 8.7) Содержимое файла Page.xaml.cs.

Разделение дизайна и кода – знакомый подход, который нам уже известен. Вернемся к коду XAML проекта – добавим анимацию:

<UserControl x:Class="SilverlightCSharp.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       Width="800" Height="600">
    <Canvas x:Name="LayoutRoot" Background="White">
<TextBlock
x:Name="myText"
  FontFamily="Verdana"
  FontSize="32"
  FontWeight="Bold"
  Foreground="Red">
  XAML-графика
  
              <TextBlock.Triggers>
     <EventTrigger RoutedEvent="Rectangle.Loaded"> 
      <BeginStoryboard> 
        <Storyboard>
              <DoubleAnimation RepeatBehavior="Forever"
                Storyboard.TargetName="myText"
                Storyboard.TargetProperty="FontSize" 
         To="50"  Duration="0:0:5" AutoReverse="True"  /> 
            </Storyboard>
      </BeginStoryboard> 
    </EventTrigger> 
     </TextBlock.Triggers>
</TextBlock>
        <Button Width="150" Height="50" Canvas.Left="50" 
Canvas.Top="250" Content="Изменить текст" 
x:Name="myButton" Click="myButton_Click" ></Button>

    </Canvas>
</UserControl>

Здесь мы использовали пример из предыдущей лекции, в который добавили для атрибута "x:Name" элемента TextBlock значение "myText". В обработчике события myButton_Click создадим трехкратное изменение текста:

private void myButton_Click(object sender, RoutedEventArgs e)
   {
       if (myText.Text == "XAML-графика")
       {
           myText.Text = "Привет, Silverligth C#!";
       }
       else if (myText.Text == "Привет, Silverligth C#!")
       {
           myText.Text = "Анимированный текст";
       }
       else
       {
           myText.Text = "XAML-графика";
       }
   }
 }
}

Мы обращаемся к элементу TextBlock по его имени "myText" так, словно это обычный Windows-элемент. Запускаем приложение – нажатие на кнопку меняет анимированный текст циклическим образом:

(рис 8.8) Готовое приложение

Заметим, что в качестве кнопки вовсе не обязательно использовать элемент Button. Любая фигура или даже текст могут служить элементом, который будет реагировать на события.

WPF и C#

Взаимодействие WPF-приложений и C# осуществляется еще более простым образом. Новое поколение Windows-приложений предоставляет еще большие возможности, сохраняя старые подходы и концепции. Панель инструментов Toolbox позволяет перетаскивать на форму элементы, а в окне Solution Explorer можно видеть связанные файлы XAML и C# (рис. 8.9):

(рис 8.9) WPF-приложение

В данном случае обработчик события создается двойным щелчком по кнопке. Напишем в нем знакомое выражение для вызова диалогового окна:

namespace WPFInteractive
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Привет, WPF!");
        }

       
    }
}

Запускаем проект, нажимаем на кнопку Button (рис. 8.10):

(рис 8.10) Запуск приложения

Среда сгенерировала для кнопки XAML-код, причем событие Click точно такое же, как и в случае Silverlight-приложений:

<Window x:Class="WPFInteractive.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">
    
    <Grid>
        <Button Margin="102,125,101,114" Name="button1" 
Click="button1_Click">Button</Button>
    </Grid>
</Window>

Поддержка видео

Потоковое видео или возможность смотреть онлайн-ролики – одно из самых перспективных направлений развития сети. На протяжении всей Пекинской Олимпиады 2008 года посетители официального сайта http://www.nbcolympics.com, созданного с использованием технологии Silverlight, могли видеть прямые трансляции соревнований (рис. 8.11):

(рис 8.11) Раздел видео на официальном сайте Пекинской Олимпиады (http://www.nbcolympics.com/video/index.html).

За все 17 дней соревнований сайты выдержал более 50 млн. уникальных пользователей. Это означает, что поддержка видео в Silverlight по своей производительности вполне может конкурировать с признанным лидером – технологией Flash.

Рассмотрим добавление видеоролика на Silverlight-сайт. Сразу после создания нового проекта щелкаем правой кнопкой на его заголовке, в появившемся контекстном меню выбираем пункт "Add Existing Item…". В появившемся диалоговом окне выбираем видео-файл, который нужно добавить. Из аудио и видео поддерживаются следующие форматы: *.mp3, *.asf, *.asx, *.wma, *.wmv. После добавления файл отображается в списке содержимого проекта. Перетаскиваем его в режиме дизайна на холст (рис. 8.12):

(рис 8.12) Размещение видео-файла и список содержимого проекта

Компилируем проект – ролик начинает сразу же воспроизводиться на веб-странице (рис. 8.13):

(рис 8.13) Воспроизведение видео на странице

Редактор Microsoft Expression Blend сформировал исключительно простой код для поддержки видео:

<Canvas
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="640" Height="480"
  Background="White"
  x:Name="Page">
  <MediaElement x:Name="quasol_rus_wmv" Width="424" 
Height="240" Canvas.Left="113" Canvas.Top="112" 
Source="quasol_rus.wmv" Stretch="Fill"/>
</Canvas>

Мы видим, что элемент MediaElement, отвечает за поддержку медиа-содержимого. Свойство Source может содержать и абсолютную ссылку на подходящий файл. Отметим, что для элемента MediaElement было сформировано значение "quasol_rus_wmv" для атрибута x:Name. Атрибут Stretch определяет расположение видеоролика относительно размеров элемента MediaElement. Дело в том, что каждое видео содержит свой собственный размер, например, 640х480 пикселей. Геометрические размеры MediaElement могут быть установлены произвольным образом. При значении "None" атрибута Stretch размеры видео не будут зависеть от размеров MediaElement. В нашем случае, при значении "Fill" видео заполняет всю область MediaElement. Если мы будем непропорционально изменять MediaElement, то видео будет искажаться. При значении "Uniform" видео будет подгоняться по ширине, сохраняя свои исходные пропорции. Наконец, при значении "UniformToFill" видео будет подгоняться до тех пор, пока его размеры меньше ра змеров элемента MediaElement. Если же они станут больше, то непопадающая часть отображаемого ролика будет обрезаться.

При попытке добавить неподдерживаемый формат видео, редактор отображает курсор соответствующим образом:

(рис 8.14) Добавление неподдерживаемого формата

Поддержка небольшого перечня формата файлов – для видео, по сути, только *.wma и *.wmv, могло бы существенным образом усложнить работу. В самом деле, необходимость использовать сторонние редакторы для кодирования видео означает необходимость затрат на их приобретение. Кроме того, большинство разработчиков вряд ли захотят осваивать, к примеру, Adobe Premier. Но пакет Microsoft Expression Studio специально для этих задач содержит утилиту Microsoft Expression Encoder (рис. 8.15):

(рис 8.15) Работа с видео в Microsoft Expression Encoder

Подобно другим видео-редакторам, Microsoft Expression Encoder содержит изрядное количество возможностей и настроек. Но нас интересует просто преобразование в формат, поддерживаемый Silverlight-проектами. Поэтому загружаем сразу все ролики, которые нужно перекодировать, выделям их и нажимаем кнопку "Encode". Время преобразования зависит от процессора, объема оперативной памят и исходного видео. К примеру, стандартный DVDRip, размером около 1,4 Гб, на компьютере с процессором Core 2 Duo 2.13 ГГц и 2 Гб оперативной памяти обрабатывается чуть меньше двух часов. Клипы и трейлеры к фильмам преобразуются за считанные минуты (рис. 8.16):

(рис 8.16) Кодировка роликов

Созданные файлы – уже в формате *.wmv, добавляем в проект и перетаскиваем их на поверхность холста. Самое интересное, что размеры медиа-элементов можно изменять точно также, как и обычных фигур (рис. 8.17):

(рис 8.17) Несколько роликов в одном проекте

Запускаем приложение – все добавленные видео-файлы запускаются одновременно (рис. 8.18):

(рис 8.18) Одновременное воспроизведение нескольких фильмов

Код, сформированный средой, содержит четыре элемента MediaElement – по одному на каждый видео-файл:

<Canvas
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="1024" Height="600"
  Background="White"
  x:Name="Page">
  <MediaElement x:Name="admiral_trl2_wmv" Width="447.852" 
Height="188.938" Canvas.Left="453.778" 
Canvas.Top="202.5" Source="admiral_trl2.wmv" Stretch="Fill"/>
  <MediaElement x:Name="maxpain_trlrb_wmv" Width="445.63" 
Height="188" Canvas.Left="456" Canvas.Top="10.5" 
Source="maxpain_trlrb.wmv" Stretch="Fill"/>
  <MediaElement x:Name="priklyucheniya_alyonushki_i_eryomy_wmv" 
Width="441.778" Height="331.334" Canvas.Left="12" 
Canvas.Top="262" Source="priklyucheniya-alyonushki-i-eryomy.wmv" Stretch="Fill"/>
  <MediaElement x:Name="quasol_rus_wmv" Width="440" 
Height="247.5" Canvas.Left="12" Canvas.Top="10.5" 
Source="quasol_rus.wmv" Stretch="Fill"/>
</Canvas>

Прямоугольные экраны, фиксированные размеры – это все уже давно известно. Воспользуемся действительно эффектными возможностями Silverlight. Применим трансформации к медиа-элементам:

<Canvas
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="1024" Height="600"
  Background="#FF05052C"
  x:Name="Page">
  <MediaElement x:Name="admiral_trl2_wmv" Width="447.852" 
  Height="188.938" Canvas.Left="447.778" 
Canvas.Top="223.5" Source="admiral_trl2.wmv" Stretch="Fill">
  
      <MediaElement.RenderTransform>  
    <TransformGroup>  
      <SkewTransform AngleX="15" />  
      <RotateTransform Angle="10"/>  
    </TransformGroup>  
    </MediaElement.RenderTransform>
  </MediaElement>

  
  <MediaElement x:Name="priklyucheniya_alyonushki_i_eryomy_wmv" 
Width="441.778" Height="331.334" 
  Canvas.Left="78" Canvas.Top="166" 
Source="priklyucheniya-alyonushki-i-eryomy.wmv" Stretch="Fill">
    <MediaElement.RenderTransform>  
    <TransformGroup>  
      <SkewTransform AngleX="15" />  
      <RotateTransform Angle="10"/>  
    </TransformGroup>  
    </MediaElement.RenderTransform>
  </MediaElement>
  
  
  <MediaElement x:Name="quasol_rus_wmv" Width="440" 
Height="247.5" Canvas.Left="12" 
  Canvas.Top="10.5" Source="quasol_rus.wmv" 
Stretch="Fill">
      <MediaElement.RenderTransform>  
    <TransformGroup>  
      <SkewTransform AngleX="15" />  
      <RotateTransform Angle="10"/>  
    </TransformGroup>  
    </MediaElement.RenderTransform>
  </MediaElement>
  
    <MediaElement x:Name="maxpain_trlrb_wmv" Width="445.63" 
Height="188" 
  Canvas.Left="390" Canvas.Top="22.5" 
Source="maxpain_trlrb.wmv" Stretch="Fill">
  <MediaElement.RenderTransform>  
    <TransformGroup>  
      <SkewTransform AngleX="15" />  
      <RotateTransform Angle="10"/>  
    </TransformGroup>  
    </MediaElement.RenderTransform>
  </MediaElement>
  
</Canvas>

Здесь мы исказили фигуры по горизонтали с одновременным поворотом. Код написан вручную, т.е. без использования визуальных инструментов Expression Blend для более ясного и лаконичного оформления. Запускаем приложение – видео, как ни в чем не бывало, продолжает воспроизводиться (рис. 8.19)

(рис 8.19) Воспроизведение видео с трансформированными медиа-элементами

Добавим еще и маску прозрачности, сформированную радиальным градиентом:

<Canvas
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="1024" Height="600"
  Background="#FF05052C"
  x:Name="Page">
  <MediaElement x:Name="admiral_trl2_wmv" Width="447.852" 
  Height="188.938" Canvas.Left="447.778" 
Canvas.Top="223.5" Source="admiral_trl2.wmv" Stretch="Fill">
  
      <MediaElement.RenderTransform>  
    <TransformGroup>  
      <SkewTransform AngleX="15" />  
      <RotateTransform Angle="10"/>  
    </TransformGroup>  
    </MediaElement.RenderTransform>
    
     <MediaElement.OpacityMask>
  
                <RadialGradientBrush >
              <GradientStop Color="Blue" Offset="0.8" />
               <GradientStop Color="Transparent" Offset="1" />  
            </RadialGradientBrush>
       
    </MediaElement.OpacityMask>    
    
  </MediaElement>

  
  <MediaElement x:Name="priklyucheniya_alyonushki_i_eryomy_wmv" 
Width="441.778" Height="331.334" 
  Canvas.Left="78" Canvas.Top="166" 
Source="priklyucheniya-alyonushki-i-eryomy.wmv" Stretch="Fill">
    <MediaElement.RenderTransform>  
    <TransformGroup>  
      <SkewTransform AngleX="15" />  
      <RotateTransform Angle="10"/>  
    </TransformGroup>  
    </MediaElement.RenderTransform>
    
         <MediaElement.OpacityMask>
  
                <RadialGradientBrush >
              <GradientStop Color="Blue" Offset="0.8" />
               <GradientStop Color="Transparent" Offset="1" />  
            </RadialGradientBrush>
       
    </MediaElement.OpacityMask>  
  </MediaElement>
  
  
  <MediaElement x:Name="quasol_rus_wmv" Width="440" 
Height="247.5" Canvas.Left="12" 
  Canvas.Top="10.5" Source="quasol_rus.wmv" Stretch="Fill">
      <MediaElement.RenderTransform>  
    <TransformGroup>  
      <SkewTransform AngleX="15" />  
      <RotateTransform Angle="10"/>  
    </TransformGroup>  
    </MediaElement.RenderTransform>
    
         <MediaElement.OpacityMask>
  
                <RadialGradientBrush >
              <GradientStop Color="Blue" Offset="0.8" />
               <GradientStop Color="Transparent" Offset="1" />  
            </RadialGradientBrush>
       
    </MediaElement.OpacityMask>  
  </MediaElement>
  
    <MediaElement x:Name="maxpain_trlrb_wmv" Width="445.63" 
Height="188" 
  Canvas.Left="390" Canvas.Top="22.5" Source="
maxpain_trlrb.wmv" Stretch="Fill">
  <MediaElement.RenderTransform>  
    <TransformGroup>  
      <SkewTransform AngleX="15" />  
      <RotateTransform Angle="10"/>  
    </TransformGroup>  
    </MediaElement.RenderTransform>
    
         <MediaElement.OpacityMask>
  
                <RadialGradientBrush >
              <GradientStop Color="Blue" Offset="0.8" />
               <GradientStop Color="Transparent" Offset="1" />  
            </RadialGradientBrush>
       
    </MediaElement.OpacityMask>  
  </MediaElement>
  
</Canvas>

Изменения, отображаемые в режиме дизайна, позволяет представить себе, как будет выглядеть видео (рис. 8.20):

(рис 8.20) Маски прозрачности и медиа-элементы в режиме дизайна

Запускаем проект – теперь наше видео выглядит весьма необычно (рис. 8.21):

(рис 8.21) Ролики с маской прозрачности в режиме воспроизведения

Конечно, на практике, для обычных хостингов видео-файлов, может быть столь экстравагантное оформление может быть и ни к чему. Но сами возможности Silverligt позволяют создавать легко и быстро оригинальное оформление для любого видео-содержимого.

Управление воспроизведением видеоролика

Первое, что хочется сделать при просмотре видеоролика на странице – "нащупать" знакомые кнопки управления воспроизведением – остановки, паузы, проигрывания.. Но по умолчанию их нет в Silverlight-проектах. Дополним эту функциональность при помощи простейшего кода на JavaScript. Создадим еще один проект, в который добавим всего один видеофайл. В качестве "кнопок" будем использовать обычные текстовые элементы TextBlock. Код XAML будет выглядеть так:

<Canvas
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="640" Height="480"
  Background="White"
  x:Name="Page">
  <MediaElement x:Name="priklyucheniya_alyonushki_i_eryomy_wmv" 
  Width="512" Height="384" Source="priklyucheniya-alyonushki-i-eryomy.wmv" 
  Stretch="Fill" Canvas.Left="68" Canvas.Top="26"
  AutoPlay="False"
  />
  
  <TextBlock x:Name="txtPlay" Width="72" Height="24" 
      Canvas.Left="86" 
      Canvas.Top="430" Text="Play" TextWrapping="Wrap"  
      MouseLeftButtonDown="DoPlay"/>
 
<TextBlock x:Name="txtStop" Width="80" Height="24" 
Canvas.Left="238" 
      Canvas.Top="430" Text="Stop" TextWrapping="Wrap" 
      MouseLeftButtonDown="DoStop"/>
    
    <TextBlock x:Name="txtPause" Width="80" Height="24" 
Canvas.Left="158" 
      Canvas.Top="430" Text="Pause" TextWrapping="Wrap" 
      MouseLeftButtonDown="DoPause"/>
</Canvas>

В описании MediaElement был добавлен атрибут AutoPlay="False". Это означает, что теперь ролик не будет начинать проигрываться сразу после загрузки. Для трех элементов TextBlock добавлен обработчик события MouseLeftButtonDown. Открываем файл Page.xaml.js (рис. 8.22):

(рис 8.22) Файл Page.xaml.js

Добавляем код трех функций, который будет выглядеть так:

function DoPlay(sender, args) {
    sender.findName("priklyucheniya_alyonushki_i_eryomy_wmv").play(); 
}
function DoPause(sender, args) {
    sender.findName("priklyucheniya_alyonushki_i_eryomy_wmv").pause();
}
function DoStop(sender, args) {
    sender.findName("priklyucheniya_alyonushki_i_eryomy_wmv").stop();
}

Впрочем, можно и немного в другой форме:

function DoPlay(sender, eventArgs)
{
   var theHost = document.getElementById("SilverlightControl");
   var theMedia = theHost.content.findName("priklyucheniya_alyonushki_i_eryomy_wmv");
   theMedia.Play();
}
function DoPause(sender, eventArgs)
{
   var theHost = document.getElementById("SilverlightControl");
   var theMedia = theHost.content.findName("priklyucheniya_alyonushki_i_eryomy_wmv");
   theMedia.Pause();
}
 
function DoStop(sender, eventArgs)
{
   var theHost = document.getElementById("SilverlightControl");
   var theMedia = theHost.content.findName("priklyucheniya_alyonushki_i_eryomy_wmv");
   theMedia.Stop();
}

В любом случае, мы обращаемся к элементу MediaElement по значению атрибута x:Name (здесь – "priklyucheniya_alyonushki_i_eryomy_wmv") и вызываем его встроенные методы Play, Pause, Stop. Запускаем проект – теперь мы можем управлять воспроизведением (рис. 8.23):

(рис 8.23) Ролик с возможностью управления воспроизведением

Медиа-элемент содержит и другие встроенные свойства и методы, позволяющие без труда добавить привычные возможности, например, такие как отображение отношения текущего времени воспроизведения к общему. Описание этих свойств можно найти в разделе "MediaElement" библиотеки MSDN: http://msdn.microsoft.com/en-us/library/bb980132(VS.95).aspx. Впрочем, набор примеров пакета Microsoft Expression Blend содержит готовый сайт, содержащий все основные элементы управления (рис. 8.24):

(рис 8.24) Видеоролик из набора примеров Microsoft Expression Blend

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

Deep Zoom Composer

Появление и широкое распространение цифровых фотоаппаратов сделало мир панорамных фотографий доступным практически для всех. Несмотря на то, что создание хороших панорамных изображений по-прежнему требует определенных навыков и мастерства, любой, даже начинающий фотограф может сделать серию перекрывающихся снимков и затем скомпоновать их, например, в программе PTGui (http://www.photo-sturm.ru/useful/article/PTGui/). Однако есть проекты в сети, которые не могут не восхищать, а создание их совершенно невозможно с помощью обычных фотоаппаратов. На сайте GERARDMAYNARD.COM (http://gerardmaynard.com/) приводится всего пять фотографий, среди которых есть и пейзажные (рис8.25):

(рис 8.25) Изображение "Долина смерти" ("Death Valley") на сайте GERARDMAYNARD.COM

Но какие это фотографии! Фотография "Death Valley" состоит из 112 157х 18376 пикселей (2,157 гигапикселей). Чтобы представить, насколько велико это изображение, вспомним, что стандартным разрешением 19-дюймового монитора является 1280*1024 пикселей. Чтобы отобразить эту фотографию, в качестве обоев на рабочих столах в масштабе 1:1, понадобится 1572 монитора.

Понятно, что отобразить эту фотографию всю целиком за приемлемое время невозможно даже на самом высокоскоростном канале связи. Поэтому на сайте отображается миниатюра изображения. Увеличивая масштаб и используя навигационную панель, можно перемещаться по всему полотну. Догрузка фрагментов изображения осуществляется постепенно, плавно прорисовывая все новые детали (рис. 8.26):

(рис 8.26) Просмотр выделенного фрагмента. На навигационной панели заметно, что данный участок очень мал по сравнению с общим полотном

Смотрим на долину издалека – поворачиваем колесико мыши и словно в прицеле снайперской винтовки получаем детальное приближение. На пределе увеличения видим отдельные цветы и стебли. Навигационная рамка при этом сжимается в точку (рис. 8.27):

(рис 8.27) Предел увеличения полотна

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

На сайте http://gigapxl.org тоже размещены примеры подобных фотографий. Статья о том, как создаются такие уникальный фотографии, размещена в журнале Компьютерра-онлайн, которая так и называется "Гигапиксель" (http://www.computerra.ru/hitech/38859/).

Какое это отношение имеет к XAML? Дело в том, что в рамках технологии Silverlight компания Microsoft разработала еще одно направление Deep Zoom (глубокое увеличение). С помощью специальной программы Deep Zoom Composer пользователи получили возможность подготавливать панорамные фотографии и размещать их в специальных фотоальбомах, делая результат доступным в Интернете. При этом не требуется никаких специальных навыков – ни XAML, ни программирования на C#. Но создаваемый проект будет основан на Silverlight. А это означает, что, все-таки обладая навыками работы с технологией, можно изменять создаваемые фотоальбомы или даже интегрировать их в рамках своих решений.

В качестве фотографий, которые легко доступны для получения, будем использовать фрагменты космических снимков из программы Virtual Earth 3D (рис. 8.28):

(рис 8.28) Программа Virtual Earth 3D (Beta).

Далее мы делаем серию перекрывающихся снимков и сохраняем их в отдельную папку. Количество ничем не ограничено – при наличии большого количества свободного времени допускается сделать аналог изображения, скажем, для "Гигапикселя". После завершения подготовки изображения, скачиваем и устанавливаем Deep Zoom Composer, а затем открываем в нем подготовленные рисунки. Перетащив их на рабочий холст выделяем все, щелкаем правой кнопкой мыши и в появившемся контекстном меню выбираем пункт "Create panoramic photo" (рис. 8.29):

(рис 8.29) Создание панорамного изображения из серии снимков

Спустя некоторое время, зависящее от числа фрагментов и мощности процессора, появляется готовое полотно в специальном диалоговом окне "Stitching Preview". Здесь изображение можно кадрировать (обрезать) для придания ему прямоугольной формы (рис. 8.30):

(рис 8.30) Кадрирование изображения

Я специально оставил полотно в виде кусочной структуры, для того чтобы подчеркнуть фрагментарный характер панорамы. На практике, конечно, готовые изображения должны быть прямоугольными. Для публикации изображений предлагается два способа. Первый, самый просто и подходящий для всех– отправка панорамы на специальный сайтhttp://photozoom.mslivelabs.com. Для аутентификации используется Windows Live ID, который можно получить на сайте http://www.microsoft.com/rus/liveid. Интерфейс программы позволяет заняться размещение изображения не покидая Deep Zoom Composer, т.е. не запуская браузер (рис. 8.31):

(рис 8.31) Аутентификация в Deep Zoom Composer с помощью Windows Live ID

После успешной аутентификации приступаем к созданию альбома. Вводим его название, указываемый формат загружаемого изображения (например, PNG) и нажимаем кнопку "Upload" (рис. 8.32):

(рис 8.32) Загрузка панорамной фотографии в созданный альбом

Спустя некоторое время мы получаем обычную гиперссылку на созданный фотоальбом. Для его просмотра не нужен Deep Zoom Composer, главное, чтобы на компьютере был установлен Silverlight. Инструменты масштабирования изображения создаются автоматически (рис. 8.33):

(рис 8.33) Готовое изображение в фотоальбоме

Изображение в фотоальбоме при просмотре загружается точно так же, как и на рассматриваемом в начале этого раздела сайте GERARDMAYNARD.COM. Сначала появляется миниатюра, затем, по мере увеличения масштаба и перемещения по полотну, догружаются нужные фрагменты.

Если же мы собираемся дорабатывать и изменять структуры создаваемого Silverlight-сайта, то сохраним вначале проект на жестком диске своего компьютера. Для этого следует перейти на вкладку "Silverlight Export" и указать директорию для сохранения (рис. 8.34):

(рис 8.34) Сохранения проекта для локальной работы

Самое замечательно, что перейдя в к сохраненному проекту, мы обнаружим решение (Solution) содержащее все необходимые файлы. Остается только открыть его в Visual Studio .NET 2008 и начать добавлять собственные функциональные возможности (рис. 8.35):

(рис 8.35) Проект панорманого фото в среде Visual Studio .NET 2008

В библиотеке MSDN, в статье "Deep Zoom": http://msdn.microsoft.com/en-us/library/cc645050(VS.95).aspx приводится хорошее описание этой технологии. А в статье "A DeepZoom primer (explained and coded)" http://blogs.msdn.com/jaimer/archive/2008/03/31/a-deepzoom-primer-explained-and-coded.aspx Джейма Родригеса (Jaime Rodriguez) – объяснение и код аналогичного примера.

Технология DeepZoom – это не только панорамные фотографии. Создаваемый проект предоставляет большие возможности по разработке дополнительных сервисов. Если для вашего города нет карты Яндекс, если вам хочется создать гео-сервис, то технология Silverlight вполне подходит в качестве платформы разработки.

Фотосинты

Хостинги изображений, онлайн-фотоальбомы, множество фотографий в новостных лентах – современного пользователя Сети трудно удивить картинками в сети. Но направление ), разрабатываемое корпорацией Microsoft – это трехмерные изображения, взятые словно из будущего, не оставят равнодушным никого.

Представьте себе, что вы бродите с фотоаппаратом возле египетских пирамид. Хочется запечатлеть множество снимков возле древнего Сфинкса, чтобы потом их показывать знакомым и друзьям. Однако может ли фото или даже видео передать всю ту трехмерную полноту ощущений, возникающих при реальном присутствии? Фотографии останутся плоскими и двумерными, видео выхватывает небольшой кусочек обзора (а длинный фильм вряд ли кто захочет смотреть), словом, изобразительные возможности остаются весьма ограниченными. Но можно поступить немного иначе. Для этого нужно немного времени и терпения, но результат превзойдет все ожидания. Итак, общий план действий примерно такой:

  • Читаем инструкцию, как делать снимки, которые планируется использовать в фотосинтах. Или смотрим обучающее видео.
  • Делаем множество фотографий выбранного объекта. С разных позиций, под разными углами. Чем больше снимков – тем лучше.
  • Идем на официальный сайт фотосинта http://photosynth.net/learn.aspx, выполняем указанные шаги. Для работы нам понадобится скачать плагин для браузера и специальную утилиту, после чего, проделав еще несколько шагов, получим готовую композицию.
  • В результате, созданный объект представляет собой совокупность всех фотографий, пространственные пересечения которых формируют общую трехмерную форму фигуры (рис. 8.36):

    (рис 8.36) Пример фотосинта Сфинкса

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

    Прежде чем приступать к созданию своих ландшафтов, полезно ознакомиться с лучшим галереями http://photosynth.net/explore.aspx Интересные примеры, например, фотосинты Екатеринбурга, объяснения и демонстрации расположены в блоге Константина Кичинского.

    Плагин для просмотра фотосинтов – это не Silverlight. Но это родственная технология может быть интегрирована в рамках одного сайта, сделанного с включением Silverlight, обеспечивая тем самым дополнительные мультимедийные возможности.

    Страницы:

    Silverlight и JavaScript

    Silverlight поддерживает базовый набор функций JavaScript, описание которого приводится в разделе "JavaScript API for Silverlight Reference" (http://msdn.microsoft.com/en-us/library/bb979679(VS.95).aspx). Можно ожидать, что последующие версии Silverlight будут включать в себя все больший набор возможностей JavaScript.

    Связывание произвольной JavaScript функции с определенным событием осуществляется так:

    MouseLeftButtonDown="myFunction"

    Здесь MouseLeftButtonDown - событие, возникающее при нажатии левой кнопки мыши, а myFunction – имя функции, которая должна запускаться при возникновении этого события. В XAML-коде эта связка задается в описании элемента:

    <Canvas
      xmlns="http://schemas.microsoft.com/client/2007"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="200" Height="100"
      Background="White"
      x:Name="Page">
      <Rectangle Width="100" Height="30" 
       Canvas.Left="50" Canvas.Top="40" 
        Fill="yellow" RadiusY="10" RadiusX="10" 
        Stroke="green" StrokeThickness="5" 
        MouseLeftButtonDown="myFunction"/>
    </Canvas>

    Названия событий является зарезервированными, более того, регистр также учитывается. Перечень событий приводится в разделе " Events Reference" (http://msdn.microsoft.com/en-us/library/bb980189(VS.95).aspx). Функция myFunction определяется в специальном файле "Page.xaml.js", который находится в папке проекта (рис. 8.1):

    (рис 8.1) Файл "Page.xaml.js".

    Внутри функции определяется функциональность, например появление простейшего диалогового окна:

    function myFunction () {
      alert ("Привет, Silverlight и JavaScript!");
    }

    В результате, при нажатии на прямоугольник, в браузере появляется диалоговое окно (рис. 8.2):

    (рис 8.2) Простейший пример взаимодействия Silverlight и JavaScript

    Использование JavaScript в Silverlight-проектах – отличный способ определить функциональность на стороне клиента. Это означает, что при выполнении различных действий пользователь не будет ждать перезагрузки страницы, так как выполнение JavaScript не требует обращения к серверу.

    В табл. 8.1приводится несколько других несложных примеров.

    Silverlight и JavaScript
    Код Вид в браузере
    8.1.1
    Page.xaml:
    <Canvas
    xmlns="http://schemas.microsoft.com/
    client/2007"
    xmlns:x="http://schemas.microsoft.com/
    winfx/2006/xaml"
    Width="200" Height="100"
    Background="White"
    x:Name="Page">
    
        
     <Rectangle Canvas.Left="5" 
    Canvas.Top="5" Width="190" 
    Height="90"
     Fill="Transparent"  
     Stroke="green" 
    StrokeThickness="2"/>
       
    <Rectangle x:Name="myRectangle" 
    Canvas.Left="20" 
    Canvas.Top="20" 
    Width="100" Height="50" 
     Fill="Orange" 
     MouseEnter="DoMouseEnter" 
    MouseLeave="DoMouseLeave"/>
      
    </Canvas>
    
    Page.xaml.js:
    
    function DoMouseEnter(sender, mouseEventArgs)
    {   
     sender.findName("myRectangle").
    Fill="Red";
    }
    function DoMouseLeave(sender, mouseEventArgs)
    {   
     sender.findName("myRectangle").
    Fill="Orange";
    }
    Описание
    При наведении курсора на прямоугольник он становится красным. При выходе курсора из области прямоугольника цвет становится прежним
    Код Вид в браузере
    8.1.2
    Page.xaml:
    <Canvas
    xmlns="http://schemas.microsoft.com/
    client/2007"
    xmlns:x="http://schemas.microsoft.com/
    winfx/2006/xaml"
    Width="310" Height="50"
    Background="White"
    x:Name="Page">
    
        
     <Rectangle Canvas.Left="5" 
    Canvas.Top="5" Width="300" 
    Height="40"
     Fill="Transparent"  
     Stroke="green"
     StrokeThickness="2"/>
       
    
    
     <TextBlock
     Canvas.Left="12" 
     Canvas.Top="12" 
     FontSize="14"
     Foreground="Orange"
     x:Name="myTextBlock" 
    MouseEnter="DoMouseEnter" 
    MouseLeftButtonDown="
    DoMouseLeftButtonDown" 
    MouseLeftButtonUp="
    DoMouseLeftButtonUp" 
    MouseLeave="DoMouseLeave"
    Text="Наведите мышь и щелкните!" />  
     
      
    </Canvas>
    
    Page.xaml.js:
    
    function DoMouseEnter(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    FontSize="20";
    }
    function DoMouseLeftButtonDown(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    Foreground="Red";
    }
    
    function DoMouseLeftButtonUp(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    Foreground="Orange";
    }
    function DoMouseLeave(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    FontSize="14";
    }
    Описание
    При наведении курсора текст увеличивается, при нажатии левой кнопки мыши он становится красным
    Код Вид в браузере
    8.1.3
    Page.xaml:
    <Canvas
    xmlns="http://schemas.microsoft.com/
    client/2007"
    xmlns:x="http://schemas.microsoft.com/
    winfx/2006/xaml"
    Width="300" Height="120"
    Background="White"
    x:Name="Page">    
     <Rectangle Canvas.Left="5"
     Canvas.Top="5" Width="290" 
    Height="110"
     Fill="Transparent"  
     Stroke="green" 
    StrokeThickness="2"/>
     
     <!-- Кнопка с подписью-->
      
    <Ellipse x:Name="myEllipse"
     Width="152" Height="41" 
    Canvas.Left="73"
     Canvas.Top="55" Fill="Pink"
     Stroke="Red" 
     StrokeThickness="5" 
    MouseEnter="DoMouseEnter" 
    MouseLeave="DoMouseLeave" />
     
      <TextBlock
     Canvas.Left="112" 
     Canvas.Top="68" 
     FontSize="11"
     Text="Изменить цвет"
    MouseEnter="DoMouseEnter" 
    MouseLeave="DoMouseLeave" />  
      
    <!--Изменяемая надпись-->
    
     <TextBlock
     Canvas.Left="100" 
     Canvas.Top="12" 
     FontSize="14"
     Foreground="Blue"
     x:Name="myTextBlock" 
     Text="XAML-графика" />   
     
      
    </Canvas>
    
    Page.xaml.js:
    
    function DoMouseEnter(sender, mouseEventArgs)
    {   
    sender.findName("myTextBlock").
    Foreground="Red";
    }
    function DoMouseLeave(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    Foreground="Blue";
    }
    Описание
    При наведении курсора мыши на кнопку цвет надписи меняется. Для получения этой функциональности обработка событий привязывается как к эллипсу, так и к расположенному на нем текстовому элементу
    Код Вид в браузере
    8.1.4
    Page.xaml:
    <Canvas
    xmlns="http://schemas.microsoft.com/
    client/2007"
    xmlns:x="http://schemas.microsoft.com/
    winfx/2006/xaml"
    Width="300" Height="120"
    Background="White"
    x:Name="Page">    
     <Rectangle Canvas.Left="5" 
    Canvas.Top="5" Width="290"
     Height="110"
     Fill="Transparent"  
    Stroke="green" 
    StrokeThickness="2"/>
    
     <!-- Кнопка с подписью-->
      
    <Ellipse x:Name="myEllipse" 
    Width="152" 
    Height="41" Canvas.Left="73"
     Canvas.Top="55" Fill="Pink" 
    Stroke="Red" 
    StrokeThickness="5" 
    MouseEnter="DoMouseEnter" 
    MouseLeave="DoMouseLeave" />
     
      <TextBlock
     Canvas.Left="112" 
     Canvas.Top="68" 
     FontSize="11"
     Text="Изменить цвет"
    MouseEnter="DoMouseEnter" 
    MouseLeave="DoMouseLeave" />  
      
    <!--Изменяемая надпись-->
    
     <TextBlock
     Canvas.Left="100" 
     Canvas.Top="12" 
     FontSize="14"
     Foreground="Blue"
     x:Name="myTextBlock" 
     Text="XAML-графика" />   
     
      
    </Canvas>
    
    Page.xaml.js:
    
    function DoMouseEnter(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    Foreground="Red";
     sender.findName("myTextBlock").
    FontSize="24";
    }
    function DoMouseLeave(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    Foreground="Blue";
     sender.findName("myTextBlock").
    FontSize="14";
    }
    Описание
    Изменение цвета и размера шрифта при наведении курсора
    Код Вид в браузере
    8.1.5
    Page.xaml:
    <Canvas
    xmlns="http://schemas.microsoft.com/
    client/2007"
    xmlns:x="http://schemas.microsoft.com/
    winfx/2006/xaml"
    Width="300" Height="120"
    Background="White"
    x:Name="Page">    
     <Rectangle Canvas.Left="5" 
    Canvas.Top="5" Width="290" 
    Height="110"
     Fill="Transparent"  
    Stroke="green" 
    StrokeThickness="2"/>
     
     <!-- Кнопка с подписью-->
      
    <Ellipse x:Name="myEllipse" 
    Width="152" Height="41" 
    Canvas.Left="73"
     Canvas.Top="55" Fill="Pink" 
    Stroke="Red" 
    StrokeThickness="5" 
    MouseLeftButtonDown=
    "DoMouseLeftButtonDown" 
    MouseLeftButtonUp=
    "DoMouseLeftButtonUp" />  
    
     
      <TextBlock
     Canvas.Left="112" 
     Canvas.Top="68" 
     FontSize="11"
     Text="Изменить цвет"
    MouseLeftButtonDown=
    "DoMouseLeftButtonDown" 
    MouseLeftButtonUp=
    "DoMouseLeftButtonUp" />  
      
    <!--Изменяемая надпись-->
    
     <TextBlock
     Canvas.Left="100" 
     Canvas.Top="12" 
     FontSize="14"
     Foreground="Blue"
     x:Name="myTextBlock" 
     Text="XAML-графика" />   
     
      
    </Canvas>
    
    Page.xaml.js:
    
    function DoMouseLeftButtonDown(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    Foreground="Red";
     sender.findName("myTextBlock").
    FontSize=24;
    }
    function DoMouseLeftButtonUp(sender, mouseEventArgs)
    {   
     sender.findName("myTextBlock").
    Foreground="Blue";
     sender.findName("myTextBlock").
    FontSize=14;
    }
    Описание
    Изменение цвета и размера шрифта при нажатии левой кнопки мыши
    Код Вид в браузере
    8.1.6
    Page.xaml:
    <Canvas
    xmlns="http://schemas.microsoft.com/
    client/2007"
    xmlns:x="http://schemas.microsoft.com/
    winfx/2006/xaml"
    Width="300" Height="120"
    Background="White"
    x:Name="Page"   
     GotFocus="onGotFocus"
      LostFocus="onLostFocus">
       
     <Rectangle Canvas.Left="5" 
    Canvas.Top="5" Width="290" 
    Height="110"
     Fill="Transparent"  
    Stroke="green" 
    StrokeThickness="2"/>
    
    
    <!-- Текущий адрес-->
      
    <Ellipse x:Name="myEllipse" 
    Width="152" Height="41"
     Canvas.Left="73"
     Canvas.Top="18"
      Fill="Pink" 
    Stroke="Red" 
    StrokeThickness="5" 
    MouseLeftButtonDown="currLocation" 
     />  
     
      <TextBlock
     Canvas.Left="135" 
     Canvas.Top="31" 
     FontSize="11"
     Text="ГДЕ Я?"
    MouseLeftButtonDown="currLocation" 
     />
     
     <!-- Новый адрес -->
     
      <Ellipse x:Name="myEllipse_Copy1"
     Width="152" Height="41" 
    Canvas.Left="73"
     Canvas.Top="66" Fill="Pink" 
    Stroke="Red" StrokeThickness="5" 
        MouseLeftButtonDown="newLocation" 
     />
      <TextBlock
        Canvas.Left="122" 
        Canvas.Top="79" 
        FontSize="11"
        Text="ИНТУИТ.РУ"
        MouseLeftButtonDown="newLocation" 
     />  
     
      
    </Canvas>
    
    Page.xaml.js:
    
    
    function currLocation()
    {
    alert(window.location)
    }
    function newLocation()
    {
    window.location="http://www.intuit.ru/"
    }
    Получение текущего адреса и переход на заданную ссылку. Эта функциональность получена с помощью свойства location объекта window самого JavaScript. Пример демонстрирует возможность создания гиперссылок
    Описание

    Использование JavaScript в XAML – достаточно увлекательное занятие. Для тех, кто знаком с JavaScript, здесь открывается новое поле деятельности. К сожалению, многие возможности еще не до конца реализованы в Silverlight (на момент написания курса), поэтому нельзя сказать, что старые подходы и концепции можно вообще без всяких изменений переносить в новые приложения.

    Silverlight и C#

    Применение языка C# в Silverlight-приложениях – самое ожидаемое действие для .NET программистов. Фактически, это одно из важнейших преимущество технологии – разрабатывать мультимедийные сайты теперь можно без необходимости менять технологии и среду разработки. Создадим простое приложение, в котором анимация XAML будет изменяться с помощью C#. Запускаем Visual Studio 2008, создаем новый проект "SilverlightCSahrp" типа "Silverlight Application" (рис. 8.3):

    (рис 8.3) Создание нового Silverlight-приложения в среде Visual Studio .NET 2008

    Появившейся XAML-код изменим следующим образом:

    <UserControl x:Class="SilverlightCSharp.Page"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           Width="800" Height="600">
        <Canvas x:Name="LayoutRoot" Background="White">
    
            </Canvas>
    </UserControl>

    Вместо элемента Grid будем использовать привычный Canvas. Добавим XAML-код кнопки, которая носит привычное название Button:

    <Button Width="150" Height="50" Canvas.Left="50" 
    Canvas.Top="250" Content="Изменить текст" 
    x:Name="myButton" ></Button>

    В принципе, добавлять элементы можно и перетаскиванием их из панели Toolbox. В любом случае, появляется кнопка, встроенное оформление которой вполне придает ей "трехмерный" вид. Для создания обработчика события Click достаточно ввести первые буквы – IntelliSense предложит вставить подходящее значение (рис. 8.4):

    (рис 8.4) Применение IntelliSense для написания события Click

    Сразу после вставки среда предлагает создать новый обработчик события (Event Handler) (рис. 8.5):

    (рис 8.5) Создания обработчика события

    Нажав клавишу Enter, получаем шаблон на C# для метода myButton_Click – точь-в-точь, как в Windows или ASP.NET приложениях. Для перехода к созданному методу можно открыть файл Page.xaml.cs в окне Solution Explorer. Впрочем, среда предлагает более быстрый способ – щелкнуть правой кнопкой мыши на названии метода и выбрать пункт контекстного меню "Navigate to Event Handler" (рис. 8.6):

    (рис 8.6) Переход к коду на C# с помощью меню "Navigate to Event Handler".

    Файл Page.xaml.cs содержит класс Page, в котором размещается метод (рис. 8.7):

    (рис 8.7) Содержимое файла Page.xaml.cs.

    Разделение дизайна и кода – знакомый подход, который нам уже известен. Вернемся к коду XAML проекта – добавим анимацию:

    <UserControl x:Class="SilverlightCSharp.Page"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           Width="800" Height="600">
        <Canvas x:Name="LayoutRoot" Background="White">
    <TextBlock
    x:Name="myText"
      FontFamily="Verdana"
      FontSize="32"
      FontWeight="Bold"
      Foreground="Red">
      XAML-графика
      
                  <TextBlock.Triggers>
         <EventTrigger RoutedEvent="Rectangle.Loaded"> 
          <BeginStoryboard> 
            <Storyboard>
                  <DoubleAnimation RepeatBehavior="Forever"
                    Storyboard.TargetName="myText"
                    Storyboard.TargetProperty="FontSize" 
             To="50"  Duration="0:0:5" AutoReverse="True"  /> 
                </Storyboard>
          </BeginStoryboard> 
        </EventTrigger> 
         </TextBlock.Triggers>
    </TextBlock>
            <Button Width="150" Height="50" Canvas.Left="50" 
    Canvas.Top="250" Content="Изменить текст" 
    x:Name="myButton" Click="myButton_Click" ></Button>
    
        </Canvas>
    </UserControl>

    Здесь мы использовали пример из предыдущей лекции, в который добавили для атрибута "x:Name" элемента TextBlock значение "myText". В обработчике события myButton_Click создадим трехкратное изменение текста:

    private void myButton_Click(object sender, RoutedEventArgs e)
       {
           if (myText.Text == "XAML-графика")
           {
               myText.Text = "Привет, Silverligth C#!";
           }
           else if (myText.Text == "Привет, Silverligth C#!")
           {
               myText.Text = "Анимированный текст";
           }
           else
           {
               myText.Text = "XAML-графика";
           }
       }
     }
    }

    Мы обращаемся к элементу TextBlock по его имени "myText" так, словно это обычный Windows-элемент. Запускаем приложение – нажатие на кнопку меняет анимированный текст циклическим образом:

    (рис 8.8) Готовое приложение

    Заметим, что в качестве кнопки вовсе не обязательно использовать элемент Button. Любая фигура или даже текст могут служить элементом, который будет реагировать на события.

    WPF и C#

    Взаимодействие WPF-приложений и C# осуществляется еще более простым образом. Новое поколение Windows-приложений предоставляет еще большие возможности, сохраняя старые подходы и концепции. Панель инструментов Toolbox позволяет перетаскивать на форму элементы, а в окне Solution Explorer можно видеть связанные файлы XAML и C# (рис. 8.9):

    (рис 8.9) WPF-приложение

    В данном случае обработчик события создается двойным щелчком по кнопке. Напишем в нем знакомое выражение для вызова диалогового окна:

    namespace WPFInteractive
    {
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                MessageBox.Show("Привет, WPF!");
            }
    
           
        }
    }

    Запускаем проект, нажимаем на кнопку Button (рис. 8.10):

    (рис 8.10) Запуск приложения

    Среда сгенерировала для кнопки XAML-код, причем событие Click точно такое же, как и в случае Silverlight-приложений:

    <Window x:Class="WPFInteractive.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">
        
        <Grid>
            <Button Margin="102,125,101,114" Name="button1" 
    Click="button1_Click">Button</Button>
        </Grid>
    </Window>

    Поддержка видео

    Потоковое видео или возможность смотреть онлайн-ролики – одно из самых перспективных направлений развития сети. На протяжении всей Пекинской Олимпиады 2008 года посетители официального сайта http://www.nbcolympics.com, созданного с использованием технологии Silverlight, могли видеть прямые трансляции соревнований (рис. 8.11):

    (рис 8.11) Раздел видео на официальном сайте Пекинской Олимпиады (http://www.nbcolympics.com/video/index.html).

    За все 17 дней соревнований сайты выдержал более 50 млн. уникальных пользователей. Это означает, что поддержка видео в Silverlight по своей производительности вполне может конкурировать с признанным лидером – технологией Flash.

    Рассмотрим добавление видеоролика на Silverlight-сайт. Сразу после создания нового проекта щелкаем правой кнопкой на его заголовке, в появившемся контекстном меню выбираем пункт "Add Existing Item…". В появившемся диалоговом окне выбираем видео-файл, который нужно добавить. Из аудио и видео поддерживаются следующие форматы: *.mp3, *.asf, *.asx, *.wma, *.wmv. После добавления файл отображается в списке содержимого проекта. Перетаскиваем его в режиме дизайна на холст (рис. 8.12):

    (рис 8.12) Размещение видео-файла и список содержимого проекта

    Компилируем проект – ролик начинает сразу же воспроизводиться на веб-странице (рис. 8.13):

    (рис 8.13) Воспроизведение видео на странице

    Редактор Microsoft Expression Blend сформировал исключительно простой код для поддержки видео:

    <Canvas
      xmlns="http://schemas.microsoft.com/client/2007"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="640" Height="480"
      Background="White"
      x:Name="Page">
      <MediaElement x:Name="quasol_rus_wmv" Width="424" 
    Height="240" Canvas.Left="113" Canvas.Top="112" 
    Source="quasol_rus.wmv" Stretch="Fill"/>
    </Canvas>

    Мы видим, что элемент MediaElement, отвечает за поддержку медиа-содержимого. Свойство Source может содержать и абсолютную ссылку на подходящий файл. Отметим, что для элемента MediaElement было сформировано значение "quasol_rus_wmv" для атрибута x:Name. Атрибут Stretch определяет расположение видеоролика относительно размеров элемента MediaElement. Дело в том, что каждое видео содержит свой собственный размер, например, 640х480 пикселей. Геометрические размеры MediaElement могут быть установлены произвольным образом. При значении "None" атрибута Stretch размеры видео не будут зависеть от размеров MediaElement. В нашем случае, при значении "Fill" видео заполняет всю область MediaElement. Если мы будем непропорционально изменять MediaElement, то видео будет искажаться. При значении "Uniform" видео будет подгоняться по ширине, сохраняя свои исходные пропорции. Наконец, при значении "UniformToFill" видео будет подгоняться до тех пор, пока его размеры меньше ра змеров элемента MediaElement. Если же они станут больше, то непопадающая часть отображаемого ролика будет обрезаться.

    При попытке добавить неподдерживаемый формат видео, редактор отображает курсор соответствующим образом:

    (рис 8.14) Добавление неподдерживаемого формата

    Поддержка небольшого перечня формата файлов – для видео, по сути, только *.wma и *.wmv, могло бы существенным образом усложнить работу. В самом деле, необходимость использовать сторонние редакторы для кодирования видео означает необходимость затрат на их приобретение. Кроме того, большинство разработчиков вряд ли захотят осваивать, к примеру, Adobe Premier. Но пакет Microsoft Expression Studio специально для этих задач содержит утилиту Microsoft Expression Encoder (рис. 8.15):

    (рис 8.15) Работа с видео в Microsoft Expression Encoder

    Подобно другим видео-редакторам, Microsoft Expression Encoder содержит изрядное количество возможностей и настроек. Но нас интересует просто преобразование в формат, поддерживаемый Silverlight-проектами. Поэтому загружаем сразу все ролики, которые нужно перекодировать, выделям их и нажимаем кнопку "Encode". Время преобразования зависит от процессора, объема оперативной памят и исходного видео. К примеру, стандартный DVDRip, размером около 1,4 Гб, на компьютере с процессором Core 2 Duo 2.13 ГГц и 2 Гб оперативной памяти обрабатывается чуть меньше двух часов. Клипы и трейлеры к фильмам преобразуются за считанные минуты (рис. 8.16):

    (рис 8.16) Кодировка роликов

    Созданные файлы – уже в формате *.wmv, добавляем в проект и перетаскиваем их на поверхность холста. Самое интересное, что размеры медиа-элементов можно изменять точно также, как и обычных фигур (рис. 8.17):

    (рис 8.17) Несколько роликов в одном проекте

    Запускаем приложение – все добавленные видео-файлы запускаются одновременно (рис. 8.18):

    (рис 8.18) Одновременное воспроизведение нескольких фильмов

    Код, сформированный средой, содержит четыре элемента MediaElement – по одному на каждый видео-файл:

    <Canvas
      xmlns="http://schemas.microsoft.com/client/2007"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="1024" Height="600"
      Background="White"
      x:Name="Page">
      <MediaElement x:Name="admiral_trl2_wmv" Width="447.852" 
    Height="188.938" Canvas.Left="453.778" 
    Canvas.Top="202.5" Source="admiral_trl2.wmv" Stretch="Fill"/>
      <MediaElement x:Name="maxpain_trlrb_wmv" Width="445.63" 
    Height="188" Canvas.Left="456" Canvas.Top="10.5" 
    Source="maxpain_trlrb.wmv" Stretch="Fill"/>
      <MediaElement x:Name="priklyucheniya_alyonushki_i_eryomy_wmv" 
    Width="441.778" Height="331.334" Canvas.Left="12" 
    Canvas.Top="262" Source="priklyucheniya-alyonushki-i-eryomy.wmv" Stretch="Fill"/>
      <MediaElement x:Name="quasol_rus_wmv" Width="440" 
    Height="247.5" Canvas.Left="12" Canvas.Top="10.5" 
    Source="quasol_rus.wmv" Stretch="Fill"/>
    </Canvas>

    Прямоугольные экраны, фиксированные размеры – это все уже давно известно. Воспользуемся действительно эффектными возможностями Silverlight. Применим трансформации к медиа-элементам:

    <Canvas
      xmlns="http://schemas.microsoft.com/client/2007"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="1024" Height="600"
      Background="#FF05052C"
      x:Name="Page">
      <MediaElement x:Name="admiral_trl2_wmv" Width="447.852" 
      Height="188.938" Canvas.Left="447.778" 
    Canvas.Top="223.5" Source="admiral_trl2.wmv" Stretch="Fill">
      
          <MediaElement.RenderTransform>  
        <TransformGroup>  
          <SkewTransform AngleX="15" />  
          <RotateTransform Angle="10"/>  
        </TransformGroup>  
        </MediaElement.RenderTransform>
      </MediaElement>
    
      
      <MediaElement x:Name="priklyucheniya_alyonushki_i_eryomy_wmv" 
    Width="441.778" Height="331.334" 
      Canvas.Left="78" Canvas.Top="166" 
    Source="priklyucheniya-alyonushki-i-eryomy.wmv" Stretch="Fill">
        <MediaElement.RenderTransform>  
        <TransformGroup>  
          <SkewTransform AngleX="15" />  
          <RotateTransform Angle="10"/>  
        </TransformGroup>  
        </MediaElement.RenderTransform>
      </MediaElement>
      
      
      <MediaElement x:Name="quasol_rus_wmv" Width="440" 
    Height="247.5" Canvas.Left="12" 
      Canvas.Top="10.5" Source="quasol_rus.wmv" 
    Stretch="Fill">
          <MediaElement.RenderTransform>  
        <TransformGroup>  
          <SkewTransform AngleX="15" />  
          <RotateTransform Angle="10"/>  
        </TransformGroup>  
        </MediaElement.RenderTransform>
      </MediaElement>
      
        <MediaElement x:Name="maxpain_trlrb_wmv" Width="445.63" 
    Height="188" 
      Canvas.Left="390" Canvas.Top="22.5" 
    Source="maxpain_trlrb.wmv" Stretch="Fill">
      <MediaElement.RenderTransform>  
        <TransformGroup>  
          <SkewTransform AngleX="15" />  
          <RotateTransform Angle="10"/>  
        </TransformGroup>  
        </MediaElement.RenderTransform>
      </MediaElement>
      
    </Canvas>

    Здесь мы исказили фигуры по горизонтали с одновременным поворотом. Код написан вручную, т.е. без использования визуальных инструментов Expression Blend для более ясного и лаконичного оформления. Запускаем приложение – видео, как ни в чем не бывало, продолжает воспроизводиться (рис. 8.19)

    (рис 8.19) Воспроизведение видео с трансформированными медиа-элементами

    Добавим еще и маску прозрачности, сформированную радиальным градиентом:

    <Canvas
      xmlns="http://schemas.microsoft.com/client/2007"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="1024" Height="600"
      Background="#FF05052C"
      x:Name="Page">
      <MediaElement x:Name="admiral_trl2_wmv" Width="447.852" 
      Height="188.938" Canvas.Left="447.778" 
    Canvas.Top="223.5" Source="admiral_trl2.wmv" Stretch="Fill">
      
          <MediaElement.RenderTransform>  
        <TransformGroup>  
          <SkewTransform AngleX="15" />  
          <RotateTransform Angle="10"/>  
        </TransformGroup>  
        </MediaElement.RenderTransform>
        
         <MediaElement.OpacityMask>
      
                    <RadialGradientBrush >
                  <GradientStop Color="Blue" Offset="0.8" />
                   <GradientStop Color="Transparent" Offset="1" />  
                </RadialGradientBrush>
           
        </MediaElement.OpacityMask>    
        
      </MediaElement>
    
      
      <MediaElement x:Name="priklyucheniya_alyonushki_i_eryomy_wmv" 
    Width="441.778" Height="331.334" 
      Canvas.Left="78" Canvas.Top="166" 
    Source="priklyucheniya-alyonushki-i-eryomy.wmv" Stretch="Fill">
        <MediaElement.RenderTransform>  
        <TransformGroup>  
          <SkewTransform AngleX="15" />  
          <RotateTransform Angle="10"/>  
        </TransformGroup>  
        </MediaElement.RenderTransform>
        
             <MediaElement.OpacityMask>
      
                    <RadialGradientBrush >
                  <GradientStop Color="Blue" Offset="0.8" />
                   <GradientStop Color="Transparent" Offset="1" />  
                </RadialGradientBrush>
           
        </MediaElement.OpacityMask>  
      </MediaElement>
      
      
      <MediaElement x:Name="quasol_rus_wmv" Width="440" 
    Height="247.5" Canvas.Left="12" 
      Canvas.Top="10.5" Source="quasol_rus.wmv" Stretch="Fill">
          <MediaElement.RenderTransform>  
        <TransformGroup>  
          <SkewTransform AngleX="15" />  
          <RotateTransform Angle="10"/>  
        </TransformGroup>  
        </MediaElement.RenderTransform>
        
             <MediaElement.OpacityMask>
      
                    <RadialGradientBrush >
                  <GradientStop Color="Blue" Offset="0.8" />
                   <GradientStop Color="Transparent" Offset="1" />  
                </RadialGradientBrush>
           
        </MediaElement.OpacityMask>  
      </MediaElement>
      
        <MediaElement x:Name="maxpain_trlrb_wmv" Width="445.63" 
    Height="188" 
      Canvas.Left="390" Canvas.Top="22.5" Source="
    maxpain_trlrb.wmv" Stretch="Fill">
      <MediaElement.RenderTransform>  
        <TransformGroup>  
          <SkewTransform AngleX="15" />  
          <RotateTransform Angle="10"/>  
        </TransformGroup>  
        </MediaElement.RenderTransform>
        
             <MediaElement.OpacityMask>
      
                    <RadialGradientBrush >
                  <GradientStop Color="Blue" Offset="0.8" />
                   <GradientStop Color="Transparent" Offset="1" />  
                </RadialGradientBrush>
           
        </MediaElement.OpacityMask>  
      </MediaElement>
      
    </Canvas>

    Изменения, отображаемые в режиме дизайна, позволяет представить себе, как будет выглядеть видео (рис. 8.20):

    (рис 8.20) Маски прозрачности и медиа-элементы в режиме дизайна

    Запускаем проект – теперь наше видео выглядит весьма необычно (рис. 8.21):

    (рис 8.21) Ролики с маской прозрачности в режиме воспроизведения

    Конечно, на практике, для обычных хостингов видео-файлов, может быть столь экстравагантное оформление может быть и ни к чему. Но сами возможности Silverligt позволяют создавать легко и быстро оригинальное оформление для любого видео-содержимого.

    Управление воспроизведением видеоролика

    Первое, что хочется сделать при просмотре видеоролика на странице – "нащупать" знакомые кнопки управления воспроизведением – остановки, паузы, проигрывания.. Но по умолчанию их нет в Silverlight-проектах. Дополним эту функциональность при помощи простейшего кода на JavaScript. Создадим еще один проект, в который добавим всего один видеофайл. В качестве "кнопок" будем использовать обычные текстовые элементы TextBlock. Код XAML будет выглядеть так:

    <Canvas
      xmlns="http://schemas.microsoft.com/client/2007"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="640" Height="480"
      Background="White"
      x:Name="Page">
      <MediaElement x:Name="priklyucheniya_alyonushki_i_eryomy_wmv" 
      Width="512" Height="384" Source="priklyucheniya-alyonushki-i-eryomy.wmv" 
      Stretch="Fill" Canvas.Left="68" Canvas.Top="26"
      AutoPlay="False"
      />
      
      <TextBlock x:Name="txtPlay" Width="72" Height="24" 
          Canvas.Left="86" 
          Canvas.Top="430" Text="Play" TextWrapping="Wrap"  
          MouseLeftButtonDown="DoPlay"/>
     
    <TextBlock x:Name="txtStop" Width="80" Height="24" 
    Canvas.Left="238" 
          Canvas.Top="430" Text="Stop" TextWrapping="Wrap" 
          MouseLeftButtonDown="DoStop"/>
        
        <TextBlock x:Name="txtPause" Width="80" Height="24" 
    Canvas.Left="158" 
          Canvas.Top="430" Text="Pause" TextWrapping="Wrap" 
          MouseLeftButtonDown="DoPause"/>
    </Canvas>

    В описании MediaElement был добавлен атрибут AutoPlay="False". Это означает, что теперь ролик не будет начинать проигрываться сразу после загрузки. Для трех элементов TextBlock добавлен обработчик события MouseLeftButtonDown. Открываем файл Page.xaml.js (рис. 8.22):

    (рис 8.22) Файл Page.xaml.js

    Добавляем код трех функций, который будет выглядеть так:

    function DoPlay(sender, args) {
        sender.findName("priklyucheniya_alyonushki_i_eryomy_wmv").play(); 
    }
    function DoPause(sender, args) {
        sender.findName("priklyucheniya_alyonushki_i_eryomy_wmv").pause();
    }
    function DoStop(sender, args) {
        sender.findName("priklyucheniya_alyonushki_i_eryomy_wmv").stop();
    }

    Впрочем, можно и немного в другой форме:

    function DoPlay(sender, eventArgs)
    {
       var theHost = document.getElementById("SilverlightControl");
       var theMedia = theHost.content.findName("priklyucheniya_alyonushki_i_eryomy_wmv");
       theMedia.Play();
    }
    function DoPause(sender, eventArgs)
    {
       var theHost = document.getElementById("SilverlightControl");
       var theMedia = theHost.content.findName("priklyucheniya_alyonushki_i_eryomy_wmv");
       theMedia.Pause();
    }
     
    function DoStop(sender, eventArgs)
    {
       var theHost = document.getElementById("SilverlightControl");
       var theMedia = theHost.content.findName("priklyucheniya_alyonushki_i_eryomy_wmv");
       theMedia.Stop();
    }

    В любом случае, мы обращаемся к элементу MediaElement по значению атрибута x:Name (здесь – "priklyucheniya_alyonushki_i_eryomy_wmv") и вызываем его встроенные методы Play, Pause, Stop. Запускаем проект – теперь мы можем управлять воспроизведением (рис. 8.23):

    (рис 8.23) Ролик с возможностью управления воспроизведением

    Медиа-элемент содержит и другие встроенные свойства и методы, позволяющие без труда добавить привычные возможности, например, такие как отображение отношения текущего времени воспроизведения к общему. Описание этих свойств можно найти в разделе "MediaElement" библиотеки MSDN: http://msdn.microsoft.com/en-us/library/bb980132(VS.95).aspx. Впрочем, набор примеров пакета Microsoft Expression Blend содержит готовый сайт, содержащий все основные элементы управления (рис. 8.24):

    (рис 8.24) Видеоролик из набора примеров Microsoft Expression Blend

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

    Deep Zoom Composer

    Появление и широкое распространение цифровых фотоаппаратов сделало мир панорамных фотографий доступным практически для всех. Несмотря на то, что создание хороших панорамных изображений по-прежнему требует определенных навыков и мастерства, любой, даже начинающий фотограф может сделать серию перекрывающихся снимков и затем скомпоновать их, например, в программе PTGui (http://www.photo-sturm.ru/useful/article/PTGui/). Однако есть проекты в сети, которые не могут не восхищать, а создание их совершенно невозможно с помощью обычных фотоаппаратов. На сайте GERARDMAYNARD.COM (http://gerardmaynard.com/) приводится всего пять фотографий, среди которых есть и пейзажные (рис8.25):

    (рис 8.25) Изображение "Долина смерти" ("Death Valley") на сайте GERARDMAYNARD.COM

    Но какие это фотографии! Фотография "Death Valley" состоит из 112 157х 18376 пикселей (2,157 гигапикселей). Чтобы представить, насколько велико это изображение, вспомним, что стандартным разрешением 19-дюймового монитора является 1280*1024 пикселей. Чтобы отобразить эту фотографию, в качестве обоев на рабочих столах в масштабе 1:1, понадобится 1572 монитора.

    Понятно, что отобразить эту фотографию всю целиком за приемлемое время невозможно даже на самом высокоскоростном канале связи. Поэтому на сайте отображается миниатюра изображения. Увеличивая масштаб и используя навигационную панель, можно перемещаться по всему полотну. Догрузка фрагментов изображения осуществляется постепенно, плавно прорисовывая все новые детали (рис. 8.26):

    (рис 8.26) Просмотр выделенного фрагмента. На навигационной панели заметно, что данный участок очень мал по сравнению с общим полотном

    Смотрим на долину издалека – поворачиваем колесико мыши и словно в прицеле снайперской винтовки получаем детальное приближение. На пределе увеличения видим отдельные цветы и стебли. Навигационная рамка при этом сжимается в точку (рис. 8.27):

    (рис 8.27) Предел увеличения полотна

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

    На сайте http://gigapxl.org тоже размещены примеры подобных фотографий. Статья о том, как создаются такие уникальный фотографии, размещена в журнале Компьютерра-онлайн, которая так и называется "Гигапиксель" (http://www.computerra.ru/hitech/38859/).

    Какое это отношение имеет к XAML? Дело в том, что в рамках технологии Silverlight компания Microsoft разработала еще одно направление Deep Zoom (глубокое увеличение). С помощью специальной программы Deep Zoom Composer пользователи получили возможность подготавливать панорамные фотографии и размещать их в специальных фотоальбомах, делая результат доступным в Интернете. При этом не требуется никаких специальных навыков – ни XAML, ни программирования на C#. Но создаваемый проект будет основан на Silverlight. А это означает, что, все-таки обладая навыками работы с технологией, можно изменять создаваемые фотоальбомы или даже интегрировать их в рамках своих решений.

    В качестве фотографий, которые легко доступны для получения, будем использовать фрагменты космических снимков из программы Virtual Earth 3D (рис. 8.28):

    (рис 8.28) Программа Virtual Earth 3D (Beta).

    Далее мы делаем серию перекрывающихся снимков и сохраняем их в отдельную папку. Количество ничем не ограничено – при наличии большого количества свободного времени допускается сделать аналог изображения, скажем, для "Гигапикселя". После завершения подготовки изображения, скачиваем и устанавливаем Deep Zoom Composer, а затем открываем в нем подготовленные рисунки. Перетащив их на рабочий холст выделяем все, щелкаем правой кнопкой мыши и в появившемся контекстном меню выбираем пункт "Create panoramic photo" (рис. 8.29):

    (рис 8.29) Создание панорамного изображения из серии снимков

    Спустя некоторое время, зависящее от числа фрагментов и мощности процессора, появляется готовое полотно в специальном диалоговом окне "Stitching Preview". Здесь изображение можно кадрировать (обрезать) для придания ему прямоугольной формы (рис. 8.30):

    (рис 8.30) Кадрирование изображения

    Я специально оставил полотно в виде кусочной структуры, для того чтобы подчеркнуть фрагментарный характер панорамы. На практике, конечно, готовые изображения должны быть прямоугольными. Для публикации изображений предлагается два способа. Первый, самый просто и подходящий для всех– отправка панорамы на специальный сайтhttp://photozoom.mslivelabs.com. Для аутентификации используется Windows Live ID, который можно получить на сайте http://www.microsoft.com/rus/liveid. Интерфейс программы позволяет заняться размещение изображения не покидая Deep Zoom Composer, т.е. не запуская браузер (рис. 8.31):

    (рис 8.31) Аутентификация в Deep Zoom Composer с помощью Windows Live ID

    После успешной аутентификации приступаем к созданию альбома. Вводим его название, указываемый формат загружаемого изображения (например, PNG) и нажимаем кнопку "Upload" (рис. 8.32):

    (рис 8.32) Загрузка панорамной фотографии в созданный альбом

    Спустя некоторое время мы получаем обычную гиперссылку на созданный фотоальбом. Для его просмотра не нужен Deep Zoom Composer, главное, чтобы на компьютере был установлен Silverlight. Инструменты масштабирования изображения создаются автоматически (рис. 8.33):

    (рис 8.33) Готовое изображение в фотоальбоме

    Изображение в фотоальбоме при просмотре загружается точно так же, как и на рассматриваемом в начале этого раздела сайте GERARDMAYNARD.COM. Сначала появляется миниатюра, затем, по мере увеличения масштаба и перемещения по полотну, догружаются нужные фрагменты.

    Если же мы собираемся дорабатывать и изменять структуры создаваемого Silverlight-сайта, то сохраним вначале проект на жестком диске своего компьютера. Для этого следует перейти на вкладку "Silverlight Export" и указать директорию для сохранения (рис. 8.34):

    (рис 8.34) Сохранения проекта для локальной работы

    Самое замечательно, что перейдя в к сохраненному проекту, мы обнаружим решение (Solution) содержащее все необходимые файлы. Остается только открыть его в Visual Studio .NET 2008 и начать добавлять собственные функциональные возможности (рис. 8.35):

    (рис 8.35) Проект панорманого фото в среде Visual Studio .NET 2008

    В библиотеке MSDN, в статье "Deep Zoom": http://msdn.microsoft.com/en-us/library/cc645050(VS.95).aspx приводится хорошее описание этой технологии. А в статье "A DeepZoom primer (explained and coded)" http://blogs.msdn.com/jaimer/archive/2008/03/31/a-deepzoom-primer-explained-and-coded.aspx Джейма Родригеса (Jaime Rodriguez) – объяснение и код аналогичного примера.

    Технология DeepZoom – это не только панорамные фотографии. Создаваемый проект предоставляет большие возможности по разработке дополнительных сервисов. Если для вашего города нет карты Яндекс, если вам хочется создать гео-сервис, то технология Silverlight вполне подходит в качестве платформы разработки.

    Фотосинты

    Хостинги изображений, онлайн-фотоальбомы, множество фотографий в новостных лентах – современного пользователя Сети трудно удивить картинками в сети. Но направление ), разрабатываемое корпорацией Microsoft – это трехмерные изображения, взятые словно из будущего, не оставят равнодушным никого.

    Представьте себе, что вы бродите с фотоаппаратом возле египетских пирамид. Хочется запечатлеть множество снимков возле древнего Сфинкса, чтобы потом их показывать знакомым и друзьям. Однако может ли фото или даже видео передать всю ту трехмерную полноту ощущений, возникающих при реальном присутствии? Фотографии останутся плоскими и двумерными, видео выхватывает небольшой кусочек обзора (а длинный фильм вряд ли кто захочет смотреть), словом, изобразительные возможности остаются весьма ограниченными. Но можно поступить немного иначе. Для этого нужно немного времени и терпения, но результат превзойдет все ожидания. Итак, общий план действий примерно такой:

  • Читаем инструкцию, как делать снимки, которые планируется использовать в фотосинтах. Или смотрим обучающее видео.
  • Делаем множество фотографий выбранного объекта. С разных позиций, под разными углами. Чем больше снимков – тем лучше.
  • Идем на официальный сайт фотосинта http://photosynth.net/learn.aspx, выполняем указанные шаги. Для работы нам понадобится скачать плагин для браузера и специальную утилиту, после чего, проделав еще несколько шагов, получим готовую композицию.
  • В результате, созданный объект представляет собой совокупность всех фотографий, пространственные пересечения которых формируют общую трехмерную форму фигуры (рис. 8.36):

    (рис 8.36) Пример фотосинта Сфинкса

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

    Прежде чем приступать к созданию своих ландшафтов, полезно ознакомиться с лучшим галереями http://photosynth.net/explore.aspx Интересные примеры, например, фотосинты Екатеринбурга, объяснения и демонстрации расположены в блоге Константина Кичинского.

    Плагин для просмотра фотосинтов – это не Silverlight. Но это родственная технология может быть интегрирована в рамках одного сайта, сделанного с включением Silverlight, обеспечивая тем самым дополнительные мультимедийные возможности.

    Вернуться к учебному плану