Опубликован: 24.03.2009 | Доступ: свободный | Студентов: 2283 / 115 | Оценка: 4.24 / 3.93 | Длительность: 17:47:00
Лекция 11:

Мультимедиа, рукописный ввод и Deep Zoom

Базовые элементы управления воспроизведением

Основными методами управления видео являются Play, Stop и Pause. Если свойству AutoPlay элемента управления MediaElement задано значение false, для начала воспроизведения видео необходимо применить Play. Даже если AutoPlay задано значение true, и воспроизведение начинается автоматически, с помощью этих методов его можно остановить или приостановить. Далее представлен пример XAML, в котором имеется элемент мультимедиа и три простых элемента управления воспроизведением, реализованных как элементы TextBlock:

<MediaElement x:Name="vid" Source="balls.wmv" Height="200" 
             Width = "200" Stretch="Fill" /> 
<Canvas Canvas.Top="160">
  <Rectangle Fill= "Black" Width = "200" Height="24" Opacity="0.7"/>
  <TextBlock Foreground= "White" Canvas.Left="20">Play</TextBlock>
  <TextBlock Foreground="White" Canvas. Left="80">Stop</TextBlock>
  <TextBlock Foreground="White" Canvas. Left=" 140" >Pause</TextBlock> 
</Canvas>

На рис. 11.10 показано, как эти элементы управления будут выглядеть на видеоизображении.

 Добавление элементов управления в видеоизображение

Рис. 11.10. Добавление элементов управления в видеоизображение

Для создания элементов управления вы задаете имя функции, которая должна выполняться в ответ на событие мыши, используя атрибут самого элемента управления видео. Намного более подробно обработка событий Silverlight с помощью JavaScript рассматривается в "Элемент управления браузера Silverlight" , "Элемент управления браузера Silverlight". Однако, в данном случае, просто требуется начать, остановить или приостановить воспроизведение видео, когда пользователь щелкнет соответствующий текстовый блок. Это реализуется путем обработки события MouseLeftButtonDown текстового блока, которое ассоциируется с функциями, воспроизводящими, приостанавливающими или останавливающими воспроизведение.

При программировании на JavaScript необходимо обеспечить, чтобы эти функции были доступны со страницы, на которой размещается элемент управления Silverlight. Итак, они могут быть реализованы либо путем использования элементов JavaScript на странице, либо в файле js, который включен в страницу с помощью элемента JavaScript, свойству Src которого задано соответствующее значение.

Если для сведения воедино содержимого XAML используется Expression Blend, он обеспечивает для Page.xaml псевдо-файл выделенного кода Page.xaml.js. Это идеальное место для реализации функциональности JavaScript.

Создадим проект Silverlight 1.0 Site. Далее представлен XAML, описывающий похожий UI, как был создан в предыдущем примере, но с объявлениями обработчиков событий:

<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="vid" Source="balls.wmv"
                Height="200" Width="200" Stretch="Fill" />
  <Canvas Canvas.Top="160">
    <Rectangle Fill="Black" Width="200" Height="24" Opacity="0.7"/>
    <TextBlock MouseLeftButtonDown="doPlay"
               Foreground="White"
               Canvas.Left="20">Play</TextBlock>
    <TextBlock MouseLeftButtonDown="doStop"
               Foreground="White"
               Canvas.Left="80">Stop</TextBlock>
    <TextBlock MouseLeftButtonDown="doPause"
               Foreground="White"
               Canvas.Left="140">Pause</TextBlock>
  </Canvas>
</Canvas>

Теперь можно написать кода на JavaScript для начала, остановки и приостановки воспроизведения. Вот этот код:

function doPlay(sender, args) 
{
  var meVid = sender.findName("vid");
  meVid.Play(); 
}
function doStop(sender, args) 
{
  var meVid = sender.findName("vid");
  meVid.Stop(); 
}
function doPause(sender, args) 
{
  var meVid = sender.findName("vid");
  meVid.Pause(); 
}

