Отслеживание хода анимации
99WPF --- Графика и анимация WPF --- Отслеживание хода анимации
Проигрывателю анимации, разобранному в предыдущей статье, все еще не хватает одного средства, которое присутствует в большинстве проигрывателей медиа, а именно: возможности определения текущей позиции. Чтобы сделать его более забавным, можно добавить некоторый текст, который показывает временное смещение, и панель прохождения, предоставляющую визуальную индикацию хода анимации. Ниже показан усовершенствованный проигрыватель анимации с обеими деталями (вместе с ползунком для управления скоростью, о котором речь шла в предыдущей статье):
Добавить эти элементы достаточно просто. Сначала нужен элемент 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, как показано в этом примере.