четверг, 24 ноября 2011 г.

Анимация времени

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

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

Публикую здесь исходный код класса, может быть кому-нибудь пригодится.

/// <summary>
/// Класс анимации типа DateTime
/// </summary>
public class DateTimeAnimation : AnimationTimeline
{
    public static readonly DependencyProperty FromProperty = 
           DependencyProperty.Register("From",
           typeof(DateTime), typeof(DateTimeAnimation));
 
    public static readonly DependencyProperty ToProperty = 
           DependencyProperty.Register("To",
           typeof(DateTime), typeof(DateTimeAnimation));
 
    /// <summary>
    /// Получает или задает начальное значение анимации
    /// </summary>
    public DateTime From
    {
        get { return (DateTime)this.GetValue(FromProperty); }
        set { this.SetValue(FromProperty, value); }            
    }
 
    /// <summary>
    /// Получает или задает конечное значение анимации
    /// </summary>
    public DateTime To
    {
        get { return (DateTime)this.GetValue(ToProperty); }
        set { this.SetValue(ToProperty, value); }
    }
 
    /// <summary>
    /// Возвращает значение, указывающие, используется ли в этой анимации параметр
    /// defaultDestinationValue метода GetCurrentValue как ее конечное значение
    /// </summary>
    public override bool IsDestinationDefault
    {
        get { return true; }
    }
 
    /// <summary>
    /// Возвращает тип значения, создаваемого данной анимацией
    /// </summary>
    public override Type TargetPropertyType
    {
        get { return typeof(DateTime); }
    }
 
    //////////////////////////////////////////////////////////////////////////
        
    protected override Freezable CreateInstanceCore()
    {
        Contract.IsFalse(From == DateTime.MinValue);
        Contract.IsFalse(To == DateTime.MinValue);
        return new DateTimeAnimation();
    }
 
    public override Object GetCurrentValue(Object defaultOriginValue,
                                           Object defaultDestinationValue,
                                           AnimationClock animationClock)
    {
        Contract.IsNotNull(animationClock);
        if (animationClock.CurrentProgress == null)
            return From;
        double commonDelta = (To - From).TotalDays;
        double curDelta = (double)animationClock.CurrentProgress * commonDelta;
        return From.AddDays(curDelta);
    }
 
} /// class DateTimeAnimation

Комментариев нет:

Отправить комментарий