XAML
<Window Background="Black" Loaded="CharacterRainWindow_OnLoaded" >
<StackPanel
x:Name="RootStackPanel"
Background="Black" Orientation="Horizontal" TextElement.Foreground=" LightGreen" />
</Window>
代码
// 创建一列字符及对应的动画
private static Storyboard[] CreateStoryBoards(Panel rootGrid, char[] chars, int length)
{
// 保存一列的面板
var panel = new StackPanel
{
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Left,
Margin = new Thickness(3, 0, 3, 0),
};
rootGrid.Children.Add(panel);
// 创建列字符并加入面板
var textBlocks = CreateTextBlocks(panel, chars, length);
// 每一列开始的时间
var baseBeginTime = Random.Shared.NextDouble() * 5000;
// 创建字符对应的动画
var storyboards = CreateStoryBoards(textBlocks, baseBeginTime);
return storyboards;
}
private static Storyboard[] CreateStoryBoards(TextBlock[] textBlocks, double baseBeginTime)
{
DoubleAnimation animation = new()
{
From = 0,
To = 1,
Duration = new Duration(TimeSpan.FromSeconds(3)),
// AutoReverse = true,
RepeatBehavior = RepeatBehavior.Forever,
};
var ls = new List<Storyboard>();
for (var idx = 0; idx < textBlocks.Length; idx++)
{
var copy = animation.Clone();
copy.BeginTime = TimeSpan.FromMilliseconds( baseBeginTime + 100d * idx);
Storyboard storyboard = new();
storyboard.Children.Add(copy);
var textBlock = textBlocks[idx];
Storyboard.SetTarget(copy, textBlock);
Storyboard.SetTargetProperty(copy, new PropertyPath(OpacityProperty));
ls.Add(storyboard);
}
return ls.ToArray();
}
private static TextBlock[] CreateTextBlocks(StackPanel panel, char[] chars, int length)
{
var textBlocks = Enumerable.Range(0, length).Select(_ =>
{
TextBlock textBlock = new()
{
Text = $"{chars[Random.Shared.Next(chars.Length)]}",
FontSize = TextElement.GetFontSize(panel),
FontFamily = TextElement.GetFontFamily(panel),
Foreground = TextElement.GetForeground(panel),
Opacity = 0,
};
return textBlock;
}).ToArray();
Array.ForEach(textBlocks, textBlock => panel.Children.Add(textBlock));
return textBlocks;
}
private void CharacterRainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
var rootGrid = this.RootStackPanel;
// 用来生成的字符
var chars = "观自在菩萨行深般若波罗蜜多时照见五蕴皆空度一切苦厄舍利子色不异空空不异色色即是空空即是色".ToArray();
_ = Enumerable.Range(0, 50).Select(it =>
{
return Task.Run(() =>
{
// 调用一次生成一列字符
this.Dispatcher.BeginInvoke(() =>
{
var storyboards = CreateStoryBoards(rootGrid, chars, 50);
Array.ForEach(storyboards, storyboard => storyboard.Begin());
}, DispatcherPriority.ApplicationIdle);
});
}).ToArray();
// 字符整体缓缓显示
var animation = new DoubleAnimation
{
From = 0,
To = 1,
Duration = new Duration(TimeSpan.FromSeconds(5)),
};
rootGrid.BeginAnimation(OpacityProperty, animation);
}