我正在制作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));
}
}
}
感谢您的所有澄清。
答案 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。
请注意,为避免水平跳跃,您必须使用固定长度的文本字符串和恒定宽度的字体。