WPF/WinUI XAML TextBlock控件的C#从随机字母显示到文本显示效果

xzlaal3s  于 2022-12-07  发布在  C#
关注(0)|答案(1)|浏览(168)

我正在尝试在WinUI 3中创建一个基于TextBlock控件的自定义控件,该控件必须使用 * 随机字母滚动效果(逐个字母)* 显示所包含的文本,直到显示全部文本。让我们假设类似于机场出发广告牌...
为了更好地了解所需的效果,请使用Adobe After Effects制作this is a video
如何在C#代码中实现(最接近的)效果?

ki0zmccv

ki0zmccv1#

在我的解决方案中,动画是通过设置Text DependencyProperty来触发的。如果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;
    }
}

相关问题