繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM