我正在开发Windows Store 8.1 App项目,并希望创建自定义进度条/仪表控件。该类在内部测量一些值并将其显示为文本和进度条/仪表。价值变化应该是动画的:
public class CustomGauge : UserControl{
private static readonly DependencyProperty SpeedProperty = DependencyProperty.Register("Speed", typeof(double), typeof(CustomGauge), new PropertyMetadata(null, new PropertyChangedCallback(SpeedChanged)));
private double Speed{
get { return (double)GetValue(SpeedProperty ); }
set { SetValue(SpeedProperty , value); }
}
// In CustomGauge.xaml a TextBlock uses a Binding to Speed to display the value
private static void SpeedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
CustomGauge gauge = d as CustomGauge;
if (gauge != null)
gauge.DrawSpeed();
}
private void OnSpeedChanged(double newSpeedValue) {
DoubleAnimation animation = new DoubleAnimation();
animation.EnableDependentAnimation = true;
animation.Duration = new Duration(TimeSpan.FromSeconds(1.5));
animation.To = newSpeedValue;
PowerEase easing = new PowerEase();
easing.Power = 5.0;
easing.EasingMode = EasingMode.EaseOut;
animation.EasingFunction = easing;
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(animation);
Storyboard.SetTarget(animation, this);
Storyboard.SetTargetProperty(animation, "Speed");
storyboard.Begin();
}
private void DrawSpeed() {
...
}
}
虽然使用绑定到“速度”的XAML文本块的文本是动画的,但是仪表/进度条只是从旧值跳转到没有动画的新值。这是因为SpeedChanged(...)仅使用新值调用一次,而不是从旧值到新值调用动画的每个中间值。
我该如何解决这个问题,并使用动画来改变仪表/进度条?
答案 0 :(得分:0)
您可以做的一件事是为动画创建“步长”和“步时”。它将获取给定的值,找出差异,并将差异切割成块,为每个块制作动画。
注意:我使用WinRTXamlToolkit作为他们真棒StoryBoard Extensions。这可能是不必要的,如果你选择不整合整个库,很容易添加一个扩展。
// Set this to something sensible for your speeds.
// You may want to have it be calculated on the fly,
// Such as by doing an even distribution of steps,
// Possibly with a minimum value for a step to be. Up to you.
private const double StepSize = 5;
private const double StepTime = 1.5;
private async void OnSpeedChanged(double newSpeedValue) {
DoubleAnimation animation = new DoubleAnimation();
animation.EnableDependentAnimation = true;
PowerEase easing = new PowerEase();
easing.Power = 5.0;
easing.EasingMode = EasingMode.EaseOut;
animation.EasingFunction = easing;
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(animation);
Storyboard.SetTarget(animation, this);
Storyboard.SetTargetProperty(animation, "Speed");
// You may want to have this be an absolute value and store the sign
// in case there is both a positive and negative change in speed
var difference = newSpeedValue - Speed;
for(double stepValue = Speed + StepSize; i < difference; i += StepSize)
{
animation.Duration = new Duration(TimeSpan.FromSeconds(StepTime));
animation.To = stepValue;
await storyboard.BeginAsync();
}
// do the last one
animation.Duration = new Duration(TimeSpan.FromSeconds(StepTime));
animation.To = newSpeedValue;
await storyboard.BeginAsync();
}
最后要注意的是我已经使OnSpeedChanged异步。对于SpeedChanged方法,它只是“设置并忘记它”,因为它会调用它并立即继续。如果你的速度经常变化,你需要做一些链接效果,比如用CancellationToken取消最后的动画。另一种选择是保持正在运行的动画任务的队列并按顺序运行它们。出于多种原因,这可能是也可能不是一个好主意。
希望这有助于编码!