[英]C# From random letters displaying to a text reveal effect for WPF/WinUI XAML TextBlock control
我正在尝试基于TextBlock
控件在WinUI 3中创建一个自定义控件,该控件必须使用随机字母滚动效果(逐个字母)显示包含的文本,直到显示全文。 比如说机场出发广告牌……
为了更好地理解所需的效果,这是一个使用 Adobe After Effects 制作所需结果的视频。
如何在 C# 代码中实现(最接近的)效果?
在我的解决方案中,通过设置 Text DependencyProperty 触发 animation。 如果在当前 animation 期间覆盖 Text 属性,则可以轻松重新启动效果。 但是你也可以通过一些公共方法来触发它。 但请记住,TextBlock 控件可能会因大量文本和快速文本更改而变慢。 如果您遇到性能问题,您应该为 Win2D CanvasControl 重写它。
LetterRevealTextBlock.xaml:
<UserControl
x:Class="Test.WinUI3.LetterRevealTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Test.WinUI3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<TextBlock x:Name="LRTB" FontFamily="Consolas"/>
</UserControl>
LetterRevealTextBlock.xaml.cs:
namespace Test.WinUI3;
public sealed partial class LetterRevealTextBlock : UserControl
{
private static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(LetterRevealTextBlock), new PropertyMetadata("", (d, e) => ((LetterRevealTextBlock)d).TextChanged(d, e)));
public string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
private static readonly DependencyProperty ScrollIntervalProperty = DependencyProperty.Register(
"ScrollInterval", typeof(int), typeof(LetterRevealTextBlock), new PropertyMetadata(40, (d, e) => ((LetterRevealTextBlock)d).ScrollIntervalChanged(d, e)));
public int ScrollInterval { get => (int)GetValue(ScrollIntervalProperty); set => SetValue(ScrollIntervalProperty, value); }
private static readonly DependencyProperty RevealIntervalProperty = DependencyProperty.Register(
"RevealInterval", typeof(int), typeof(LetterRevealTextBlock), new PropertyMetadata(200, (d, e) => ((LetterRevealTextBlock)d).RevealIntervalChanged(d, e)));
public int RevealInterval { get => (int)GetValue(RevealIntervalProperty); set => SetValue(RevealIntervalProperty, value); }
const string Chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
private Random Random = new Random();
private char[] TextArray {get; set; }
private int CurrentChar = 0;
private DispatcherTimer RevealTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(200) };
private DispatcherTimer ScrollTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(40) };
private void ScrollIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ScrollTimer.Interval = TimeSpan.FromMilliseconds((int)e.NewValue);
}
private void RevealIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RevealTimer.Interval = TimeSpan.FromMilliseconds((int)e.NewValue);
}
private void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextArray = (e.NewValue as string).ToCharArray();
CurrentChar = 0;
ScrollTimer.Start();
RevealTimer.Start();
}
private void ScrollTimer_Tick(object sender, object e)
{
for (int i = 0; i < Text.Length; i++)
{
if (i <= CurrentChar)
{
TextArray[i] = Text[i];
}
else
{
TextArray[i] = Text[i] == ' ' ? ' ' : Chars[Random.Next(Chars.Length - 1)];
}
}
LRTB.Text = new string(TextArray);
if (CurrentChar >= Text.Length - 1)
{
CurrentChar = 0;
ScrollTimer.Stop();
RevealTimer.Stop();
return;
}
}
private void RevealTimer_Tick(object sender, object e)
{
CurrentChar++;
}
public LetterRevealTextBlock()
{
this.InitializeComponent();
ScrollTimer.Tick += ScrollTimer_Tick;
RevealTimer.Tick += RevealTimer_Tick;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.