【问题标题】:How to create a smooth animated text marquee?如何创建平滑的动画文本选取框?
【发布时间】:2017-12-04 15:05:44
【问题描述】:

我知道关于水平文本动画/文本滚动有很多不同的主题,但不幸的是,它们都没有提供带有可重复文本的平滑滚动。我尝试过使用包含文本的各种 WPF 控件的双/厚度动画。还尝试使用视觉画笔制作动画,与其他方法相比,这给了我迄今为止最优雅的滚动(例如使用Canvas.Left 属性等),但如果文本长度或动画速度太高,那也会使文本模糊.

我已经完成了使用 SharpDX 库的纯 DirectX C# 实现。还应该提到我是 DirectX 编程的初学者。代码如下:

public void RunMethod()
{
    // Make window active and hide mouse cursor.
    window.PointerCursor = null;
    window.Activate();

    var str = "This is an example of a moving TextLayout object with no snapped pixel boundaries.";

    // Infinite loop to prevent the application from exiting.
    while (true)
    {
        // Dispatch all pending events in the queue.
        window.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessAllIfPresent);

        // Quit if the users presses Escape key.
        if (window.GetAsyncKeyState(VirtualKey.Escape) == CoreVirtualKeyStates.Down)
        {
            return;
        }

        // Set the Direct2D drawing target.
        d2dContext.Target = d2dTarget;

        // Clear the target. 
        d2dContext.BeginDraw();
        d2dContext.Clear(Color.CornflowerBlue);

        //float layoutXOffset = 0;
        float layoutXOffset = layoutX;

        // Create the DirectWrite factory objet.
        SharpDX.DirectWrite.Factory fontFactory = new SharpDX.DirectWrite.Factory();

        // Create a TextFormat object that will use the Segoe UI font with a size of 24 DIPs.
        textFormat = new TextFormat(fontFactory, "Verdana", 100.0f);

        textLayout2 = new TextLayout(fontFactory, str, textFormat, 2000.0f, 100.0f);

        // Draw moving text without pixel snapping, thus giving a smoother movement.
        // d2dContext.FillRectangle(new RectangleF(layoutXOffset, 1000, 1000, 100), backgroundBrush);
        d2dContext.DrawTextLayout(new Vector2(layoutXOffset, 0), textLayout2, textBrush, DrawTextOptions.NoSnap);

        d2dContext.EndDraw();

        //var character = str.Substring(0, 1);
        //str = str.Remove(0, 1);
        //str += character;
        layoutX -= 3.0f;

        if (layoutX <= -1000)
        {
            layoutX = 0;
        }

        // Present the current buffer to the screen.
        swapChain.Present(1, PresentFlags.None);
    }
}

基本上它会创建一个无限循环并减去水平偏移量。以下是挑战:我需要类似于 HTML marquee 的可重复文本,没有任何间隙,可能需要将其扩展到多个显示器。

请提出建议。

【问题讨论】:

    标签: c# wpf directx sharpdx wpf-animation


    【解决方案1】:

    DirectX和sharpdx我都不知道怎么用,但是如果你想你可以考虑这个解决方案

    前段时间我遇到了类似的问题,但文本位于组合框中。赏金后,我得到了我想要的东西。我以发布相关代码为例,但您可以查看完整答案here

    基本上,只要您有一个包含无法完全显示的字符串的文本块/文本框,导致长度超过文本块/框的长度,您就可以使用这种方法。您可以定义一个从您需要的基础派生的自定义用户控件(例如 SlidingComboBox : Combobox),并为您的故事板定义一个动画,如下所示

    _animation = new DoubleAnimation()
     {
          From = 0,
          RepeatBehavior = SlideForever ? RepeatBehavior.Forever : new RepeatBehavior(1), //repeat only if slide-forever is true
          AutoReverse = SlideForever
     };
    

    在我的示例中,我希望此行为仅在鼠标位于组合框上时才处于活动状态,因此在我的自定义 OnMouse 输入中我有这段代码

    if (_parent.ActualWidth < textBlock.ActualWidth)
    {
         _animation.Duration = TimeSpan.FromMilliseconds(((int)textBlock.Text?.Length * 100));
         _animation.To = _parent.ActualWidth - textBlock.ActualWidth;
         _storyBoard.Begin(textBlock);
    }
    

    其中 _parent 表示所选项目的容器。在检查文本长度与组合框长度后,我开始动画并在要显示的文本末尾结束它

    请注意,在我提到的问题中,还有其他解决方案。我正在发布对我有用的那个

    【讨论】:

    • 所以,我现在把它搅成很小的一块。在我更改文本长度和持续时间后,它开始闪烁。此外,文本应该是可重复的,没有任何间隙,没有反向选项。
    • @adhiman 好吧,我不知道您所说的“闪烁”是什么意思。然而,对于可重复的文本,事情变得更加复杂,因为我不知道如何做到这一点。我唯一想到的是创建另一个名为“显示文本”的属性,它将存储 N 次重复文本,以便您可以模拟循环效果
    猜你喜欢
    • 2011-03-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多