2010-12-30 14 views
2

アニメーションがTextBlockです。 60秒では、FontSizeが8ptから200ptに増加します。テキストが大きくなるにつれてアニメーションが上下に動くことを除いて、すべてがうまくいきます。なぜこれが起こっており、これを避けることが可能ですか?WPF:アニメーションがスムーズでない

私は非常に単純なXAMLファイルを持っている:

<Window x:Class="Timer.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Width="800" 
     Height="500" 
     Title="MainWindow" 
     Loaded="Window_Loaded"> 

    <Grid> 

     <TextBlock 
      Name="TimerTextBlock" 
      HorizontalAlignment="Center" 
      VerticalAlignment="Center" 
      Text="00h : 00m : 00.000s" /> 

    </Grid> 

</Window> 

と同じように簡単なコードビハインド:

public partial class MainWindow : Window 
{ 
    private const string timerFormat = "{0:hh'h : 'mm'm : 'ss'.'fff's'}"; 
    private DispatcherTimer dispatcherTimer; 
    private DateTime targetTime; 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     targetTime = DateTime.Now.AddSeconds(60); 
     double totalTime = targetTime.Subtract(DateTime.Now).TotalMilliseconds; 

     DoubleAnimation animation = new DoubleAnimation(); 
     animation.From = TimerTextBlock.FontSize; 
     animation.To = 200; 
     animation.Duration = new Duration(targetTime.Subtract(DateTime.Now)); 
     TimerTextBlock.BeginAnimation(TextBlock.FontSizeProperty, animation); 

     dispatcherTimer = new DispatcherTimer(); 
     dispatcherTimer.Interval = TimeSpan.FromMilliseconds(1); 
     dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); 
     dispatcherTimer.Start(); 
    } 

    private void dispatcherTimer_Tick(object sender, EventArgs e) 
    { 
     if (DateTime.Compare(targetTime, DateTime.Now) > 0) 
     { 
      TimerTextBlock.Text = 
       string.Format(timerFormat, targetTime.Subtract(DateTime.Now)); 
     } 
    } 
} 

は、すべての明確化をありがとうございました。

+0

「ピクセル分割」の問題は間違いないと私は結論づけました。コントロールが2つのピクセルの間のどこかに描かれなければならない状況になると、ちょっとチョップするのが理にかなっています。しかし、何とかこれを避ける方法はありますか? – Boris

+0

私はインターネット上で答えを探していましたが、私はいくつかの "MatrixAnimations"に出くわしました。それは何ですか、それはトリックをすることができますか? (もしそうなら、どう?) – Boris

答えて

2

縦ジャンプの問題は、フォントレンダリングの丸めによるものです。具体的には、WPFはフォントスムージングを有効にするためにサブピクセルフォントの高さを避けます。これを回避する1つの方法は、テキストをパスジオメトリに変換し、スケール変換を使用してアニメーション化することです。

ジャンプのないサンプルの別のバージョンです。新しいXAMLは次のとおりです。

<Grid> 
    <Path Name="Path" HorizontalAlignment="Center" VerticalAlignment="Center"/> 
</Grid> 

、新しいコードウィンドウをロードするとき:

SetText(""); 
var transform = new ScaleTransform(1, 1); 
Path.LayoutTransform = transform; 
var animationX = new DoubleAnimation(1, 10, new Duration(TimeSpan.FromSeconds(60))); 
transform.BeginAnimation(ScaleTransform.ScaleXProperty, animationX); 
var animationY = new DoubleAnimation(1, 10, new Duration(TimeSpan.FromSeconds(60))); 
transform.BeginAnimation(ScaleTransform.ScaleYProperty, animationY); 

とanmiatedされるテキストを設定するための新しい方法:

private void SetText(string text) 
{ 
    var formatted = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Lucida Console"), 12, Brushes.Black); 
    Path.Data = formatted.BuildGeometry(new Point(0, 0)); 
    Path.Fill = Brushes.Black; 
} 

とあなたをタイマーイベントハンドラからSetTextを呼び出してください。

水平ジャンプを回避するには、固定長テキスト文字列と固定幅フォントを使用する必要があります。

+0

+1とてもいいです。テキストはスムーズにアニメートされますが、テキストが拡大するにつれてわずかなエイリアシングがあります。これは期待されていますか? –

+0

サブピクセルアンチエイリアスはアニメーションの滑らかさに欠かせないので、鮮明なテキストやスムーズなアニメーションがトレードオフです。 –

+0

いいです。あまりにもあなたは固定長のテキスト文字列と一定の幅のフォントに限られていますが、テキストを中央に揃える他の方法はありません。 – Boris

関連する問題