Когда функция JavaScript определяется как обработчик события, она должна принимать два параметра. Первый, sender, - это объект, который формирует событие. Второй, args, содержит аргументы, которые включаются как часть события.

Теперь в этой JavaScript-функции необходимо получить ссылку на объект MediaElement, управление которым осуществляется. Выполняется это с помощью метода findName объекта sender. Хотя отправителем является текстовый блок, который щелкнул пользователь, выполнение его метода findName все равно обеспечит выполнение поиска по всему XAML-документу до тех пор, пока не будет найден элемент vid (который был создан путем применения атрибута x:Name к нашему объекту MediaElement ). Если вернуться к XAML, можно увидеть, что в MediaElement был элемент x:Name со значением vid, так что поиск должен быть успешным. Ссылка на соответствующий объект MediaElement будет сохранена в переменной JavaScript meVid. Теперь для управления воспроизведением осталось просто вызывать методы Play, Stop или Pause для этого объекта.

При создании проекта приложения для Silverlight 2 и использовании .NET все даже еще проще: не надо использовать findName для доступа к элементу, и ему уже присвоено имя vid, так что код будет выглядеть так:

private void doPlay(object sender, MouseButtonEventArgs e) 
{
  vid.Play(); 
}
private void doPause(object sender, MouseButtonEventArgs e) 
{
  vid.Pause(); 
}
private void doStop(object sender, MouseButtonEventArgs e) 
{
  vid.Stop(); 
}

Управление буферизацией и загрузкой

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

Когда буфер полон на 100%, начинается воспроизведение. Воспроизведение может прерываться при изменении состояния связи и дозагрузки буфера. Silverlight позволяет отслеживать это поведение с помощью события BufferingProgressChanged (Показатель процесса буферизации изменился) и свойства BufferingProgress (Показатель процесса буферизации). Используя эти событие и свойство, можно показывать пользователям текущее состояние буферизации или выполнять логику для улучшения взаимодействия с пользователем (UX) как результат условий буферизации. Например, в условиях плохого соединения буферизация может не превышать 50%. Вы можете перехватить это значение и предоставить соответствующую обратную связь своему клиенту.

Для управления буферизацией задайте в MediaElement обработчик событий, определяющий функцию для обработки события BufferingProgressChanged:

<MediaElement x:Name="vid" Source="balls.wmv" Height="200" Width="200"
Stretch="Fill" Buffering Prog ressChanged = "doBuff"/> <TextBlock x:Name="txtBuff"></TextBlock>

Таким образом, функция doBuff будет выполняться каждый раз при изменении наполненности буфера. Это событие тесно связано со свойством BufferingProgress. Данное свойство принимает значения в диапазоне от 0 до 1, где 0 соответствует пустому буферу, и 1 - полному. Событие будет формироваться при изменении наполнения буфера на 5% (т.е. 0,05) или более и когда буфер заполнен полностью.

Далее представлен код, который может использоваться для ответа на это событие и обеспечения обратной связи о текущем состоянии буфера пользователям.

Сначала JavaScript-версия:

function doBuff(sender, args) 
{
  var theText = sender.findName("txtBuff");
  var meVid = sender.findName("vid");
  var prog = meVid.BufferingProgress * 100;
  prog = "Buffering % " + prog;
  theText.Text = prog; 
}

