WPF:动画不流畅

时间:2010-12-30 02:10:33

标签: wpf animation

我正在制作TextBlock动画。在60秒内,它将FontSize从8pt增加到200pt。一切都运行正常,除了我的动画随着文本的增长而上下移动一点。为什么会发生这种情况,是否可以避免这种情况?

我有一个非常简单的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));
        }
    }
}

感谢您的所有澄清。

1 个答案:

答案 0 :(得分:2)

您的垂直跳跃问题是由字体渲染舍入引起的。具体来说,WPF将避免子像素字体高度,以启用字体平滑。避免这种情况的一种方法是将文本转换为路径几何体,然后使用缩放变换为其设置动画。

以下是没有跳转的示例的替代版本。新的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);

以及一种设置相关文本的新方法:

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。

请注意,为避免水平跳跃,您必须使用固定长度的文本字符串和恒定宽度的字体。