Отслеживание хода анимации

99

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

Отображение позиции и хода анимации

Добавить эти элементы достаточно просто. Сначала нужен элемент Label, чтобы показать время, и элемент управления ProgressBar для отображения графической панели. Может показаться, что значение TextBlock и содержимое ProgressBar следует устанавливать с помощью выражения привязки данных, однако это не так. Дело в том, что единственный способ получения информации о текущем состоянии анимации от Storyboard заключается в применении таких методов, как GetCurrentTime() и GetCurrentProgress(). Нет никакой возможности получить ту же информацию через свойства.

Простейшее решение предполагает реакцию на одно из событий раскадровки, перечисленных ниже:

Completed

Анимация достигла конечной точки

CurrentGlobalSpeedInvalidated

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

CurrentStateInvalidated

Анимация запустилась или завершилась

CurrentTimeInvalidated

Таймер анимации переместился вперед на инкремент, изменяя анимацию. Это событие также случается, когда анимация запускается, останавливается или завершается.

RemoveRequested

Анимация удалена. Анимируемое свойство будет впоследствии возвращено в исходное значение.

В рассматриваемой ситуации необходимым событием является CurrentTimeInvalidated, которое инициируется при всяком продвижении таймера вперед. (Обычно это происходит 60 раз в секунду, но если код требует больше времени на выполнение, некоторые "тики" таймера могут быть потеряны.)

Когда возникает событие CurrentTimeInvalidated, отправителем является объект Clock (из пространства имен System.Windows.Media.Animation). Объект Clock позволяет получить текущее время в виде TimeSpan и текущий показатель хода анимации, как значение между 0 и 1.

Ниже приведен код, который обновляет метку и панель прохождения:

private void MyStoryboard_CurrentTimeInvalidated(object sender, EventArgs e)
    {
        Clock cl = (Clock)sender;
        if (cl.CurrentProgress == null)
        {
            lblTime.Foreground = new SolidColorBrush(Colors.Red);
            lblTime.Content = "stop";
            prgBar.Value = 0;
        }
        else
        {
            lblTime.Foreground = new SolidColorBrush(Colors.Black);
            lblTime.Content = cl.CurrentTime.ToString();
            prgBar.Value = 100*(double)cl.CurrentProgress;
        }
   }

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

Пройди тесты
Лучший чат для C# программистов