И вот, как это было бы сделано в выделенном коде .NET (на C#):

private void doBuff(object sender, RoutedEventArgs e) 
{
  double prog = vid.BufferingProgress * 100;
  txtBuff.Text = "Buffering % " + prog; 
}

Если у вас не видно текст с отображением буферизации в Silverlight-приложении, обратите внимание на используемый элемент компоновки. Если вы использовали <Grid>, текст может находиться под "кнопками" Play, Stop и Pause. В этом случае задайте для текстовых блоков небольшой отступ с помощью свойства Margin.

Можно переопределить автоматическую буферизацию, задавая конкретную продолжительность буферизованного видео. Например, если необходимо всегда иметь 10-секундный буфер видео и, таким образом, снизить риск прерывания воспроизведения из-за повторной синхронизации буфера при ухудшении состояния связи, можно задать свойство BufferingTime (Размер буфера). В качестве его значения задается временной диапазон. Так, например, чтобы задать 10-секундный буфер, BufferingTime задается значение 0:0:10, как показано в следующем примере:

<MediaElement x:Name="vid" Source="balls.wmv"
          Height="200" Width = "200" Stretch="Fill"
          BufferingProgressChanged = "doBuff"
          BufferingTime="0:0:10"/> 
<TextBlock x:Name="txtDown"></TextBlock>

Если прогрессивная загрузка недоступна или не поддерживается, придется загружать весь видеофайл целиком и только потом начинать его воспроизведение. В этом случае событие DownloadPro-gressChanged и свойство DownloadProgress могут использоваться для получения состояния загрузки. Принципы работы с ними аналогичны функциям буферизации. Дале представлен XAML, определяющий событие DownloadProgressChanged:

<MediaElement x:Name="vid" Source="balls.wmv"
           Height="200" Width="200" Stretch="Fill"
           BufferingProgressChanged = "doBuff"
           BufferingTime="0:0:10"
           DownloadProgressChanged = "doDown"/>
<TextBlock x:Name="txtDown"></TextBlock>

И теперь код функции doDown, обрабатывающей это событие. Опять же, сначала рассмотрим JavaScript-версию:

function doDown(sender, args) 
{
  var theText = sender.findName("txtDown");
  var meVid = sender.findName("vid");
  var prog = meVid.DownloadProgress * 100;
  prog = "Downloading % " + prog;
  theText.Text = prog; 
}

И BOT.NET-версия:

private void doDown(object sender, RoutedEventArgs e) 
{
 double prog = vid.DownloadProgress * 100;
 txtBuff.Text = "Downloading % " + prog;
}

Управление текущим состоянием видео

Silverlight представляет свойство CurrentState (Текущее состояние) и связанное с ним событие Cur-rentStateChanged (Текущее состояние изменилось), которое может использоваться для ответа на изменение состояния мультимедиа.

Действительными состояниями свойства CurrentState являются:

  • Buffering ( Буферизация ) Буфер не заполнен на 100%, поэтому воспроизведение приостановлено до полного заполнения буфера.
  • Closed ( Закрыто ) Мультимедиа закрыто.
  • Error ( Ошибка ) Возникла проблема с загрузкой, буферизацией или воспроизведением мультимедиа.
  • Opening ( Открывается ) Мультимедийный файл найден, и буферизация или загрузка должны вот-вот начаться.
  • Paused ( Приостановлено ) Воспроизведение приостановлено.
  • Playing ( Воспроизводится ) Идет воспроизведение мультимедиа.
  • Stopped ( Остановлено ) Воспроизведение остановлено.

Вот как событие CurrentStateChanged элемента управления MediaElement определяется в XAML:

<MediaElement x:Name="vid" Source="balls.wmv" 
          Height="200" Width="200" Stretch="Fill" 
          CurrentStateChanged= "doState" BufferingTime="0:0:10" />

Здесь задается функция doState, которая будет вызываться в ответ на изменение текущего состояния. Далее представлен пример такой JavaScript-функции, которая использует значение свойства Cur-rentState элемента управления MediaElement в окне уведомления:

function doState(sender, args) 
{
  var meVid = sender.findName("vid");
  alert(meVid.CurrentState); 
}

В C#, вместо окна уведомления MessageBox, для вывода содержимого свойства CurrentState на экран можно использовать TextBlock:

private void doState(object sender, RoutedEventArgs e) 
{
  txtBuff.Text = vid.CurrentState.ToString(); 
}