【问题标题】:WPF: Animation is not smoothWPF:动画不流畅
【发布时间】:2014-02-01 11:50:54
【问题描述】:

我正在为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));
        }
    }
}

感谢您的所有澄清。

【问题讨论】:

  • 我得出结论,这绝对是“像素分割”的问题。切一点是有意义的,因为控件处于必须在两个像素之间的某个位置绘制的情况。但是,有没有办法以某种方式避免这种情况?
  • 我一直在网上寻找答案,发现了一些“MatrixAnimations”。那是什么,它可以解决问题吗? (如果是,怎么做?)

标签: wpf animation


【解决方案1】:

您的垂直跳跃问题是由于字体渲染四舍五入造成的。具体来说,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。

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

【讨论】:

  • + 1 非常好。文本现在动画流畅,但是,随着文本的增长,文本会出现轻微的锯齿。这是预期的吗?
  • 亚像素抗锯齿对于动画的流畅度至关重要,因此需要权衡:清晰的文本或流畅的动画。
  • 不错的一个。太糟糕了,您仅限于固定长度的文本字符串和等宽的字体,但是没有其他方法可以使文本居中对齐。
  • 或者,如果文本在动画过程中没有改变,任何字符串和任何字体都可以(或缓慢改变)。
猜你喜欢
  • 2014-10-30
  • 2017-03-02
  • 2010-11-07
  • 2017-07-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-17
  • 2018-07-28
  • 2015-11-28
相关资源
最近更新 更多