2009-06-14 83 views
4

我在地圖上爲'比賽'製作動畫。比賽需要45分鐘,但動畫運行60秒。使用Silverlight的DispatcherTimer - 有沒有更好的方法(動畫DependencyProperty)?

你可以看2008 City2Surf race demo看看我的意思。

在左上角的「種族時鐘」必須顯示「實時」,並且必須是建立在.xaml.csSystem.Windows.Threading.DispatcherTimer似乎有點一個黑客攻擊的。

我想也許有會是上的動畫,而不是僅僅StoryBoard.GetCurrentTime()一個DependencyProperty,而是我不得不

  // SET UP AND START TIMER, before StoryBoard.Begin() 
     dt = new System.Windows.Threading.DispatcherTimer(); 
     dt.Interval = new TimeSpan(0, 0, 0, 0, 100); // 0.1 second 
     dt.Tick +=new EventHandler(dt_Tick); 
     winTimeRatio = (realWinTime.TotalSeconds * 1.0)/animWinTime.TotalSeconds; 
     dt.Start(); 

然後Tick事件處理

void dt_Tick(object sender, EventArgs e) 
    { 
     var sb = LayoutRoot.Resources["Timeline"] as Storyboard; 
     TimeSpan ts = sb.GetCurrentTime(); 
     TimeSpan toDisplay = new TimeSpan(0,0, 
       Convert.ToInt32(ts.TotalSeconds * winTimeRatio)); 
     RaceTimeText.Text = toDisplay.ToString(); 
    } 

這工作和似乎表現良好 - 但我的問題是:我是否在Silverlight動畫/故事板類中丟失了一些可以更加整潔的東西?我必須記得停止的DispatcherTimer呢!

或者以另一種方式提出問題:對TextBox內容(.Text本身,而不是位置/尺寸/等)的「動畫」有什麼更好的建議?

+0

我喜歡比賽的形象化。做得好。 – caryden 2009-08-04 19:05:48

回答

5

這是一種方法。這很好,很簡單,但有點混亂。你可以擺脫故事板,並在每個滴答,增加一個本地值的滴答間隔,並用它來設置你的時間。你將只有一個時間片。

或...更優雅和可重用的方法是創建一個輔助類,它是一個DependencyObject。我還會使用一個帶有DoubleAnimation的StoryBoard,並將Storyboard.Target綁定到DoubleTextblockSetter的一個實例。將故事板持續時間設置爲您的時間,並將該值設置爲以秒爲單位的時間。這裏是DoublerBlockSetterCode。

public class DoubleTextBlockSetter : DependencyObject 
{ 
    private TextBlock textBlock { get; private set; } 
    private IValueConverter converter { get; private set; } 
    private object converterParameter { get; private set; } 

    public DoubleTextBlockSetter(
       TextBlock textBlock, 
       IValueConverter converter, 
       object converterParameter) 
    { 
     this.textBlock = textBlock; 
     this.converter = converter; 
     this.converterParameter = converterParameter; 
    } 

    #region Value 

    public static readonly DependencyProperty ValueProperty = 
     DependencyProperty.Register(
      "Value", 
      typeof(double), 
      typeof(DoubleTextBlockSetter), 
      new PropertyMetadata(
       new PropertyChangedCallback(
        DoubleTextBlockSetter.ValuePropertyChanged 
       ) 
      ) 
     ); 

    private static void ValuePropertyChanged(
     DependencyObject obj, 
     DependencyPropertyChangedEventArgs args) 
    { 
     DoubleTextBlockSetter control = obj as DoubleTextBlockSetter; 
     if (control != null) 
     { 
      control.OnValuePropertyChanged(); 
     } 
    } 

    public double Value 
    { 
     get { return (double)this.GetValue(DoubleTextBlockSetter.ValueProperty); } 
     set { base.SetValue(DoubleTextBlockSetter.ValueProperty, value); } 
    } 

    protected virtual void OnValuePropertyChanged() 
    { 
     this.textBlock.Text = this.converter.Convert(
      this.Value, 
      typeof(string), 
      this.converterParameter, 
      CultureInfo.CurrentCulture) as string; 
    } 

    #endregion 
} 

那麼你可能有一個格式轉換器:

public class TicksFormatConverter : IValueConverter 
{ 
    TimeSpanFormatProvider formatProvider = new TimeSpanFormatProvider(); 

    public object Convert(object value, 
     Type targetType, 
     object parameter, 
     CultureInfo culture) 
    { 
     long numericValue = 0; 

     if (value is int) 
     { 
      numericValue = (long)(int)value; 
     } 
     else if (value is long) 
     { 
      numericValue = (long)value; 
     } 
     else if (value is double) 
     { 
      numericValue = (long)(double)value; 
     } 
     else 
      throw new ArgumentException("Expecting type of int, long, or double."); 

     string formatterString = null; 
     if (parameter != null) 
     { 
      formatterString = parameter.ToString(); 
     } 
     else 
     { 
      formatterString = "{0:H:m:ss}"; 
     } 

     TimeSpan timespan = new TimeSpan(numericValue); 

     return string.Format(this.formatProvider, formatterString, timespan); 
    } 

    public object ConvertBack(
     object value, 
     Type targetType, 
     object parameter, 
     CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

我差點忘了TimespanFormatProvider。 Silverlight中沒有時間範圍的格式提供程序,因此它顯示。

public class TimeSpanFormatProvider : IFormatProvider, ICustomFormatter 
{ 
    public object GetFormat(Type formatType) 
    { 
     if (formatType != typeof(ICustomFormatter)) 
      return null; 
     return this; 
    } 

    public string Format(string format, object arg, IFormatProvider formatProvider) 
    { 
     string formattedString; 

     if (arg is TimeSpan) 
     { 
      TimeSpan ts = (TimeSpan)arg; 
      DateTime dt = DateTime.MinValue.Add(ts); 
      if (ts < TimeSpan.FromDays(1)) 
      { 
       format = format.Replace("d.", ""); 
       format = format.Replace("d", ""); 
      } 

      if (ts < TimeSpan.FromHours(1)) 
      { 
       format = format.Replace("H:", ""); 
       format = format.Replace("H", ""); 
       format = format.Replace("h:", ""); 
       format = format.Replace("h", ""); 
      } 

      // Uncomment of you want to minutes to disappear below 60 seconds. 
      //if (ts < TimeSpan.FromMinutes(1)) 
      //{ 
      // format = format.Replace("m:", ""); 
      // format = format.Replace("m", ""); 
      //} 

      if (string.IsNullOrEmpty(format)) 
      { 
       formattedString = string.Empty; 
      } 
      else 
      { 
       formattedString = dt.ToString(format, formatProvider); 
      } 
     } 
     else 
      throw new ArgumentNullException(); 

     return formattedString; 
    } 
} 

所有這些東西都是可重用的,並且應該存在於您的工具箱中。我把它從我的手中抽出來。然後,當然,你線它一起:

Storyboard sb = new Storyboard(); 
DoubleAnimation da = new DoubleAnimation(); 
sb.Children.Add(da); 
DoubleTextBlockSetter textBlockSetter = new DoubleTextBlockSetter(
    Your_TextBlock, 
    new TicksFormatConverter(), 
    "{0:m:ss}"); // DateTime format 

Storyboard.SetTarget(da, textBlockSetter); 

da.From = Your_RefreshInterval_Secs * TimeSpan.TicksPerSecond; 
da.Duration = new Duration(
    new TimeSpan(
     Your_RefreshInterval_Secs * TimeSpan.TicksPerSecond)); 
sb.begin(); 

這應該做的伎倆。它只有一百萬行代碼。而我們甚至還沒有寫出Hello World ......;)我沒有編譯它,但是我直接從我的庫中複製並粘貼了3個類。我用過它們很多。它效果很好。我也將這些類用於其他事情。 TickFormatConverter在數據綁定時派上用場。我也有一個能做秒的人。很有用。 DoubleTextblockSetter允許我動畫數字,這非常有趣。尤其是當您應用不同類型的插值。

享受。

+0

哇很全面的回答!我會試試看看我是怎麼走的...... – Conceptdev 2009-06-18 10:13:11

相關問題